Skip to content

Semantic Conventions for Agent-to-Agent (A2A) Protocol Telemetry #254

@pwkowalski

Description

@pwkowalski

Proposal: Semantic Conventions for Agent-to-Agent (A2A) Protocol Telemetry

Summary

We propose introducing a standardized telemetry specification for the Agent-to-Agent (A2A) Protocol within OpenTelemetry. This includes defining a dedicated a2a.* attribute namespace, span structures for A2A client and server operations, and standardized metrics for monitoring multi-agent system performance and coordination.


Motivation

As the Agent-to-Agent (A2A) Protocol is adopted across different frameworks and platforms to orchestrate multi-agent workflows, there is currently a lack of standardized OpenTelemetry semantic conventions to represent these interactions.

Without standardized A2A semantic conventions:

  1. Telemetry Fragmentation: Systems implementing the protocol must rely on custom, non-interoperable span names and attributes, making end-to-end tracing fragmented and difficult to parse when a workflow spans different platforms or vendors.
  2. Broken Distributed Tracing: There is no standard specification for propagating trace context and session details within A2A metadata, which makes tracking asynchronous or delegated multi-agent tasks highly challenging.
  3. No Standardized Performance Metrics: Monitoring the health and performance of agent collaborations lacks unified metrics (such as task durations, message exchange volumes, or active state tracking), limiting visibility in standard APM dashboards.

This proposal aims to establish a unified a2a.* namespace for spans, attributes, and metrics to ensure vendor-neutral, out-of-the-box observability for A2A-based communication.


Proposed Spans & Attributes

1. Client-Side Spans (CLIENT Kind)

Emitted by an A2A client (or an initiator agent) when it sends a request to a remote agent.

  • Span Name: {a2a.method.name}
  • Span Status: SHOULD be set to ERROR if the request didn't complete successfully. The status description should match the protocol error message.

GenAI & A2A Specific Attributes:

Status Attribute Type Description Example
New (Shared) a2a.method.name string The name of the executed A2A method as defined by the protocol. "send_message", "send_streaming_message", "get_task", "cancel_task"
New (Shared) a2a.protocol.version string Version of the A2A protocol in use. "v1.0.0"
New (Shared) a2a.protocol.binding string Underlying transport or transport binding used. "JSONRPC", "GRPC", "HTTP+JSON"
New (Shared) a2a.message.id string The unique ID of the A2A message sent in the client request. "msg-user-1234"
New (Shared) a2a.message.referenced_task_ids string[] Array of task IDs referenced or linked in the request. ["task-abc-5678"]
New (Shared) a2a.task.id string The task ID of the started unit of work as returned by the server. "task-xyz-9012"
New (Shared) a2a.task.state string State of the task as reported in the response. "submitted", "working", "input-required", "completed", "failed"
New (Shared) a2a.task.artifact_ids string[] Artifact IDs associated with the task returned in the response. ["art-001", "art-002"]
New (Client-only) a2a.agent.card.url string The endpoint URL of the target A2A agent's Agent Card. "https://a2a-protocol.org/example/a2a/v1/card"
New (Shared) a2a.protocol.requested_extensions string[] Protocol extensions requested by the client. ["https://a2a-protocol.org/example/extensions/auth-forward/v1"]
Existing (Shared) gen_ai.operation.name string Name of the GenAI operation being performed. "invoke_agent"
Existing (Shared) gen_ai.conversation.id string The unique identifier for a conversation (session, thread), used to store and correlate messages within this conversation. "conv_5j66UpCpwteGg4YSxUnt7lPY"

gen_ai.conversation.id Development Conditionally Required when available string The unique identifier for a conversation (session, thread), used to store and correlate messages within this conversation. [4] conv_5j66UpCpwteGg4YSxUnt7lPY

Shared Transport & RPC Attributes (Reused):

We recommend reusing the following standard, existing OpenTelemetry network and RPC conventions:

