Konfiguration av observabilitetsautentisering

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:

  1. getAgenticApplicationToken(tenantId, agentId) : klientuppgifter + Federated Managed Identity (FMI)-väg
  2. MSAL acquireTokenForClient med app-token som clientAssertion och scope api://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örssamtycke

  • Agent365.Observability.OtelWrite applikationsroll : Agentens servicehuvudkonto måste ha OtelWrite rollen 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() och get_agentic_tenant_id() för att läsa agenten och hyresgästen från aktiviteten (läser från recipient enligt SDK-konventionen).
  • Hämta och cacha S2S-token innan du skapar spans. Exportörens BatchSpanProcessor kan flusha innan hanteraren är klar: om token inte är cachad än, misslyckas exporten.
  • Omge alla A365-scope i BaggageBuilder så 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_middlewareaiohttpApplication (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_credentials som 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])