Proposal: Distributed Tracing Semantic Conventions for A2A
- Linguagem predominante
- Shell
- Estrelas
- 25.7k
- Forks
- 2.6k
- Merge médio
- 3d 6h
- PRs com merge (30d)
- 16
Descrição
### 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.
Guia de contribuição
Avaliação
Esta issue ainda não foi avaliada.