Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
L'utilità di esportazione di Agent 365 richiede un resolver di token per l'autenticazione durante l'esportazione dei dati di telemetria. Questa guida illustra la configurazione degli agenti compilati con Managed Disks, che copre sia gli agenti abilitati per Agent 365 che gli agenti del motore personalizzati in .NET, Python e Node.js.
Per l'installazione della distro, la configurazione generale e gli scenari che non prevedono l'Agent SDK, vedere Microsoft OpenTelemetry Distro.
Informazioni generali
Esistono quattro scenari di autenticazione, a seconda del tipo di agente e del modo in cui acquisisce i token. L'acquisizione di token può avvenire tramite il flusso On-Behalf-Of (OBO) o Service-to-Service (S2S). Scegliere lo scenario corrispondente alla configurazione:
| Scenario | Description |
|---|---|
| Agente 365 abilitato con OBO | Il AgenticTokenCache integrato della distribuzione gestisce automaticamente l'acquisizione dei token. Non è necessario alcun sistema di risoluzione personalizzato. Questo è l'approccio consigliato per gli agenti abilitati per Agent 365. |
| Agente 365 abilitato con S2S | L'agente acquisisce un token usando la catena di identità agentic (getAgenticApplicationToken + Microsoft Authentication Libraries (MSAL)). Richiede un elemento personalizzato TokenResolver. Utilizza questo approccio quando OBO non è disponibile o quando sono necessari token per la sola app. |
| Motore personalizzato con OBO | L'agente ottiene un token utente tramite Azure Bot OAuth, con ambito limitato all'API di osservabilità. Richiede un TokenResolver personalizzato e una connessione OAuth di Azure Bot. |
| Motore personalizzato con S2S | L'agente acquisisce un token di sola applicazione usando le credenziali del client. Richiede un TokenResolver personalizzato. La registrazione dell'app deve essere un'app standard (non agentica). |
Agente 365 abilitato con OBO
Gli agenti abilitati per Agent 365 ricevono richieste con identità agente (agenticAppId, agenticUserId) dalla piattaforma Agent 365. Con OBO, il componente integrato della distribuzione AgenticTokenCache gestisce automaticamente l'acquisizione dei token: non è necessario alcun token resolver personalizzato.
Prerequisiti
- Registrazione dell'app Entra: un'entità servizio (registrazione dell'app) con ID client, segreto client e ID tenant
-
Autorizzazioni API delegate : Aggiungi
Agent365.Observability.OtelWrite(Delegato), concedi il consenso dell'amministratore. Per i passaggi dettagliati, vedere Concedere l'autorizzazione.
Configurazione
Ad ogni turno, l'agente chiama la funzione RegisterObservability passandole il contesto del turno. La cache integrata usa il token delegato dell'utente del gestore AgenticUserAuthorization per eseguire uno scambio OBO, acquisendo un token con ambito limitato a Agent365.Observability.OtelWrite.
Per istruzioni complete sull'installazione, inclusi pacchetti, configurazione ed esempi di codice, vedere Cache dei token agentic con le app di Agent Framework.
Agent 365 abilitato tramite S2S
Gli agenti con Agent 365 abilitato possono anche usare l'autenticazione S2S (servizio-servizio) invece di OBO. L'agente acquisisce un token utilizzando la propria identità del service principal tramite una catena di identità agentica in due passaggi:
-
getAgenticApplicationToken(tenantId, agentId): credenziali client + percorso di identità gestita federata (FMI) - MSAL
acquireTokenForClientcon il token dell'app impostato suclientAssertione scopeapi://9b975845-388f-4429-889e-eab1ef63949c/.default
Annotazioni
L'identità gestita federata (FMI) è un'architettura in cui un'identità gestita partecipa alla federazione dell'identità del carico di lavoro tramite credenziali di identità federate, abilitando lo scambio di token e l'autenticazione senza segreto in base alle relazioni di trust tra le identità.
È necessario specificare un oggetto personalizzato TokenResolver e impostare UseS2SEndpoint = true.
Prerequisiti
Registrazione dell'app Entra : entità servizio (registrazione dell'app) con ID client, segreto del client e ID tenant
Autorizzazioni dell'API dell'applicazione : Aggiungere
Agent365.Observability.OtelWrite(applicazione), concedere il consenso amministratoreAgent365.Observability.OtelWriteruolo dell'app : l'entità servizio dell'agente deve avere il ruoloOtelWriteassegnato sulla risorsa Agent365 Observability. Usa la CLI di Agent 365:a365 setup permissions bot --config-dir "<path-to-config-dir>"Annotazioni
La propagazione dei ruoli potrebbe richiedere alcuni minuti. Durante questo periodo sono previsti errori iniziali 401 o 403 dall'endpoint di esportazione.
Passaggio 1: Configurazione dell'ambiente
Gli esempi di codice seguenti illustrano come impostare le impostazioni di ambiente di esportazione di connessioni, tenant, credenziali client e osservabilità necessarie prima di abilitare il flusso del token S2S personalizzato.
Non è necessario alcun gestore AgenticUserAuthorization. S2S usa la catena di identità agentica manuale (get_agentic_application_token + MSAL acquire_token_for_client) per ottenere un token con ambito limitato alla risorsa di osservabilità.
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
Passaggio 2: Configurare la distribuzione con il resolver di token personalizzato
Gli esempi seguenti mostrano come abilitare l'esportazione di Agent 365 e registrare un TokenResolver personalizzato affinché l'esportatore possa recuperare i token S2S per ogni agente e 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,
)
Passaggio 3: Acquisire e memorizzare nella cache il token S2S
In ogni messaggio in arrivo acquisire il token S2S tramite la catena di identità agentic e memorizzarlo nella cache per il sistema di risoluzione.
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])
Importante
Il flusso manuale in due passaggi (get_agentic_application_token + MSAL acquire_token_for_client) è necessario per S2S.
AgenticUserAuthorization.get_token() restituisce un token con ambito 5a807f24-.../.default (Bot Framework), non relativo alla risorsa di osservabilità api://9b975845-.../.default: l'endpoint S2S lo rifiuta con 401 InvalidAudience.
- Usare
context.activity.get_agentic_instance_id()eget_agentic_tenant_id()per recuperare l'agente e il tenant dall'attività (recuperandoli darecipientsecondo la convenzione dell'SDK). - Acquisire e memorizzare nella cache il token S2S prima di creare intervalli. Il
BatchSpanProcessordell'esportatore potrebbe svuotarsi prima che il gestore termini : se il token non è ancora stato memorizzato nella cache, l'esportazione ha esito negativo. - Racchiudi tutti gli scope A365 tra i tag
BaggageBuilderin modo che l'utilità di esportazione sappia per quali agente e tenant risolvere i token. Senza bagagli, gli intervalli vengono rilasciati automaticamente con "Nessun intervallo con identità tenant/agente trovato".
Motore personalizzato con OBO
Gli agenti del motore personalizzato usano registrazioni delle app standard con connessioni OAuth di Azure Bot, non la catena di identità agentica. Usando OBO, l'agente ottiene un token utente tramite Azure Bot OAuth con ambito già limitato all'API di osservabilità A365 dal servizio token di Bot Framework. Una singola getToken chiamata o GetTurnTokenAsync restituisce il token con ambito corretto, quindi non è necessario exchangeToken.
Prerequisiti
Registrazione dell'app Entra con autorizzazioni API delegate. Aggiungi Agent365.Observability.OtelWrite (delegato) e concedi il consenso dell'amministratore
Importante
L'agentId nella cache dei token deve corrispondere all'ID client della registrazione dell'app, non a agenticAppId dell'attività, che non esiste per gli agenti del motore personalizzato. L'URL di esportazione include agentId e una mancata corrispondenza provoca un errore HTTP 403.
Passaggio 1: Configurazione dell'ambiente e dell'app
Gli esempi seguenti illustrano come configurare l'app e l'ambiente di runtime, inclusi i valori di connessione del servizio, le impostazioni del tenant e del client e i mapping di autorizzazione necessari.
# .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
Importante
load_configuration_from_env converte in maiuscolo tutte le chiavi delle variabili di ambiente. Il nome del gestore diventa OBOCONNECTIONPROFILE e devi farvi riferimento rispettando esattamente la distinzione tra maiuscole e minuscole nelle chiamate a auth_handlers e get_token(). L'assenza di TYPE causa Auth handler ... not recognized or not configured in fase di esecuzione.
Passaggio 2: Configurare la distro per OBO
Gli esempi seguenti mostrano come abilitare l'esportazione in Agent 365, mantenere l'esportatore sull'endpoint OBO e registrare un elemento personalizzato TokenResolver che restituisce token delegati durante l'esportazione.
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,
)
Annotazioni
La modalità OBO richiede jwt_authorization_middleware in aiohttpApplication (convalida il token JWT in ingresso (token Web JSON) da Bot Framework. Il percorso S2S/emulatore non deve includere questo middleware.
from microsoft_agents.hosting.aiohttp import jwt_authorization_middleware
app = Application(middlewares=[jwt_authorization_middleware])
Passaggio 3: Acquisire il token OBO
Gli esempi seguenti mostrano come richiedere un token OBO delegato dalla connessione OAuth di Azure Bot configurata, quindi memorizzarlo nella cache per client app e tenant per l'esportatore.
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
Importante
portale di Azure prerequisito: La connessione OAuth bot Azure denominata oboConnectionProfile deve avere Scopes impostata su api://9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite. Senza questa impostazione, il token ha come ambito il gruppo di destinatariapi://botid-... () del bot e l'esportazione ha esito negativo con HTTP 401 InvalidAudience.
Annotazioni
AGENT_APP.auth.get_token() restituisce direttamente il token con ambito corretto. Non è necessaria alcuna exchange_token() chiamata. Il servizio token di Bot Framework gestisce lo scambio OBO quando l'ambito della connessione OAuth ha come destinazione la risorsa di osservabilità A365.
Motore personalizzato con S2S
Gli agenti del motore personalizzati possono usare S2S (credenziali del client) per acquisire un token di sola applicazione utilizzando le credenziali della connessione al servizio. Questo metodo usa le credenziali client MSAL standard: non è richiesta alcuna catena di identità agentic.
Prerequisiti
-
registrazione dell'app di Azure AD: Deve essere un motore personalizzato (standard). Le registrazioni dell'app abilitate per Agent 365 non possono usare semplicemente
client_credentialsper la risorsa di osservabilità (AADSTS82001). -
Autorizzazioni dell'applicazione : aggiungere
Agent365.Observability.OtelWrite(applicazione, non delegata) e concedere il consenso amministratore.
Importante
L'oggetto agentId utilizzato per la memorizzazione nella cache deve essere ClientId di ServiceConnection. L'URL di esportazione è /observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces : una mancata corrispondenza causa HTTP 403.
Passaggio 1: Configurazione dell'ambiente e dell'app
Gli esempi seguenti illustrano come configurare l'app e l'ambiente di runtime, inclusi i valori di connessione del servizio, le impostazioni del tenant e del client e i mapping di autorizzazione necessari.
# .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
Passaggio 2: Configurare la distribuzione per S2S
Gli esempi seguenti illustrano come abilitare l'esportazione di Agent 365, impostare l'utilità di esportazione sull'endpoint S2S e registrare un personalizzato TokenResolver per la ricerca di token durante l'esportazione.
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,
)
Passaggio 3: Acquisire il token S2S
Gli esempi seguenti illustrano come richiedere un token di accesso per sola app per la risorsa di osservabilità usando le credenziali della connessione al servizio, quindi memorizzarlo nella cache in base all'agente e al tenant per l'esportatore.
# 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
Passaggio 4: Impostare il baggage per l'esportazione degli span
L'utilità di esportazione di Agent365 richiede che il baggage (ID del tenant e ID dell'agente) sia impostato nel contesto dello span. Senza di esso, l'esportatore scarta silenziosamente gli span con il messaggio 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])