Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# Release History
# Unreleased
### Features Added
- Add a Store-ready Agent 365 service-to-service sample covering invoke-agent,
guardrail, inference, execute-tool, and output telemetry scopes.
([#276](https://github.com/microsoft/opentelemetry-distro-python/pull/276))
- Add typed Agent365 execute-tool argument and result schema models with `schema_version: "1.0"` serialization,
`ToolCallAction`/`ToolCallOutcomeStatus`/`ToolPolicyDecision` enums, provider extension data wrapped under
the JSON `metadata` property, public exports, and `ExecuteToolScope` support while preserving raw
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -348,6 +348,7 @@ remain enabled by default.
|---|---|---|
| [samples/a365/exporter.py](https://github.com/microsoft/opentelemetry-distro-python/blob/main/samples/a365/exporter.py) | A365 | LangChain with A365 auto-instrumentation |
| [samples/a365/manual_telemetry.py](https://github.com/microsoft/opentelemetry-distro-python/blob/main/samples/a365/manual_telemetry.py) | A365 | Manual instrumentation using all scope classes |
| [samples/a365/s2s/s2s_exporter.py](https://github.com/microsoft/opentelemetry-distro-python/blob/main/samples/a365/s2s/s2s_exporter.py) | A365 | Store-ready S2S export with all manual observability scopes |
| [samples/distro/tracing.py](https://github.com/microsoft/opentelemetry-distro-python/blob/main/samples/distro/tracing.py) | Azure Monitor | Basic tracing |
| [samples/distro/metrics.py](https://github.com/microsoft/opentelemetry-distro-python/blob/main/samples/distro/metrics.py) | Azure Monitor | Metrics collection |
| [samples/distro/logging_sample.py](https://github.com/microsoft/opentelemetry-distro-python/blob/main/samples/distro/logging_sample.py) | Azure Monitor | Log export |
Expand Down
99 changes: 99 additions & 0 deletions samples/a365/s2s/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# A365 S2S Exporter Sample

This sample exports [Agent 365](https://learn.microsoft.com/en-us/microsoft-agent-365/)
telemetry through the service-to-service (S2S) endpoint and demonstrates every
public manual observability scope.

The service authenticates on its own behalf. The token resolver uses the
Blueprint application credentials to obtain an agent-instance token and then an
application token for the A365 observability scope. It deliberately omits the
agentic-user FIC step and does not emit `microsoft.agent.user.id` or
`microsoft.agent.user.email`.

## Prerequisites

- Python 3.10+
- [uv](https://docs.astral.sh/uv/)
- A Blueprint app registration granted the
`Agent365.Observability.OtelWrite` **application** permission with admin
consent. See [`MIGRATION_A365.md`](../../../MIGRATION_A365.md) under
"Troubleshooting - Permissions and Setup".
- Real tenant, agent Blueprint, agent app instance client ID, and human caller
values from the deployment being validated. Angle-bracket placeholders are
rejected at startup.

## Configure and run

PowerShell:

```powershell
$env:ENABLE_OBSERVABILITY = "true"
$env:ENABLE_A365_OBSERVABILITY_EXPORTER = "true"
$env:CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID = "<blueprint-app-client-id>"
$env:CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET = "<blueprint-app-secret>"
$env:CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID = "<tenant-guid>"
$env:A365_AGENT_APP_INSTANCE_ID = "<agent-app-instance-id>"
$env:A365_AGENT_BLUEPRINT_ID = "<agent-blueprint-id>"
$env:A365_CALLER_USER_ID = "<caller-user-id>"
$env:A365_CALLER_USER_EMAIL = "<caller-user-email>"
$env:A365_CALLER_CLIENT_IP = "<caller-client-ip>"

uv run --with msal python samples\a365\s2s\s2s_exporter.py
```

Bash:

```bash
export ENABLE_OBSERVABILITY=true
export ENABLE_A365_OBSERVABILITY_EXPORTER=true
export CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTID="<blueprint-app-client-id>"
export CONNECTIONS__SERVICE_CONNECTION__SETTINGS__CLIENTSECRET="<blueprint-app-secret>"
export CONNECTIONS__SERVICE_CONNECTION__SETTINGS__TENANTID="<tenant-guid>"
export A365_AGENT_APP_INSTANCE_ID="<agent-app-instance-id>"
export A365_AGENT_BLUEPRINT_ID="<agent-blueprint-id>"
export A365_CALLER_USER_ID="<caller-user-id>"
export A365_CALLER_USER_EMAIL="<caller-user-email>"
export A365_CALLER_CLIENT_IP="<caller-client-ip>"

uv run --with msal python samples/a365/s2s/s2s_exporter.py
```

`a365_use_s2s_endpoint=True` routes exports to the S2S ingest endpoint. The
tenant and agent ID in each export request must match the configured tenant and
agent app instance client ID; the resolver rejects mismatches before token
acquisition. `gen_ai.agent.id` and the `{agentId}` export URL segment therefore
use `A365_AGENT_APP_INSTANCE_ID`, not the Blueprint client ID.

## Scope and Store-validation coverage

| Scope | Sample behavior | Store validation |
| --- | --- | --- |
| `InvokeAgentScope` | Root request, agent/Blueprint/caller identity, endpoint, input, and final output | Required |
| `InferenceScope` | Model/provider, messages, token usage, and finish reason | Required |
| `ExecuteToolScope` | Tool identity, arguments, and result | Required |
| `OutputScope` | Child span representing asynchronous/final output | Validate before publishing |
| `ApplyGuardrailScope` | Input-safety decision and finding event | Additional security telemetry |

The sample populates the publishing attributes documented in
[Validate for Store publishing](https://learn.microsoft.com/en-us/microsoft-agent-365/developer/observability?tabs=python#validate-for-store-publishing),
including the tenant, agent, Blueprint, human caller, client address, channel,
conversation, operation, message, endpoint, model, and tool fields applicable
to each span. Human caller identity uses the standard `user.id` and
`user.email` attributes. S2S agentic-user attributes
`microsoft.agent.user.id` and `microsoft.agent.user.email` are intentionally
absent.

## Verify export

The sample enables DEBUG logging for the A365 exporter. A successful run reports
the HTTP status and correlation ID on stderr:

```text
DEBUG ...agent365_exporter: HTTP 200 success on attempt 1. Correlation ID: <id>. Response: ...
```

HTTP 401 usually indicates an invalid token audience or tenant. HTTP 403
usually indicates missing `Agent365.Observability.OtelWrite` application
permission, missing admin consent, or an agent/Blueprint identity that is not
onboarded for the tenant. Use the logged correlation ID when investigating
either response.
Loading
Loading