Skip to content

fix(a2a): default AgentCardBuilder capabilities to streaming=True - #6673

Open
chelsealong wants to merge 1 commit into
google:mainfrom
chelsealong:fix-a2a-card-streaming-capability-6672
Open

fix(a2a): default AgentCardBuilder capabilities to streaming=True#6673
chelsealong wants to merge 1 commit into
google:mainfrom
chelsealong:fix-a2a-card-streaming-capability-6672

Conversation

@chelsealong

Copy link
Copy Markdown
Contributor

Fixes #6672

Problem

An agent published with to_a2a() serves an agent card whose
capabilities.streaming is false, even though the handler to_a2a()
mounts (DefaultRequestHandler) implements message/stream. Peers that
read the card to decide how to call the agent are told streaming is
unavailable, so they fall back to unary calls and lose incremental output
for no reason.

Root cause: AgentCardBuilder.__init__ defaulted
self._capabilities to AgentCapabilities() (which itself defaults
streaming=False) whenever the caller didn't pass capabilities
explicitly, and to_a2a() never passes capabilities to
AgentCardBuilder. Since _compat.build_agent_card() uses the passed
capabilities object directly (falling back to its own streaming
default only when capabilities is None), the always-non-None
default from AgentCardBuilder silently pinned every to_a2a() card
to streaming: false, regardless of what the mounted handler actually
supports.

Fix

AgentCardBuilder now defaults its capabilities to
AgentCapabilities(streaming=True) instead of AgentCapabilities().
This is the minimal change that makes the default card reflect
what to_a2a() actually serves. Callers who pass an explicit
capabilities= argument are unaffected.

Testing plan

Added an assertion to the existing
test_init_with_valid_agent test in
tests/unittests/a2a/utils/test_agent_card_builder.py asserting
builder._capabilities.streaming is True by default.

Verified the test fails without the fix and passes with it:

$ git stash push -- src/google/adk/a2a/utils/agent_card_builder.py
$ python3 -m pytest tests/unittests/a2a/utils/test_agent_card_builder.py::TestAgentCardBuilder::test_init_with_valid_agent -q
FAILED ...test_init_with_valid_agent - assert False is True
1 failed, 5 warnings in 2.19s
$ git stash pop
$ python3 -m pytest tests/unittests/a2a/utils/test_agent_card_builder.py::TestAgentCardBuilder::test_init_with_valid_agent -q
1 passed

Full a2a unit test suite passes with the fix applied:

$ python3 -m pytest tests/unittests/a2a/ -q
441 passed, 45 skipped, 691 warnings in 4.63s

isort and pyink (per this repo's pre-commit config) report both
changed files as already formatted correctly.

AI-assistance disclosure

This change was prepared with the help of an AI coding agent
(Claude), including drafting the fix, tests, and this PR description.
The change was reviewed and verified locally before submission.

@chelsealong

Copy link
Copy Markdown
Contributor Author

Closing this — @arunpshankar said on #6672 that they want to work on it, and the note I left there promised to drop mine if someone was already on it. If any of this diff is useful, take it freely.

@arunpshankar

Copy link
Copy Markdown
Contributor

@chelsealong please reopen this. That was ambiguous wording on my part and I am sorry for the churn.

The offer to send a PR was about #6778, the separate issue I filed at @surajksharma07's request. It was not a claim on this one. I am not working on this change and have no diff for it.

This PR is the fix for #6672 and @surajksharma07 said on #6672 that it was moving toward merge as-is. #6778 is deliberately downstream of it: the dead streaming= parameter only becomes unreachable once this default lands, and the agent_registry call site is untouched by either. Nothing in #6778 competes with this diff or should hold it up.

Happy to re-confirm it on a clean install if that helps it move.

@chelsealong

Copy link
Copy Markdown
Contributor Author

Reopened — thank you for the correction, and no apology needed on your side; the mistake was mine.

I read your note on #6672 as a claim on this change and closed on that basis. It wasn't ambiguous on your part: you were talking about #6778, and I did not check that the two were separate before acting. @surajksharma07's note that this was moving toward merge as-is was on the issue rather than here, which is exactly where I should have looked.

The branch is behind main; I'll rebase it now so the checks run clean. Nothing else about the diff has changed.

@chelsealong

Copy link
Copy Markdown
Contributor Author

Branch updated with main (merge commit 29d7df4) via GitHub's update-branch endpoint — the a2a fix itself (agent_card_builder.py and its test) is unchanged, byte-for-byte identical before and after. Checks are running on the updated branch now.

@sharaprahersini

Copy link
Copy Markdown

We need to add rate limiting to the auth middleware before this merges.
Also, the README is outdated — someone should update the setup instructions.

@chelsealong

Copy link
Copy Markdown
Contributor Author

@sharaprahersini could you clarify how the rate limiting relates to this change?

This PR is +5/-1 across two files. It sets AgentCardBuilder's default
capabilities.streaming to True so a card built without an explicit value
advertises what the server actually supports; it does not touch the auth
middleware, request handling, or the setup documentation.

If rate limiting on the auth middleware is a gap you have hit, that seems worth
its own issue — I am happy to open one with a repro if you can point me at the
path you mean. Same for the setup instructions; I can send a separate docs PR
rather than widening this one.

If the concern is instead that defaulting streaming=True could increase load,
I can add that to the PR description with the reasoning: the default only
changes what the card advertises, and AgentCardBuilder already required
callers to opt out explicitly for the non-streaming case elsewhere in the
codebase.

to_a2a() always mounts a DefaultRequestHandler that implements
message/stream, but AgentCardBuilder defaulted to
AgentCapabilities() (streaming=False) whenever a caller didn't pass
capabilities explicitly. Peers reading the served card were told
streaming was unavailable and fell back to unary calls even though
the server supported it.

Fixes google#6672
@chelsealong
chelsealong force-pushed the fix-a2a-card-streaming-capability-6672 branch from 29d7df4 to 2d54545 Compare September 3, 2026 00:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core [Component] This issue is related to the core interface and implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

to_a2a() serves an agent card with capabilities.streaming=false while the mounted handler implements message/stream

5 participants