Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
De Agent 365-exporteur vereist een tokenresolver voor authenticatie bij het exporteren van telemetrie. Deze handleiding beschrijft de installatie voor agents die zijn gebouwd met de SDK voor Microsoft 365-agenten, zowel voor agents die Agent 365 ondersteunen als voor agents met een aangepaste engine in .NET, Python en Node.js.
Zie Microsoft OpenTelemetry Distro voor installatie in een distributie, algemene configuratie en scenario's zonder Agent SDK.
Overzicht
Er zijn vier authenticatiescenario's, afhankelijk van uw agenttype en hoe deze tokens verkrijgt. Tokenverkrijging kan gebruikmaken van On-Behalf-Of flow (OBO) of Service-to-Service (S2S). Kies het scenario dat overeenkomt met uw configuratie:
| Scenario | Omschrijving |
|---|---|
| Agent 365-compatibel met OBO | De ingebouwde AgenticTokenCache van de distributie handelt tokenverkrijging automatisch af. Geen aangepaste resolver nodig. Dit is de aanbevolen aanpak voor Agent 365-compatibele agents. |
| Agent 365-compatibel met S2S | De agent verkrijgt een token met behulp van de agent-identiteitsketen (getAgenticApplicationToken + Microsoft Authentication Libraries (MSAL)). Vereist een aangepaste TokenResolver. Gebruik deze aanpak wanneer OBO niet beschikbaar is of wanneer u alleen app-tokens nodig hebt. |
| Aangepaste engine met OBO | De agent verkrijgt een gebruikerstoken via Azure Bot OAuth, gekoppeld aan de Observability API. Vereist een aangepaste TokenResolver en een Azure Bot OAuth-verbinding. |
| Aangepaste engine met S2S | De agent verkrijgt een app-only token met behulp van clientreferenties. Vereist een aangepaste TokenResolver. De app-registratie moet een standaard (niet-agentische) app zijn. |
Agent 365-compatibel met OBO
Agent 365-compatibele agents ontvangen verzoeken met een agentische identiteit (agenticAppId, agenticUserId) van het Agent 365-platform. Met OBO handelt de ingebouwde AgenticTokenCache van de distributie de tokenverwerving automatisch af: er is geen aangepaste tokenresolver nodig.
Vereisten
- Voer app-registratie in: Een serviceprincipal (app-registratie) met Client ID, Client Secret en Tenant ID
-
Gedelegeerde API-machtigingen: Voeg
Agent365.Observability.OtelWrite(Gedelegeerd) toe en verleen beheerdersrechten. Zie De machtiging verlenen voor gedetailleerde stappen.
Instellen
Bij elke beurt roept uw agent de RegisterObservability-functie aan met de beurtcontext. De ingebouwde cache gebruikt het gedelegeerde token van de gebruiker van de AgenticUserAuthorization handler om een OBO-uitwisseling uit te voeren en een token te verkrijgen dat is gekoppeld aan Agent365.Observability.OtelWrite.
Zie Agentic token cache met Agent Framework-apps voor volledige installatie-instructies, inclusief pakketten, configuratie en codevoorbeelden.
Agent 365-compatibel met S2S
Agents die zijn ingeschakeld voor Agent 365 kunnen ook S2S-authenticatie (service-to-service) gebruiken in plaats van OBO. De agent verkrijgt een token met behulp van zijn eigen serviceprincipal-identiteit via een tweestaps agentische identiteitsketen:
-
getAgenticApplicationToken(tenantId, agentId): clientreferenties + Federated Managed Identity (FMI)-pad - MSAL
acquireTokenForClientmet het app-token alsclientAssertionen bereikapi://9b975845-388f-4429-889e-eab1ef63949c/.default
Notitie
Federated Managed Identity (FMI) is een architectuur waarbij een beheerde identiteit deelneemt aan de federatie van workload-identiteiten via gefedereerde identiteitsreferenties, waardoor tokenuitwisseling en geheimloze authenticatie mogelijk is op basis van vertrouwensrelaties tussen identiteiten.
U moet een aangepaste TokenResolver opgeven en UseS2SEndpoint = true instellen.
Vereisten
Voer app-registratie in: Een serviceprincipal (app-registratie) met Client ID, Client Secret en Tenant ID
Applicatie-API-machtigingen: Toevoegen
Agent365.Observability.OtelWrite(Applicatie), beheerdersrechten verlenenAgent365.Observability.OtelWriteApp-rol: De serviceprincipal van de agent moet de rolOtelWritetoegewezen hebben op de Agent365 Observability-resource. Gebruik de Agent 365 CLI:a365 setup permissions bot --config-dir "<path-to-config-dir>"Notitie
Het doorgeven van de rol kan enkele minuten duren. Initiële 401- of 403-fouten van het export-eindpunt zijn gedurende deze periode te verwachten.
Stap 1: Omgevingsconfiguratie
De volgende codevoorbeelden laten zien hoe u de vereiste verbinding, tenant, clientreferenties en omgevingsinstellingen voor de observability-exporter instelt voordat u de aangepaste S2S-tokenstroom inschakelt.
Geen handler AgenticUserAuthorization nodig. S2S gebruikt de handmatige agent-identiteitsketen (get_agentic_application_token + MSAL acquire_token_for_client) om een token te verkrijgen dat is gekoppeld aan de observability-resource.
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
Stap 2: Configureer de distributie met een aangepaste tokenresolver
De volgende voorbeelden laten zien hoe u Agent 365-export inschakelt en een aangepaste TokenResolver registreert, zodat de exporter S2S-tokens kan ophalen voor elke agent en tenant.
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,
)
Stap 3: Het S2S-token verkrijgen en cachen
Verkrijg bij elk inkomend bericht het S2S-token via de agentische identiteitsketen en cache het voor de resolver.
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])
Belangrijk
De handmatige tweestapsflow (get_agentic_application_token + MSAL acquire_token_for_client) is vereist voor S2S.
AgenticUserAuthorization.get_token() Retourneert een token dat is gekoppeld aan 5a807f24-.../.default (Bot Framework), niet aan de observability resource api://9b975845-.../.default: het S2S-eindpunt wijst dit af met 401 InvalidAudience.
- Gebruik
context.activity.get_agentic_instance_id()enget_agentic_tenant_id()om de agent en tenant uit de activiteit te lezen (leest uitrecipientvolgens de SDK-conventie). - Verkrijg en cache het S2S-token voordat spans worden aangemaakt. De
BatchSpanProcessorvan de exporter kan worden geleegd voordat de handler klaar is: als het token nog niet in de cache is opgeslagen, mislukt de export. - Omwikkel alle A365-scopes met
BaggageBuilderzodat de exporteur weet voor welke agent en tenant tokens moeten worden opgelost. Zonder deze omwikkeling worden spans stilzwijgend genegeerd met de melding "Geen spans met tenant-/agentidentiteit gevonden."
Aangepaste engine met OBO
Agenten van de aangepaste engine gebruiken standaard app-registraties met Azure Bot OAuth-verbindingen, niet de agent-identiteitsketen. Door OBO te gebruiken, verkrijgt de agent een gebruikerstoken via Azure Bot OAuth dat al is gekoppeld aan de A365-observatie-API door de Bot Framework Token Service. Een enkele aanroep van getToken of GetTurnTokenAsync retourneert het correct gekoppelde token, dus u hebt exchangeToken niet nodig.
Vereisten
Entra-appregistratie met Gedelegeerde API-machtigingen. Voeg Agent365.Observability.OtelWrite (Gedelegeerd) toe en verleen beheerdersrechten
Belangrijk
De agentId in de tokencache moet overeenkomen met de Client-ID van de app-registratie - niet met de agenticAppId van de activiteit, die niet bestaat voor aangepaste engine-agents. De export-URL bevat de agentId, en een mismatch veroorzaakt HTTP 403.
Stap 1: Omgeving en app-configuratie
De volgende voorbeelden laten zien hoe u uw app en runtime-omgeving configureert, inclusief serviceverbindingswaarden, tenant- en clientinstellingen en vereiste autorisatietoewijzingen.
# .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
Belangrijk
load_configuration_from_env zet alle sleutels van omgevingsvariabelen in hoofdletters. De handlernaam wordt OBOCONNECTIONPROFILE en u moet deze exact met diezelfde hoofdlettergevoeligheid gebruiken in auth_handlers en get_token() aanroepen. Het ontbreken van TYPE veroorzaakt Auth handler ... not recognized or not configured tijdens runtime.
Stap 2: Configureer de distributie voor OBO
De volgende voorbeelden laten zien hoe u Agent 365-export inschakelt, de exporter op het OBO-eindpunt houdt en een aangepaste TokenResolver registreert die gedelegeerde tokens retourneert tijdens de export.
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,
)
Notitie
De OBO-modus vereist jwt_authorization_middleware op de aiohttpApplication (valideert de inkomende JWT (JSON Web Token) van Bot Framework). Het S2S/emulator-pad mag deze middleware niet bevatten.
from microsoft_agents.hosting.aiohttp import jwt_authorization_middleware
app = Application(middlewares=[jwt_authorization_middleware])
Stap 3: Het OBO-token verkrijgen
De volgende voorbeelden laten zien hoe u een gedelegeerd OBO-token kunt aanvragen via de geconfigureerde Azure Bot OAuth-verbinding en dit vervolgens kunt cachen per app-client en tenant voor de exporteur.
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
Belangrijk
Vereiste voor de Azure Portal: De Azure Bot OAuth-verbinding met de naam oboConnectionProfile moeten de bereiken hebben ingesteld op api://9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite. Zonder deze instelling is het token beperkt tot de eigen doelgroep van de bot (api://botid-...) en mislukt de export met HTTP 401 InvalidAudience.
Notitie
AGENT_APP.auth.get_token() Retourneert direct het token met de juiste scope - er is geen aanroep exchange_token() nodig. De Bot Framework Token Service handelt de OBO-uitwisseling af wanneer de scope van de OAuth-verbinding gericht is op de A365-observatieresource.
Aangepaste engine met S2S
Aangepaste engine-agents kunnen S2S (clientreferenties) gebruiken om een app-only token te verkrijgen met behulp van de serviceverbindingsreferenties. Deze methode gebruikt standaard MSAL-clientreferenties - er is geen agent-identiteitsketen vereist.
Vereisten
-
Azure AD-appregistratie: Moet een aangepaste engine (standaard) app zijn. App-registraties die Agent 365 ondersteunen, kunnen geen gewone
client_credentialsgebruiken voor de observatieresource (AADSTS82001). -
Toepassingsmachtigingen: Voeg
Agent365.Observability.OtelWrite(Toepassing, niet Gedelegeerd) toe en verleen beheerdersrechten.
Belangrijk
De agentId die gebruikt wordt voor caching moet de ClientId van de ServiceConnection zijn. De export-URL is /observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces : een mismatch veroorzaakt HTTP 403.
Stap 1: Omgeving en app-configuratie
De volgende voorbeelden laten zien hoe u uw app en runtime-omgeving configureert, inclusief serviceverbindingswaarden, tenant- en clientinstellingen en vereiste autorisatietoewijzingen.
# .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
Stap 2: Configureer de distributie voor S2S
De volgende voorbeelden laten zien hoe u Agent 365-export inschakelt, de exporteur instelt op het S2S-eindpunt en een aangepaste TokenResolver registreert voor tokenopzoeking tijdens de export.
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,
)
Stap 3: Het S2S-token verkrijgen
De volgende voorbeelden laten zien hoe u een app-only toegangstoken voor de observability-resource kunt aanvragen met behulp van de serviceverbindingsgegevens, en hoe u dit vervolgens per agent en tenant kunt cachen voor de exporter.
# 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
Stap 4: Bagage instellen voor span-export
De Agent365-exporter vereist dat de bagage (tenant-ID en agent-ID) is ingesteld in de span-context. Zonder deze bagage laat de exporter spans stilzwijgend vallen met de melding 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])