Skip to content

fix(client): add extra_params option to RestTransport for provider-specific query params (Fixes #1089)#1124

Open
isheng-eqi wants to merge 2 commits into
a2aproject:mainfrom
isheng-eqi:fix/stream-extra-params-1089
Open

fix(client): add extra_params option to RestTransport for provider-specific query params (Fixes #1089)#1124
isheng-eqi wants to merge 2 commits into
a2aproject:mainfrom
isheng-eqi:fix/stream-extra-params-1089

Conversation

@isheng-eqi

Copy link
Copy Markdown

Summary

Add an extra_params option to RestTransport and CompatRestTransport that allows injecting query parameters (such as {'alt': 'sse'} for Google A2A API) into every streaming request URL. This resolves issue #1089 where Google's transcoding layer wraps SSE responses inside JSON arrays unless ?alt=sse is appended.

Problem

When connecting to Google A2A API endpoints, the transcoding layer wraps streaming RPC responses inside JSON arrays [{...}] by default. The SDK's RestTransport parses these using json_format.Parse, which expects a single JSON object {...}, causing a crash:

google.protobuf.json_format.ParseError: Failed to parse {'task': {...}} field: unhashable type: 'dict'.

Adding ?alt=sse tells Google to use standard SSE formatting.

Changes

  • src/a2a/client/transports/rest.py — Accept optional extra_params dict in __init__, pass to send_http_stream_request via params kwarg
  • src/a2a/compat/v0_3/rest_transport.py — Same extra_params support for v0.3 compat transport
  • src/a2a/client/client.py — Add extra_params to ClientConfig
  • src/a2a/client/client_factory.py — Thread extra_params from config to transport constructors

Usage

# One-liner opt-in for Google A2A API:
config = ClientConfig(extra_params={'alt': 'sse'})
factory = ClientFactory(config)
client = await factory.create_from_url('https://agent.example.com')

# Or via convenience function:
client = await create_client('https://agent.example.com', ClientConfig(extra_params={'alt': 'sse'}))

Test Plan

  • 3 new tests for RestTransport (params passed, None safe, empty dict safe)
  • 1 new test for CompatRestTransport (params passed)
  • Existing test updated (CompatRestTransport now includes params=None in call args)
  • ruff check + ruff format + ty check pass
  • Compat transport module: 100% coverage
  • Rest transport module: 80% coverage (new paths covered)

Closes #1089

…ecific query params (Fixes a2aproject#1089)

Add an extra_params option to RestTransport and CompatRestTransport that
allows injecting query parameters (such as {'alt': 'sse'} for Google
A2A API) into every request URL. This resolves the streaming crash
where Google's transcoding layer wraps SSE responses inside JSON arrays
unless ?alt=sse is appended.

Changes:
- RestTransport: accept optional extra_params dict, pass to stream reqs
- CompatRestTransport: same extra_params support
- ClientConfig: add extra_params field
- ClientFactory: thread extra_params from config to transport constructors
- Tests: verify params are forwarded; verify None/empty dict are safe

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces an extra_params configuration option to ClientConfig to allow appending optional query parameters to request URLs, passing it down to RestTransport and CompatRestTransport for streaming requests. Feedback suggests extending this support to non-streaming requests to align with the documentation, and copying the extra_params dictionary during initialization to prevent external mutations.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

self._handle_http_error,
self._handle_sse_error,
json=json,
params=self._extra_params or None,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The extra_params are currently only appended to streaming requests via _send_stream_request. However, the documentation for ClientConfig.extra_params and RestTransport states that these are 'Optional query parameters to append to every request URL.' Non-streaming requests (which go through _execute_request) do not currently receive these parameters.

To ensure consistency and correctness, _execute_request should also merge self._extra_params with any method-specific params before building the request.

Comment thread src/a2a/client/transports/rest.py Outdated
self.url = url.removesuffix('/')
self.httpx_client = httpx_client
self.agent_card = agent_card
self._extra_params = extra_params or {}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

low

It is safer to create a copy of the passed extra_params dictionary to prevent any external mutations to the dictionary from unexpectedly affecting the transport's behavior.

Suggested change
self._extra_params = extra_params or {}
self._extra_params = dict(extra_params) if extra_params else {}
References
  1. For consistency, prefer using conditional expressions (ternary operators) for simple assignments over if/else blocks.

@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

🧪 Code Coverage (vs main)

⬇️ Download Full Report

Base PR Delta
src/a2a/client/client.py 96.88% 97.06% 🟢 +0.18%
src/a2a/client/transports/rest.py 89.89% 89.58% 🔴 -0.30%
src/a2a/compat/v0_3/rest_transport.py 100.00% 97.45% 🔴 -2.55%
Total 92.99% 92.94% 🔴 -0.05%

Generated by coverage-comment.yml

…ict on init

- Apply extra_params to _execute_request (non-streaming) in both
  RestTransport and CompatRestTransport
- Merge extra_params with per-request params; extra_params take
  precedence as provider-level requirements
- Copy extra_params dict on init to prevent external mutation
  (dict(extra_params) instead of direct reference)
- Add 5 new tests: non-streaming params, dict isolation, merge logic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Response Stream Array-Wrapping Crash (Transport Layer Mismatch)

1 participant