fix(a2a): Port event action allowlist, agent card description source and resume flattening to v1 - #6801
Merged
Conversation
Port of the same fix from main. Before, `_extract_event_actions` rebuilt an `EventActions` from whatever the remote peer put in the `adk_actions` metadata of a message, task, status update or artifact update, and every field on it was honored. A peer could therefore set the calling agent's session state and artifact deltas, request credentials or tool confirmations on the caller's behalf, transfer the caller to another agent, overwrite agent state, inject a compaction, or rewind the caller's invocation. Now only an explicit allowlist of inert fields (`escalate` and `skip_summarization`, in both spellings) is honored and everything else is dropped with a debug log. Because it is an allowlist, a field added to `EventActions` later is denied by default. Behaviour change: an ADK agent calling another ADK agent over A2A no longer has the peer's `state_delta` and `artifact_delta` applied to its own session. Event actions describe the sending agent's own session and no longer cross the peer boundary. The sending side is unchanged, so the metadata is still serialized outbound; only the receiving side ignores it. There is no flag to restore the old behaviour. Also ports the follow-up test that pins the allowlist against regressions.
Port of the same fix from main. The agent card served by `to_a2a()` at the well-known card path is a discovery document with no authentication in front of it. Before, the primary skill's description was built by concatenating the agent's description, its `instruction` and its `global_instruction` with the pronouns rewritten, and when no ExampleTool was declared the skill's `examples` were mined out of the instruction text with a regex looking for quoted `Example Query:` pairs. Both published the agent's system prompt. Now the description comes from `agent.description` alone and examples come only from a declared ExampleTool. Behaviour change: the card no longer contains `agent.instruction` or `agent.global_instruction`, and no longer contains examples mined out of the instruction text. Cards for agents that set an instruction get shorter and some `examples` lists become empty. To publish richer card text, put it in `agent.description`; to publish examples, declare an ExampleTool. Only `to_a2a()` is affected, because `adk api_server` serves a static agent.json and does not use the builder. Removes `_build_llm_agent_description_with_instructions`, `_replace_pronouns` and `_extract_examples_from_instruction`, along with the now-unused `re` import.
Port of the same fix from main.
Before, when an invocation resumed after a pause, RemoteA2aAgent only rewrote
the function response to text if the pausing call was the mock input-required
call, and forwarded everything else to the remote peer exactly as it sat in
the session. A reply to adk_request_credential is a serialized AuthConfig
carrying raw_auth_credential and exchanged_auth_credential, so the user's
access tokens and client secrets were shipped to the peer. A reply to
adk_request_input or adk_request_confirmation was forwarded as a function
response beside the user's text, which is the combination Runner rejects with
"Message cannot contain both function responses and text".
Now every human-input pause response is matched by the pending function call
name and flattened to text before forwarding. Credential payloads are dropped
rather than forwarded, recognized both by call name and by the shape of a
serialized AuthConfig, so a credential arriving under an innocuous name is
still dropped. Genuine long-running tool responses are preserved as data so
the peer can still resume them by id, and when any response is preserved the
message stays a pure resume with no text alongside it. A second guard in the
history-reconstruction fallback stops a dropped credential re-entering that
way.
Behaviour change: a peer that was receiving human-input function responses as
structured data now receives the answer as a text part, so a peer parsing the
{"result": ...} envelope has to read the text instead. A resume that carried
nothing but a credential now produces no message at all and falls through to
history reconstruction.
Also fixes a latent crash that the sanitizer makes reachable: this branch
dereferenced the converted message without checking it, and the converter
returns None for an event with no parts, so a resume whose parts were all
dropped raised AttributeError. It now returns None and lets the caller fall
back to history.
DeanChensj
approved these changes
Aug 19, 2026
GWeale
force-pushed
the
backport-v1-pr12
branch
from
August 19, 2026 19:18
4a02d4f to
8325f3b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ports three A2A changes from
mainto thev1branch, one commit each.Restrict which event action fields are rebuilt from peer metadata(0ba7d3cb, testcfd09e09)adk_actionsmetadata sets onlyescalateandskip_summarization; other fields are dropped with a debug log. All four converters share the allowlist, so a field added later is denied by default.state_delta,artifact_deltaand the other eight action fields no longer cross the peer boundary, with no flag to restore them. Have the A2A sub-agent return that data in its response content and let the parent write it into its own session.Build the agent card skill description from agent.description only(efdecf4c)agent.description;examplescome from a declaredExampleTool.to_a2a()no longer carries instruction text or examples mined from it. Put publishable text inagent.descriptionand declare anExampleToolfor examples.Flatten human-input responses on resume(aec7aa33)AuthConfigshape.Noneand falls back to history reconstruction.