Proposal: Distributed Tracing Semantic Conventions for A2A
- Vorherrschende Sprache
- Shell
- Sterne
- 25.7k
- Forks
- 2.6k
- Ø Merge
- 3 T. 6 Std.
- Gemergte PRs (30 T.)
- 16
Beschreibung
### Abstract
When Agent A delegates a task to Agent B via A2A, the trace breaks. The Python SDK creates spans locally (via `@trace_class`) but there's no standard way to propagate W3C Trace Context between agents. Each delegation starts a fresh, disconnected trace. This makes it impossible to see a full delegation chain in Jaeger, Grafana, or any OTel-compatible backend.
This proposal defines how trace context flows between A2A agents and what the resulting spans should look like (names, attributes, parent-child relationships), so that instrumentation libraries and SDKs converge on the same conventions.
### Motivation
I've been working with OpenTelemetry GenAI semantic conventions and running multi-agent systems in production. Three things keep coming up:
**Traces disconnect at delegation boundaries.** The `a2a-python` SDK traces request handlers on the server side, but when a client calls `message/send` to another agent, there's no mechanism to inject `traceparent` into the request and extract it on the other end. You get two separate traces instead of one connected tree. Every team I've seen solves this differently.
**Everyone invents their own attribute names.** The Traceability Extension sample uses `TraceRecord`/`TraceStep` with custom fields. Third-party libraries like traceAI use `a2a.task_id`. The CoSAI/OASIS ws2-defenders effort uses `task.id`. The Python SDK's built-in telemetry doesn't tag spans with task or agent identifiers at all. When you switch tools or vendors, your dashboards break because nothing agrees on what to call things.
**No guidance on span structure.** Should `message/send` produce one CLIENT span on the caller and one SERVER span on the receiver (like HTTP)? What about streaming via `tasks/sendSubscribe`? When an agent delegates to a sub-agent, is that a child span or a link? People make reasonable but incompatible choices here.
### Relationship to Existing Work
The Traceability Extension sample in a2a-samples demonstrates call-chain recording using a custom JSON format. It's useful for debugging but doesn't integrate with OTel backends. Issue #2026 proposes W3C header propagation specifically for A2A-to-MCP cross-protocol bridging. This proposal complements both by defining the semantic conventions that give propagated traces consistent meaning across implementations.
The OTel GenAI semantic conventions already define `gen_ai.agent.name`, `gen_ai.operation.name`, and span patterns like `invoke_agent {name}`. This proposal follows those same patterns for A2A-specific operations rather than inventing a parallel naming scheme.
### Proposed Scope
Narrowly scoped to tracing only. No metrics, cost propagation, or log correlation in v1.
**Context propagation.** Trace context (W3C `traceparent` and `tracestate`) travels in message metadata under the extension's URI key:
```json
{
"metadata": {
"": {
"traceparent": "00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01",
"tracestate": "a2a=weather-agent"
}
}
}
```
No baggage in v1. Baggage propagates to all downstream services in plaintext, which creates a data leakage vector in multi-tenant agent deployments.
**Span naming.** Following the OTel GenAI `{operation} {target}` pattern:
| Operation | Span Name | Kind |
|-----------|-----------|------|
| Client sends message | `invoke_agent {agent_name}` | CLIENT |
| Client gets task | `get_task {task_id}` | CLIENT |
| Client cancels task | `cancel_task {task_id}` | CLIENT |
| Server processes message | `process_message` | SERVER |
| Server delegates to sub-agent | `invoke_agent {agent_name}` | CLIENT |
**Semantic attributes.** Reusing OTel GenAI conventions where they exist, adding only what's A2A-specific:
| Attribute | Source | Description |
|-----------|--------|-------------|
| `gen_ai.agent.name` | OTel GenAI (existing) | Name of the target agent |
| `gen_ai.operation.name` | OTel GenAI (existing) | Method name, e.g. `message/send` |
| `a2a.task.id` | New | A2A task identifier |
| `a2a.task.state` | New | Terminal task state |
| `a2a.method` | New | JSON-RPC method name |
Three new attributes total. Everything else reuses what OTel already defines.
**Activation.** Standard `A2A-Extensions` header negotiation. Agents that support the extension extract `traceparent` from metadata and create child spans under the propagated context. Agents that don't support it simply ignore the metadata.
### Deliverables
1. Semantic conventions document covering attribute names, span structures, and propagation rules
2. Python reference implementation as a `ClientCallInterceptor` on the client side and middleware on the server side
3. End-to-end example showing a correlated trace across a two-agent delegation
Happy to start with a reference implementation and iterate based on maintainer feedback.
Beitragsleitfaden
Rechercherichtung
The proposal defines semantic conventions for distributed tracing in the A2A protocol. Start by reading the existing Python SDK's telemetry code, likely in `a2a-python`, focusing on `@trace_class` decorators and client/server interceptors. Review the OpenTelemetry GenAI semantic conventions to understand the `gen_ai.agent.name` and `gen_ai.operation.name` patterns. The implementation will involve modifying the client to inject `traceparent` into message metadata and the server to extract it, creating connected spans. Check for existing examples in the `a2a-samples` repository, particularly the Traceability Extension sample. A successful implementation will produce a single, correlated trace across a multi-agent delegation when viewed in Jaeger or Grafana.
Vom Indexierungsmodell aus dem Issue-Text verfasst.
Bewertung
- Tech-Stack
- python
- Bereich
- backend-api-design, observability
- Issue-Typ
- Feature
- Schwierigkeit
- 4/5
- Geschätzter Aufwand
- 3-5 Tage
- Aktivitätsstatus
- Aktiv
- Klarheit
- Klar beschrieben
- Anfängerfreundlichkeit
- 45/100