Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Экспортер Agent 365 требует токен-резолвера для аутентификации при экспорте телеметрии. Это руководство охватывает настройку агентов, построенных с Пакет SDK агентов Microsoft 365, охватывая как агентов с поддержкой Agent 365, так и кастомных движков по .NET, Python и Node.js.
Для установки дистрибутивов, общей конфигурации и сценариев не-агентных SDK см. Microsoft OpenTelemetry Distro.
Обзор
Существует четыре сценария аутентификации, в зависимости от типа вашего агента и способа приобретения токенов. Для получения токенов можно использовать On-Behalf-Of flow (OBO) или Service-to-Service (S2S). Выберите сценарий, который соответствует вашей схеме:
| Сценарий | Описание |
|---|---|
| Агент 365 с поддержкой OBO | Встроенный AgenticTokenCache дистрибутив автоматически управляет получением токенов. Кастомный резолвер не требуется. Это рекомендованный подход для агентов с поддержкой Agent 365. |
| Агент 365 с поддержкой S2S | Агент получает токен с помощью цепочки идентификации агента (getAgenticApplicationToken + Microsoft Authentication Libraries (MSAL)). Требуется кастомный TokenResolver. Используйте этот подход, когда OBO недоступен или нужны токены только для приложения. |
| Кастомный движок с использованием OBO | Агент получает пользовательский токен через Azure Bot OAuth, ограниченный на API наблюдаемости. Требуется кастомный TokenResolver и Azure Bot OAuth. |
| Пользовательский движок с использованием S2S | Агент приобретает токен только для приложения, используя учетные данные клиента. Требуется кастомный TokenResolver. Регистрация приложения должна быть стандартным (не агентским) приложением. |
Агент 365 с поддержкой OBO
Агенты с поддержкой Agent 365 получают запросы с агентной идентичностью (agenticAppId, agenticUserId) от платформы Agent 365. В OBO встроенный AgenticTokenCache дистрибутив автоматически обрабатывает получение токенов: не требуется пользовательский резолвер токенов.
Необходимые условия
- Регистрация приложения Entra : принципал сервиса (регистрация приложения) с идентификатором клиента, секретом клиента и идентификатором арендатора
-
Делегированные права API : Add
Agent365.Observability.OtelWrite(Delegated), предоставление согласия администратора. Подробные шаги смотрите в разделе «Предоставление разрешения».
Настройка
В каждом ходу ваш агент вызывает RegisterObservability функцию с контекстом хода. Встроенный кэш использует делегированный пользователям токен от AgenticUserAuthorization обработчика для проведения OBO-обмена, приобретая токен с Agent365.Observability.OtelWriteобластью действия .
Полные инструкции по установке, включая пакеты, конфигурацию и примеры кода, см. Кэш агентных токенов с приложениями Agent Framework.
Агент 365 с поддержкой S2S
Агенты с поддержкой агента 365 также могут использовать аутентификацию S2S (service-to-service) вместо OBO. Агент приобретает токен, используя собственную принципальную идентичность сервиса через двухступенчатую агентную цепочку идентичности:
-
getAgenticApplicationToken(tenantId, agentId): учетные данные клиента + путь Федеративной управляемой идентичности (FMI) - MSAL
acquireTokenForClientс токеном приложения какclientAssertionи областью примененияapi://9b975845-388f-4429-889e-eab1ef63949c/.default
Примечание.
Федеративная управляемая идентичность (FMI) — это архитектура, в которой управляемая идентичность участвует в федерации рабочей нагрузки с помощью федеративных идентификаторов, обеспечивая обмен токенами и бессекретную аутентификацию на основе доверительных отношений между идентичностями.
Вы должны предоставить кастомный TokenResolver и набор UseS2SEndpoint = true.
Необходимые условия
Регистрация приложения Entra : принципал сервиса (регистрация приложения) с идентификатором клиента, секретом клиента и идентификатором арендатора
Разрешения API приложений: Add
Agent365.Observability.OtelWrite(Application), предоставление согласия администратораAgent365.Observability.OtelWriteроль приложения : Принципал сервиса агента должен иметьOtelWriteроль, назначенную на ресурсе наблюдаемости Agent365. Используйте CLI Agent 365:a365 setup permissions bot --config-dir "<path-to-config-dir>"Примечание.
Распространение роли может занять несколько минут. Ожидаются начальные ошибки 401 или 403 от экспортной конечной точки в этот период.
Шаг 1: Настройка среды
Следующие примеры кода показывают, как настроить необходимые настройки соединения, арендатора, учетных данных клиента и среды экспортера наблюдаемости перед включением пользовательского потока токена S2S.
Куратор не AgenticUserAuthorization нужен. S2S использует ручную агентную цепочку идентификации (get_agentic_application_token + MSAL acquire_token_for_client) для получения токена, ограниченного на ресурс наблюдаемости.
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
Шаг 2: Настройте дистрибутив с помощью кастомного резолвера токенов
Следующие примеры показывают, как включить экспорт Agent 365 и зарегистрировать кастом TokenResolver , чтобы экспортер мог получить токены S2S для каждого агента и арендатора.
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,
)
Шаг 3: Приобрести и кэшировать токен S2S
В каждом входящем сообщении получайте токен S2S через цепочку агентной идентичности и кэшируйте его для резолвера.
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])
Это важно
Для S2S требуется ручной двухступенчатый поток (get_agentic_application_token + MSAL acquire_token_for_client).
AgenticUserAuthorization.get_token() возвращает токен с областью действия ( 5a807f24-.../.default Bot Framework), а не ресурс api://9b975845-.../.default наблюдаемости: конечная точка S2S отклоняет его с помощью 401 InvalidAudience.
- Используйте
context.activity.get_agentic_instance_id()иget_agentic_tenant_id()чтобы читать агента и арендатора из активности (читается поrecipientSDK-конвенции). - Заберите и кэшируйте токен S2S перед созданием спайпов. У экспортера
BatchSpanProcessorможет промыться до завершения обработчика: если токен ещё не кэширован, экспорт не проходит. - Оберните все области
BaggageBuilderA365, чтобы экспортер знал, для какого агента и арендатора разрешать токены. Без багажа спанты тихо сбрасывают с надписью «Ни одного варианта с идентификацией арендатора/агента не найдено».
Кастомный движок с использованием OBO
Пользовательские агенты движка используют стандартные регистрации приложений с соединениями Azure Bot OAuth, а не в цепочке агентной идентичности. Используя OBO, агент получает пользовательский токен через Azure Bot OAuth, который уже связан с API наблюдаемости A365 через Bot Framework Token Service. Одиночный getToken или GetTurnTokenAsync звонок возвращает правильно обозначенный токен, так что вам не нужен exchangeToken.
Необходимые условия
Регистрация приложения Entra с делегированными правами API. Добавить Agent365.Observability.OtelWrite (делегировано) и дать согласие администратора
Это важно
agentId Кэш в токене должен совпадать с идентификатором клиента регистрации приложения — а не с agenticAppIdID активности, которого нет для кастомных агентов движка. URL экспорта включает agentId, а несоответствие вызывает HTTP 403.
Шаг 1: Настройка среды и приложения
Следующие примеры показывают, как настроить ваше приложение и среду выполнения, включая значения подключения к сервису, настройки арендаторов и клиентов, а также необходимые отметки авторизации.
# .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
Это важно
load_configuration_from_env заглавные буквы — все ключи переменных среды. Имя обработчика появляется OBOCONNECTIONPROFILE , и вы должны ссылаться на него именно с этим корпусом и auth_handlersget_token() вызывает. Отсутствующие TYPE причины Auth handler ... not recognized or not configured во время выполнения.
Шаг 2: Настройте дистрибутив для OBO
Следующие примеры показывают, как включить экспорт из Agent 365, оставить экспортера на конечной точке OBO и зарегистрировать пользовательскую TokenResolver карту, которая возвращает делегированные токены во время экспорта.
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,
)
Примечание.
Режим OBO требует jwt_authorization_middleware на aiohttpApplication (валидирует входящий JWT (JSON Web Token) из Bot Framework). Путь S2S/эмулятора не должен включать этот промежуточный ПО.
from microsoft_agents.hosting.aiohttp import jwt_authorization_middleware
app = Application(middlewares=[jwt_authorization_middleware])
Шаг 3: Приобрести токен OBO
Следующие примеры показывают, как запросить делегированный OBO-токен у настроенного OAuth соединения Azure Bot, а затем кэшировать его по клиенту приложения и арендатору для экспортера.
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
Это важно
портал Azure предварительное условие: Соединение Azure Bot OAuth с названием oboConnectionProfile должно иметь Scopes настроенное на api://9b975845-388f-4429-889e-eab1ef63949c/Agent365.Observability.OtelWrite. Без этой настройки токен распределяется на собственную аудиторию бота (api://botid-...), и экспорт с помощью HTTP 401 InvalidAudienceзаканчивается неудачей.
Примечание.
AGENT_APP.auth.get_token() возвращает токен с правильным диапазоном напрямую — вызов не exchange_token() требуется. Служба токенов Bot Framework обрабатывает обмен OBO, когда область соединения OAuth нацелена на ресурс наблюдаемости A365.
Пользовательский движок с использованием S2S
Пользовательские агенты движка могут использовать S2S (учетные данные клиента) для получения токена только для приложения, используя учетные данные подключения к сервису. Этот метод использует стандартные учетные данные клиента MSAL — не требуется цепочка идентификации агентов.
Необходимые условия
-
Azure регистрация приложения AD : Должно быть приложение custom engine (стандартное). Регистрации приложений с поддержкой агента 365 не могут использовать plain
client_credentialsдля ресурса наблюдаемости (AADSTS82001). -
Права заявки : Add
Agent365.Observability.OtelWrite(Application, not Delegated) и предоставление согласия администратора.
Это важно
Для agentIdкэширования должныClientIdбыть . URL экспорта: /observabilityService/tenants/{tenantId}/otlp/agents/{agentId}/traces несоответствие вызывает HTTP 403.
Шаг 1: Настройка среды и приложения
Следующие примеры показывают, как настроить ваше приложение и среду выполнения, включая значения подключения к сервису, настройки арендаторов и клиентов, а также необходимые отметки авторизации.
# .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
Шаг 2: Настройте дистрибутив для S2S
Следующие примеры показывают, как включить экспорт Agent 365, установить экспортер на конечную точку S2S и зарегистрировать пользовательский TokenResolver поиск токена во время экспорта.
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,
)
Шаг 3: Приобрести токен S2S
Следующие примеры показывают, как запросить токен доступа только для приложения для ресурса наблюдаемости, используя учетные данные подключения сервиса, а затем кэшировать его агентом и арендатором для экспортера.
# 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
Шаг 4: Настройте багаж для экспорта spanов
Экспортер Agent365 требует, чтобы багаж (идентификатор арендатора и идентификатор агента) был установлен в контексте span. Без него экспортер бесшумно сбрасывает суспензии с сообщением 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])