Repository navigation
[Feat]: A2AClient should propagate trace context? #168
Description
Activity
Greetings @jerry-junjie-xu ..I am interested to work on the issue. Can You please assign this to me. ThankYou
I don't seem to have the permission to reassign issues.
Implementation sketch
The cleanest way to propagate trace context is via OpenTelemetry's standard HTTP instrumentation, injecting W3C
traceparent/tracestateheaders into every outgoingA2AClientrequest.Client-side
# src/a2a/client/trace_context.py from opentelemetry import propagate from opentelemetry.trace import get_current_span def inject_trace_context(headers: dict[str, str]) -> dict[str, str]: """Inject W3C trace context into outgoing headers.""" propagate.inject(headers) return headers
Then wire it into the existing transports. For
JsonRpcTransport(httpx-based):# Before making the HTTP call request_headers = dict(self._headers) if self._headers else {} inject_trace_context(request_headers) response = await self._http_client.post( self._url, json=payload, headers=request_headers, )
For
GrpcTransport, use the gRPC OTel instrumentation package which handles this automatically:from opentelemetry.instrumentation.grpc import GrpcAioInstrumentorClient GrpcAioInstrumentorClient().instrument()
Make OTel a soft dependency
To avoid forcing the dep on every user, guard the import:
try: from opentelemetry import propagate _OTEL_AVAILABLE = True except ImportError: _OTEL_AVAILABLE = False def inject_trace_context(headers: dict[str, str]) -> dict[str, str]: if _OTEL_AVAILABLE: propagate.inject(headers) return headers
And expose it through an
otelextra:# pyproject.toml [project.optional-dependencies] otel = ["opentelemetry-api>=1.25", "opentelemetry-instrumentation>=0.46b0"]
Server-side (pairs with #828
On the server, the reverse: extract context from incoming headers so spans created inside the agent become children of the client span:
from opentelemetry import propagate ctx = propagate.extract(dict(request.headers)) with tracer.start_as_current_span("agent.execute", context=ctx): ...
Combined effect
Client calls
message/send→ span A is active →traceparentheader injected → server extracts →agent.executespan B is a child of A → any downstream tools/LLM calls from the agent are grandchildren of A. End-to-end distributed trace across agent boundaries, which is particularly valuable for multi-agent workflows.I can submit a PR implementing this for the JSON-RPC transport first, then extend to REST / gRPC in follow-ups. Worth noting the
telemetry.pyutilities already use OTel internally, so the dependency story is already partially in place.A2AClientwas removed.
Is your feature request related to a problem? Please describe.
A2A py sdk provides OpenTelemetry util lib #and key classes/functions are intrumented.
However, the trace context is not propagated across agent boundries by default.
Describe the solution you'd like
A2AClient propagates trace context.
Describe alternatives you've considered
We can get trace context propagated manually, when we have control over the coding calling A2AClient:
Additional context
No response
Code of Conduct