Status Attribute Type Description Example
Existing (Client-only) server.address string Server domain name or IP address. "127.0.0.1"
Existing (Client-only) server.port int Server port number. 8000
Existing (Shared) network.protocol.name string OSI application layer protocol name. "http"
Existing (Shared) network.protocol.version string Actual version of the protocol used. "1.1"
Existing (Shared) network.transport string Underlying transport protocol. "tcp"
Existing (Shared) jsonrpc.request.id string A string representation of the id property of the request and its corresponding response. Required when JSONRPC transport is used. "request-1234"
Existing (Shared) jsonrpc.protocol.version string Protocol version. Required when JSONRPC transport is used. "2.0"
Existing (Shared) rpc.response.status_code string A string representation of the error code from the JSON-RPC or gRPC response. Required when gRPC transport is used and conditionally required if available and JSONRPC transport is used. "OK", "DEADLINE_EXCEEDED", "-32602"
Existing (Shared) rpc.method string The fully-qualified logical name of the method from the RPC interface perspective. Required when gRPC transport is used. "SendMessage", "SendStreamingMessage"
Existing (Shared) http.request.method string HTTP request method. Required when HTTP+JSON transport is used. "GET", "POST", "DELETE"
Existing (Shared) http.response.status_code int HTTP response status code. Required when HTTP+JSON transport is used. 200, 400
Existing (Shared) http.route string The matched route template for the request. This MUST be low-cardinality and include all static path segments, with dynamic path segments represented with placeholders. Required when HTTP+JSON transport is used. "/message:send", "/tasks/{taskId}"

2. Server-Side Spans (SERVER Kind)

Emitted by the target agent when it receives and processes an incoming A2A request.

  • Span Name: {a2a.method.name}
  • Span Status: SHOULD be set to ERROR if the request didn't complete successfully. The status description should match the protocol error message.

GenAI & A2A Specific Attributes:

Status Attribute Type Description Example
New (Shared) a2a.method.name string The name of the incoming A2A method. "send_message"
New (Shared) a2a.protocol.version string Version of the A2A protocol used by the server. "v1.0.0"
New (Shared) a2a.protocol.binding string Transport used to receive the call. "GRPC"
New (Shared) a2a.message.id string The ID of the received A2A message. "msg-user-1234"
New (Shared) a2a.message.referenced_task_ids string[] The task IDs referenced in the incoming request payload. ["task-abc-5678"]
New (Shared) a2a.task.id string The task ID of the unit of work created/managed on the server. "task-xyz-9012"
New (Shared) a2a.task.state string The current execution state of the local task. "working"
New (Shared) a2a.task.artifact_ids string[] IDs of artifacts generated by the task so far. ["art-001"]
New (Shared) a2a.protocol.requested_extensions string[] Extensions requested by the inbound client. ["https://a2a-protocol.org/example/extensions/auth-forward/v1"]
New (Server-only) a2a.protocol.activated_extensions string[] Extensions successfully activated by the server for this request. ["https://a2a-protocol.org/example/extensions/auth-forward/v1"]
Existing (Shared) gen_ai.operation.name string Name of the GenAI operation. "invoke_agent"
Existing (Shared) gen_ai.conversation.id string The unique identifier for a conversation (session, thread), used to store and correlate messages within this conversation. "conv_5j66UpCpwteGg4YSxUnt7lPY"

Shared Transport & RPC Attributes (Reused):

We recommend reusing the following standard, existing OpenTelemetry network and RPC conventions the same way we did with the CLIENT span kind:

