[Feat]: Add RetryTransport for automatic retry with exponential backoff
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 45/100
Research direction
Look at the existing transport classes (JsonRpcTransport, RestTransport, GrpcTransport) and the TenantTransportDecorator pattern. The new RetryTransport must wrap any ClientTransport. Start by examining the SDK's exception hierarchy (A2AClientError, A2AClientTimeoutError) and how they chain httpx and grpc errors. Write tests for the retry predicate and the on_retry hook. Ensure the implementation works for all three transports and does not retry domain errors.
Written by the indexing model from the issue text.
Description
Is your feature request related to a problem? Please describe.
The SDK's transports (JsonRpcTransport, RestTransport, GrpcTransport) raise immediately on transient failures (network errors, timeouts, rate limits, 5xx responses, gRPC UNAVAILABLE/RESOURCE_EXHAUSTED) with no built-in retry mechanism. Every caller has to reimplement the same retry/backoff loop, and to do it correctly they have to inspect __cause__ chains because A2AClientError doesn't expose HTTP status codes or gRPC codes directly.
Describe the solution you'd like
A RetryTransport decorator wrapping any ClientTransport, mirroring the existing TenantTransportDecorator pattern:
inner = JsonRpcTransport(httpx_client=client, agent_card=card)
transport = RetryTransport(base=inner, max_retries=3)
The default predicate retries on:
A2AClientTimeoutError(always).A2AClientErrorchained fromhttpx.RequestErrororhttpx.HTTPStatusError(408/429/502/503/504).A2AClientErrorchained fromgrpc.aio.AioRpcError(UNAVAILABLE/RESOURCE_EXHAUSTED).- Domain errors (
TaskNotFoundError, etc.) are never retried.
retry_predicate is configurable for custom logic, and on_retry is exposed as a hook for logging/metrics. Streaming methods (send_message_streaming, subscribe) only retry before the first event is yielded.
Describe alternatives you've considered
- Retry via
ClientCallInterceptor— not feasible;after()only fires on successful results, so interceptors never see exceptions. - Transport-specific retry (httpx custom transport, gRPC
retryPolicy/UnaryUnaryClientInterceptor) — operates below the SDK's exception layer, requires two separate configurations, and doesn't cover all three transports uniformly. - Retry inside each transport implementation — triples the logic across
JsonRpcTransport,RestTransport,GrpcTransportand forces every future transport to reimplement it.
Additional context
Purely additive: new RetryTransport class, tests, and one export change. No new dependencies — the grpc import is conditional, matching the SDK's existing pattern. ClientFactory integration is left as a follow-up.
Code of Conduct
- I agree to follow this project's Code of Conduct
- Dominant language
- Python
- Stars
- 2.2k
- Forks
- 496
- Avg merge
- 2d 6h
- Merged PRs (30d)
- 19
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from a2aproject/a2a-python
-
component: server status:awaiting response
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
a2aproject/a2a-python#1237 · 2 comments · 1 assignee ·
-
component: server status:awaiting response status:stale
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
a2aproject/a2a-python#1215 · 2 comments · 1 assignee ·
-
component: server status:awaiting response status:stale
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
a2aproject/a2a-python#1205 · 3 comments · 1 assignee ·
-
component: server status:awaiting response status:stale
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
a2aproject/a2a-python#1204 · 2 comments · 1 assignee ·
-
component: server
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
a2aproject/a2a-python#1192 · 3 comments · 1 assignee ·
All issues in a2aproject/a2a-python
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
stephrobert/dsoxlab#238 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
sublimehq/package_control#1780 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 70/100
nwg-piotr/nwg-displays#145 ·