Distributed observability in applications with A2A and MCP#
While developing applications composed of multiple agents, I encountered a recurring observability problem. A request would start in an orchestrator, move to another agent over A2A, pass through an MCP service, and return to the original process. Each component produced telemetry, but reconstructing the complete execution required correlating timestamps, logs, and business identifiers.
This type of architecture extends the boundaries of an operation. The flow may cross different processes, services, and protocols while still representing a single request to the person using the system. When tracing context is lost at one of these transitions, subsequent spans become part of other traces and the investigation becomes fragmented.
Context propagation between services#
W3C Trace Context provides a standardized format for carrying trace identity. The service initiating a call injects the headers and , and the receiving service uses that information when creating its own spans. This keeps the relationship between operations available to any OpenTelemetry-compatible backend.
Applying this mechanism to A2A and MCP depends on the extension points offered by their respective SDKs. In the A2A Python SDK, the context needs to accompany client calls and be recovered by the server handler. In MCP, the current implementation uses the public HTTP boundaries of the client and of the ASGI application created by the server.
During this work, I tried to avoid depending on internal SDK details. The adapters use public interfaces and delegate behavior to the original objects. This reduces the impact of updates and allows instrumentation to be added to an existing application without replacing its business implementation.
a2a-otel-kit#
I organized this implementation in the a2a-otel-kit project, a Python library distributed through PyPI under the MIT license. It brings together OpenTelemetry configuration, OTLP/HTTP export, W3C Trace Context propagation, structured JSON events, and adapters specific to A2A and MCP.
The A2A integration covers client and server calls over JSON-RPC and REST transports. The MCP integration covers Streamable HTTP through an instrumented HTTP transport on the client and ASGI middleware on the server. Both integrations create client and server spans, propagate existing context, and preserve the behavior of the original calls, including exceptions, cancellations, and early stream termination.
The instrumentation lifecycle is also explicit. Each instance owns its resources and provides and operations. Disabled configuration produces inactive spans, allowing the application to use the same code in environments with or without tracing.
Export uses OTLP/HTTP, leaving the backend choice to the application. The demonstration environment uses Grafana Tempo, but traffic can be routed through an OpenTelemetry Collector to other compatible destinations. The library does not include vendor-specific SDKs.
Handling telemetry data#
The instrumentation was designed to record operational metadata with controlled cardinality. Adapter spans use fixed names, known operation types, and a restricted list of attributes. Keys related to passwords, tokens, cookies, authorization, and credentials are discarded by the sanitizer.
The adapters do not read prompts, model responses, A2A messages, task or artifact contents, MCP arguments and results, HTTP bodies, or arbitrary header values. If a failure occurs, the span receives the corresponding status, but the exception message is not copied into the telemetry produced by the adapters.
This decision arose from a practical concern. In applications that process personal data, documents, or business information, copying interaction content to an observability platform creates another storage and access surface. For this project, details needed for functional analysis should remain in the systems responsible for that data.
The API allows the application to create its own spans and events. In these cases, the consuming code is responsible for deciding what information is appropriate, always passing through the attribute controls available in the library.
Verification with a complete execution#
The repository contains a local demonstration comprising an orchestrator, an A2A risk-analysis agent, and an MCP data service. The environment includes OpenTelemetry Collector, Grafana Tempo, and Grafana, with all configuration needed to run the flow in containers.
In the documented execution, the request generates 11 spans distributed across the three services. The A2A client and server spans remain in the same trace, and MCP calls initiated by the agent continue using that context. The result can be inspected in Grafana, where the tree shows the complete operation sequence.
In addition to visual inspection, a script verifies the data stored in Tempo. It looks for the expected spans, compares their , and searches for a private identifier deliberately inserted into the business response. The execution is considered valid only when the spans belong to the same trace and the identifier is absent from telemetry.
Current limitations#
The current version focuses on integrations that could be tested end to end. In A2A, continuity was verified for JSON-RPC and REST. Calls originating over gRPC still produce spans, but context propagation over that transport remains unverified.
In MCP, support is limited to Streamable HTTP. The stdio transport has different characteristics and does not expose the same HTTP boundary used by the adapters. Legacy SSE was also left out of scope.
The project handles instrumentation and OTLP delivery. Production configuration of the Collector, retention, sampling, backend authentication, and scalability belong to the consuming application's infrastructure.
Next steps#
I plan to test the library with other agent arrangements and follow the evolution of the official SDKs. Topics that still deserve work include A2A continuity over gRPC, other MCP deployment contexts, and examples using agent-orchestration frameworks.
The code, documentation, and demonstration are available at:
GitHub: https://github.com/brunovicco/a2a-otel-kit PyPI: https://pypi.org/project/a2a-otel-kit/
Comments on the API, instrumentation points, and observability experiences in distributed agent systems will help guide the next versions.