Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Agent 365-exportören kräver en tokenlösare för autentisering vid export av telemetri. Denna guide behandlar installation för agenter byggda med SDK för Microsoft 365-agenter, och omfattar både agenter med Agent 365-stöd och anpassade agenter för .NET, Python och Node.js.
För distroinstallation, allmän konfiguration och scenarier som inte använder Agent SDK, se Microsoft OpenTelemetry Distro.
Översikt
Det finns fyra autentiseringsscenarier, beroende på din agenttyp och hur den hämtar tokens. Tokenhämtning kan använda On-Behalf-Of-flödet (OBO) eller Service-to-Service (S2S). Välj det scenario som matchar din konfiguration:
| Scenario | beskrivning |
|---|---|
| Agent 365-aktiverad med OBO-flöde | Distributionens inbyggda AgenticTokenCache hanterar tokenhämtning automatiskt. Ingen anpassad resolver behövs. Detta är det rekommenderade tillvägagångssättet för Agent 365-aktiverade agenter. |
| Agent 365-aktiverad med S2S-flöde | Agenten hämtar en token genom att använda den agentiska identitetskedjan (getAgenticApplicationToken + Microsoft Authentication Libraries (MSAL)). Kräver en anpassad TokenResolver. Använd denna metod när OBO saknas eller när du behöver app-baserade tokens. |
| Anpassad motor med OBO | Agenten får en användartoken via Azure Bot OAuth, begränsad till observabilitets-API:et. Kräver en anpassad TokenResolver och en Azure Bot OAuth-anslutning. |
| Anpassad motor med S2S | Agenten hämtar en app-only-token med hjälp av klientuppgifter. Kräver en anpassad TokenResolver. Appregistreringen måste vara en standard (icke-agentisk) app. |
Agent 365-aktiverad med OBO-flöde
Agent 365-aktiverade agenter tar emot förfrågningar med agentidentitet (agenticAppId, agenticUserId) från Agent 365-plattformen. När OBO används hanterar distributionens inbyggda AgenticTokenCache tokenhämtning automatiskt: ingen egen tokenresolver behövs.
Krav
- Entra-appregistrering : En service principal (appregistrering) med klient-ID, klienthemlighet och hyresgäst-ID
-
Delegerade API-behörigheter : Lägg till
Agent365.Observability.OtelWrite(delegerade), ge administratörssamtycke. För detaljerade steg, se Bevilja tillståndet.
Inställningar
Vid varje tur anropar din agent funktionen RegisterObservability med turens kontext. Den inbyggda cachen använder användarens delegerade token från AgenticUserAuthorization-hanteraren för att utföra ett OBO-utbyte och erhålla en token med scope för Agent365.Observability.OtelWrite.
För kompletta installationsinstruktioner inklusive paket, konfiguration och kodexempel, se Agentic token cache för Agent Framework-appar.
Agent 365-aktiverad med S2S-flöde:
Agent 365-aktiverade agenter kan också använda S2S (service-to-service) autentisering istället för OBO. Agenten hämtar en åtkomsttoken med sin egen service principal-identitet via en tvåstegs agentisk identitetskedja:
-
getAgenticApplicationToken(tenantId, agentId): klientuppgifter + Federated Managed Identity (FMI)-väg - MSAL
acquireTokenForClientmed app-token somclientAssertionoch scopeapi://9b975845-388f-4429-889e-eab1ef63949c/.default
Kommentar
Federerad hanterad identitet (FMI) är en arkitektur där en hanterad identitet deltar i arbetsbelastningsidentitetsfederation via federerade identitetsuppgifter, vilket möjliggör tokenutbyte och autentisering utan hemligheter baserat på förtroenderelationer mellan identiteter.
Du måste tillhandahålla en anpassad TokenResolver och konfigurera UseS2SEndpoint = true.
Krav
Entra-appregistrering : En service principal (appregistrering) med klient-ID, klienthemlighet och hyresgäst-ID
API-behörigheter för applikationen : Lägg till
Agent365.Observability.OtelWrite(Applikation), bevilja administratörssamtyckeAgent365.Observability.OtelWriteapplikationsroll : Agentens servicehuvudkonto måste haOtelWriterollen tilldelad på Agent365 Observability-resursen. Använd Agent 365 CLI:a365 setup permissions bot --config-dir "<path-to-config-dir>"Kommentar
Rollpropageringen kan ta några minuter. Initiala 401- eller 403-fel från exportändpunkten förväntas under denna period.
Steg 1: Miljökonfiguration
Följande kodexempel visar hur man ställer in de nödvändiga anslutnings-, tenant-, klientuppgifts- och observabilitetsexportörens miljövariabler innan den anpassade S2S-tokenflödet aktiveras.
Ingen AgenticUserAuthorization hanterare behövs. S2S använder den manuella agentiska identitetskedjan (get_agentic_application_token + MSAL acquire_token_for_client) för att hämta en token med scope för observabilitetsresursen.
CONNECTIONSMAP__0__SERVICEURL=*
CONNECTIONSMAP__0__CONNECTION=SERVICE_CONNECTION
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=<your-client-id>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=<your-client-secret>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=<your-tenant-id>
ENABLE_A365_OBSERVABILITY=true
ENABLE_A365_OBSERVABILITY_EXPORTER=true
Steg 2: Konfigurera distributionen med en anpassad tokenresolver
Följande exempel visar hur du aktiverar exportering av Agent 365 och registrerar en anpassad TokenResolver så att exportören kan hämta S2S-tokens för varje agent och hyresgäst.
from microsoft.opentelemetry import use_microsoft_opentelemetry
_token_cache: dict[str, str] = {}
def token_resolver(agent_id: str, tenant_id: str) -> str | None:
return _token_cache.get(f"{agent_id}:{tenant_id}")
use_microsoft_opentelemetry(
enable_a365=True,
a365_token_resolver=token_resolver,
a365_use_s2s_endpoint=True,
a365_enable_observability_exporter=True,
)
Steg 3: Hämta och lagra S2S-token i cache
Vid varje inkommande meddelande hämtar du S2S-token via den agentiska identitetskedjan och cacklar den för resolvern.
import asyncio
from msal import ConfidentialClientApplication
from microsoft.opentelemetry.a365.core import BaggageBuilder, InvokeAgentScope, InvokeAgentScopeDetails, Request
OBSERVABILITY_S2S_SCOPE = "api://9b975845-388f-4429-889e-eab1ef63949c/.default"
async def get_agentic_s2s_token(connection, tenant_id: str, agent_id: str) -> str:
# Step 1: Get agentic application token (client_credentials + fmi_path)
app_token = await connection.get_agentic_application_token(tenant_id, agent_id)
if not app_token:
raise ValueError(f"Failed to get agentic app token for agent {agent_id}")
# Step 2: Exchange for observability-scoped token
cca = ConfidentialClientApplication(
client_id=agent_id,
authority=f"https://login.microsoftonline.com/{tenant_id}",
client_credential={"client_assertion": app_token},
)
result = await asyncio.to_thread(
lambda: cca.acquire_token_for_client(scopes=[OBSERVABILITY_S2S_SCOPE])
)
if not result or "access_token" not in result:
raise ValueError(f"Token acquisition failed: {result}")
return result["access_token"]
# In your message handler : use SDK helpers to get agent/tenant from the activity:
@AGENT_APP.activity("message")
async def on_message(context: TurnContext, _state: TurnState):
# get_agentic_instance_id reads from recipient (SDK convention)
agent_id = context.activity.get_agentic_instance_id()
tenant_id = context.activity.get_agentic_tenant_id()
# Acquire S2S token and cache BEFORE creating spans
connection = CONNECTION_MANAGER.get_connection("SERVICE_CONNECTION")
token = await get_agentic_s2s_token(connection, tenant_id, agent_id)
_token_cache[f"{agent_id}:{tenant_id}"] = token
# Wrap spans in BaggageBuilder so the exporter can resolve the token
request = Request(content=user_message, session_id=None)
with BaggageBuilder().tenant_id(tenant_id).agent_id(agent_id).build():
invoke_scope = InvokeAgentScope.start(request, InvokeAgentScopeDetails(), agent_details)
with invoke_scope:
invoke_scope.record_input_messages([user_message])
invoke_scope.record_output_messages([response])
Viktigt
Det manuella tvåstegsflödet (get_agentic_application_token + MSAL acquire_token_for_client) krävs för S2S.
AgenticUserAuthorization.get_token() returnerar en token med scope till 5a807f24-.../.default (Bot Framework), inte observabilitetsresursen api://9b975845-.../.default : S2S-endpointen returnerar 401 InvalidAudience.
- Använd
context.activity.get_agentic_instance_id()ochget_agentic_tenant_id()för att läsa agenten och hyresgästen från aktiviteten (läser frånrecipientenligt SDK-konventionen). - Hämta och cacha S2S-token innan du skapar spans. Exportörens
BatchSpanProcessorkan flusha innan hanteraren är klar: om token inte är cachad än, misslyckas exporten. - Omge alla A365-scope i
BaggageBuilderså att exportören vet vilken agent och hyresgäst tokens ska hämtas för. Utan bagage släpps spann tyst med "Inga spanar med hyresgäst-/agentidentitet hittad."
Anpassad motor med OBO
Anpassade motoragenter använder standardappregistreringar med Azure Bot OAuth-anslutningar, inte agentisk identitetskedja. Genom att använda OBO får agenten en användartoken via Azure Bot OAuth som redan har scope för A365-observabilitets-API:et via Bot Framework Token Service. Ett enda getToken- eller GetTurnTokenAsync-anrop returnerar en korrekt scope:ad token, så du behöver inte exchangeToken.
Krav
Entra-appregistrering med delegerade API-behörigheter. Lägg till Agent365.Observability.OtelWrite (Delegated) och bevilja administratörsgodkännande
Viktigt
Den agentId i token-cachen måste överensstämma med appregistreringens klient-ID – inte aktivitetens agenticAppId, vilket inte existerar för anpassade motoragenter. Export-URL:en inkluderar agentId, och en mismatch orsakar HTTP 403.
Steg 1: Miljö- och applikationskonfiguration
Följande exempel visar hur du konfigurerar din app och körmiljö, inklusive serviceanslutningsvärden, tenant- och klientinställningar samt nödvändiga auktoriseringsmappningar.
# .env
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=<your-client-id>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=<your-client-secret>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=<your-tenant-id>
CONNECTIONSMAP__0__CONNECTION=SERVICE_CONNECTION
CONNECTIONSMAP__0__SERVICEURL=*
# Auth handler config : TYPE is required, name is uppercased by load_configuration_from_env
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__OBOCONNECTIONPROFILE__TYPE=UserAuthorization
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__OBOCONNECTIONPROFILE__SETTINGS__AZUREBOTOAUTHCONNECTIONNAME=oboConnectionProfile
AGENTAPPLICATION__USERAUTHORIZATION__HANDLERS__OBOCONNECTIONPROFILE__SETTINGS__SCOPES=api://9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite
ENABLE_A365_OBSERVABILITY=true
ENABLE_A365_OBSERVABILITY_EXPORTER=true
Viktigt
load_configuration_from_env konverterar alla miljövariabelnycklar till versaler. Hanterarens namn blir OBOCONNECTIONPROFILE och du måste referera till det med exakt samma skrivsätt i auth_handlers- och get_token()-anrop. Om TYPE saknas uppstår Auth handler ... not recognized or not configured under körning.
Steg 2– Konfigurera OBO-programmet
Följande exempel visar hur man aktiverar exportering i Agent 365, behåller exportören på OBO-slutpunkten och registrerar en anpassad TokenResolver som returnerar delegerade tokens under exporten.
from microsoft.opentelemetry import use_microsoft_opentelemetry
_token_cache: dict[str, str] = {}
def token_resolver(agent_id: str, tenant_id: str) -> str | None:
return _token_cache.get(f"{agent_id}:{tenant_id}")
environ["ENABLE_A365_OBSERVABILITY_EXPORTER"] = "true"
use_microsoft_opentelemetry(
enable_a365=True,
a365_token_resolver=token_resolver,
a365_use_s2s_endpoint=False, # OBO uses /observability endpoint
a365_enable_observability_exporter=True,
)
Kommentar
OBO-läget kräver jwt_authorization_middleware på aiohttpApplication (validerar den inkommande JWT (JSON Web Token) från Bot Framework). S2S/emulator-sökvägen borde inte inkludera denna middleware.
from microsoft_agents.hosting.aiohttp import jwt_authorization_middleware
app = Application(middlewares=[jwt_authorization_middleware])
Steg 3: Skaffa OBO-token
Följande exempel visar hur man begär en delegerad OBO-token från den konfigurerade Azure-robot OAuth-anslutningen och sedan cachar den per appklient och tenant för exportören.
from microsoft_agents.hosting.core import (
AgentApplication, Authorization, MemoryStorage, TurnContext, TurnState,
)
from microsoft_agents.activity import load_configuration_from_env
from microsoft_agents.authentication.msal import MsalConnectionManager
from microsoft_agents.hosting.aiohttp import CloudAdapter
# Auth handlers are loaded from .env via load_configuration_from_env (see Environment config above)
agents_sdk_config = load_configuration_from_env(environ)
STORAGE = MemoryStorage()
CONNECTION_MANAGER = MsalConnectionManager(**agents_sdk_config)
ADAPTER = CloudAdapter(connection_manager=CONNECTION_MANAGER)
AUTHORIZATION = Authorization(STORAGE, CONNECTION_MANAGER, **agents_sdk_config)
AGENT_APP = AgentApplication[TurnState](
storage=STORAGE, adapter=ADAPTER, authorization=AUTHORIZATION, **agents_sdk_config,
)
CLIENT_ID = environ.get("CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID", "")
TENANT_ID = environ.get("CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID", "")
# Message handler : get_token returns a token already scoped to the observability API.
# The Azure Bot Token Service performs the OBO exchange internally based on the
# OAuth connection's configured scope. No manual MSAL exchange_token call is needed.
@AGENT_APP.activity("message", auth_handlers=["OBOCONNECTIONPROFILE"])
async def on_message(context: TurnContext, _state: TurnState):
token_response = await AGENT_APP.auth.get_token(context, "OBOCONNECTIONPROFILE")
# token_response.token has aud=<a365-observability-app-id>,
# scp=Agent365.Observability.OtelWrite
_token_cache[f"{CLIENT_ID}:{TENANT_ID}"] = token_response.token
Viktigt
Azure Portal-krav: Azure Bot OAuth-anslutningen med namnet oboConnectionProfile måste ha sina Scopes inställda på api://9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite. Utan denna inställning begränsas token till robotens egen målgrupp (api://botid-...) och exporten misslyckas med HTTP 401 InvalidAudience.
Kommentar
AGENT_APP.auth.get_token() returnerar en token med rätt scope direkt – inget exchange_token()-anrop behövs. Bot Framework Token Service hanterar OBO-utbytet när OAuth-anslutningens omfång riktar sig mot A365:s observabilitetsresurs.
Anpassad motor med S2S
Anpassade motoragenter kan använda S2S (klientuppgifter) för att skaffa en app-only-token genom att använda serviceanslutningens autentiseringsuppgifter. Denna metod använder standard MSAL-klientuppgifter – ingen agentisk identitetskedja krävs.
Krav
-
Azure AD-appregistrering : Måste vara en anpassad motor (standard) app. Agent 365-aktiverade appregistreringar kan inte använda plain
client_credentialssom observabilitetsresurs (AADSTS82001). -
Applikationsbehörigheter: Lägg till
Agent365.Observability.OtelWrite(Applikation, inte Delegerad) och ge administratörsgodkännande.
Viktigt
Det agentId som används för caching måste vara ServiceConnections ClientId. Export-URL:n är /observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces : en avvikelse orsakar HTTP 403.
Steg 1: Miljö- och applikationskonfiguration
Följande exempel visar hur du konfigurerar din app och körmiljö, inklusive serviceanslutningsvärden, tenant- och klientinställningar samt nödvändiga auktoriseringsmappningar.
# .env
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID=<your-client-id>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET=<your-client-secret>
CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID=<your-tenant-id>
CONNECTIONSMAP__0__CONNECTION=SERVICE_CONNECTION
CONNECTIONSMAP__0__SERVICEURL=*
ENABLE_A365_OBSERVABILITY=true
ENABLE_A365_OBSERVABILITY_EXPORTER=true
Steg 2– Konfigurera S2S-programmet
Följande exempel visar hur du aktiverar Agent 365-export, sätter exportören till S2S-slutpunkten och registrerar en anpassad TokenResolver för tokenuppslagning under exporten.
from microsoft.opentelemetry import use_microsoft_opentelemetry
_token_cache: dict[str, str] = {}
def token_resolver(agent_id: str, tenant_id: str) -> str | None:
return _token_cache.get(f"{agent_id}:{tenant_id}")
use_microsoft_opentelemetry(
enable_a365=True,
a365_token_resolver=token_resolver,
a365_use_s2s_endpoint=True, # S2S uses /observabilityService endpoint
a365_enable_observability_exporter=True,
)
Steg 3: Skaffa S2S-token
Följande exempel visar hur man begär en åtkomsttoken för endast app till observabilitetsresursen med hjälp av serviceanslutningens autentiseringsuppgifter, och sedan lagrar den i cache per agent och tenant för exportören.
# Force agentId to ServiceConnection ClientId (custom engine agents have no agenticAppId)
agent_id = os.environ.get("CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID")
tenant_id = os.environ.get("CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID")
connection = CONNECTION_MANAGER.get_connection("SERVICE_CONNECTION")
token = await connection.get_access_token(
resource_url="https://login.microsoftonline.com",
scopes=["api://9b975845-388f-4429-889e-eab1ef63949c/.default"],
)
_token_cache[f"{agent_id}:{tenant_id}"] = token
Steg 4: Konfigurera baggage för span-export
Agent365-exportören kräver att baggage (tenant-ID och agent-ID) måste sättas på span-kontexten. Om baggage inte är satt, droppar exportören tyst spans med meddelandet No spans with tenant/agent identity found..
from microsoft.opentelemetry.a365.core import BaggageBuilder, InvokeAgentScope
# Baggage must wrap the span as a context manager
with BaggageBuilder().tenant_id(tenant_id).agent_id(agent_id).build():
invoke_scope = InvokeAgentScope.start(request, InvokeAgentScopeDetails(), agent_details)
with invoke_scope:
invoke_scope.record_input_messages([user_message])
invoke_scope.record_output_messages([response])