Status Attribute Type Description Example
Existing (Client-only) server.address string Server domain name or IP address. "127.0.0.1"
Existing (Client-only) server.port int Server port number. 8000
Existing (Shared) network.protocol.name string OSI application layer protocol name. "http"
Existing (Shared) network.protocol.version string Actual version of the protocol used. "1.1"
Existing (Shared) network.transport string Underlying transport protocol. "tcp"
Existing (Shared) jsonrpc.request.id string A string representation of the id property of the request and its corresponding response. Required when JSONRPC transport is used. "request-1234"
Existing (Shared) jsonrpc.protocol.version string Protocol version. Required when JSONRPC transport is used. "2.0"
Existing (Shared) rpc.response.status_code string A string representation of the error code from the JSON-RPC or gRPC response. Required when gRPC transport is used and conditionally required if available and JSONRPC transport is used. "OK", "DEADLINE_EXCEEDED", "-32602"
Existing (Shared) rpc.method string The fully-qualified logical name of the method from the RPC interface perspective. Required when gRPC transport is used. "SendMessage", "SendStreamingMessage"
Existing (Shared) http.request.method string HTTP request method. Required when HTTP+JSON transport is used. "GET", "POST", "DELETE"
Existing (Shared) http.response.status_code int HTTP response status code. Required when HTTP+JSON transport is used. 200, 400
Existing (Shared) http.route string The matched route template for the request. This MUST be low-cardinality and include all static path segments, with dynamic path segments represented with placeholders. Required when HTTP+JSON transport is used. "/message:send", "/tasks/{taskId}"

Proposed Metrics

To successfully monitor multi-agent systems over time, we propose the following standard metric instruments:

Metric Name Instrument Unit Description Attributes
a2a.client.operation.duration Histogram s Client-observed latency from sending a request to receiving the response/ack. a2a.method.name, rpc.response.status_code
a2a.server.operation.duration Histogram s Server-observed latency for handling the inbound request. a2a.method.name, rpc.response.status_code
a2a.server.task.duration Histogram s The continuous lifespan of a background task, from submission to terminal state. a2a.task.state
a2a.server.task.in_progress UpDownCounter {task} The active volume of tasks in non-terminal states. a2a.task.state ("submitted", "working", "input-required", etc.)
a2a.server.task.artifacts_count Histogram {artifact} Number of structured artifacts generated during the lifecycle of a single task. a2a.task.state
a2a.server.task.message_count Histogram {message} Number of communication messages exchanged over the course of a task. a2a.task.state

Metric Note on High Cardinality

Individual a2a.task.id or a2a.message.id values MUST NOT be used as metric attributes, as they would violate OpenTelemetry cardinality guidelines and cause memory issues in backends.

Additionally, if the attribute names decided in #243 are determined to be high-cardinality dynamic values (such as carrying a user ID or dynamic session token) rather than a static agent class name (e.g., "Math Tutor"), instrumentations SHOULD NOT populate these attributes on metrics, or they MUST sanitize/mask it to preserve backend metric performance. High-cardinality correlations should be achieved solely via distributed traces and span links connecting the respective IDs.

Identified gaps

  • An open question about tracing for streaming. As it stands, there's no information about intermediate state of a streaming task.
  • introducing attributes from How to represent multiple agents on the same telemetry #243 after they're decided on.
  • a2a.agent.card.url is dubious. It might be unnecessary.

It might be good for those to be a follow-up.


References:

A2A Protocol specification: https://a2a-protocol.org/latest/specification/
JSON+RPC semantic conventions: https://opentelemetry.io/docs/specs/semconv/rpc/json-rpc/
HTTP semantic conventions: https://opentelemetry.io/docs/specs/semconv/registry/attributes/http/
gRPC semantic conventions: https://opentelemetry.io/docs/specs/semconv/rpc/grpc/
GenAI semantic conventions: https://opentelemetry.io/docs/specs/semconv/registry/attributes/gen-ai/

Related:
#24
#51
#70 - in particular, I believe our proposal should be a superset of this one. @xiaocang if you could give your feedback as well it would be great.


Edit 1 (6/9/26)

Removing Context Propagation as it's out of scope for Semantic Conventions, and too restrictive either way.

Adding gen_ai.conversation.id.

Edit 2 (6/12/26)

Removing gen_ai.agent.name and gen_ai.agent.id for now - it will be aligned with #243.
Potentially relevant:

Adding identified gaps.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    New issues

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions