Skip to content

fix(a2a) warn when session state is dropped - #6859

Open
sylvesterkaczmarek wants to merge 1 commit into
google:mainfrom
sylvesterkaczmarek:fix/a2a-state-boundary-warning
Open

fix(a2a) warn when session state is dropped#6859
sylvesterkaczmarek wants to merge 1 commit into
google:mainfrom
sylvesterkaczmarek:fix/a2a-state-boundary-warning

Conversation

@sylvesterkaczmarek

Copy link
Copy Markdown

Link to Issue or Description of Change

Problem

Session state is local to each side of a RemoteA2aAgent boundary, but state loss was silent. A caller state-only event contributes no A2A parts, so the peer receives older content. Remote state deltas are intentionally rejected because a peer must not mutate caller state, but that rejection was only debug-logged.

Solution

  • Warn before an outbound state-only hand-off is dropped.
  • Warn when an inbound remote state delta is rejected.
  • Document the boundary in the API docstring and task-mode guide.
  • Document safe alternatives: send peer inputs as content and return caller-visible values as content or task output.

This preserves the security boundary while making both loss directions visible.

Testing Plan

  • Added regression tests.
  • Relevant tests pass.

pytest tests/unittests/agents/test_remote_a2a_agent.py tests/unittests/a2a/converters/test_to_adk.py -q --disable-warnings

262 passed in 2.56s

Both warning directions are covered and unsafe state mutation remains blocked.

All applicable pre-commit hooks passed.

Manual E2E

Not run against deployed A2A services. The tests exercise the exact request-history and inbound-metadata boundaries.

Checklist

  • I have read the CONTRIBUTING document.
  • I have self-reviewed this change.
  • I have added regression tests.
  • Relevant tests pass locally.
  • I have tested against deployed A2A services.
  • This change has no downstream dependencies.

Additional context

State forwarding remains out of scope because applying peer-controlled state would cross the existing trust boundary.

@iarjunganesh

Copy link
Copy Markdown

Thanks for addressing the runtime boundary here. I traced the converter path and
confirmed that the inbound warning covers a remote LlmAgent(output_key=...):
the remote event's stateDelta is serialized into artifact metadata and then
rejected by the caller converter with the new warning.

I opened #6862 for the complementary caller-side construction hazard: a local
LlmAgent(output_key=...) immediately followed by RemoteA2aAgent. That event
also contains content, so the state-only outbound warning in this PR does not
fire even though the associated session key is unavailable remotely. #6862 is
limited to that detectable ordering and touches separate files.

One review point for this PR: _construct_message_parts_from_session() checks
ctx.session.events[-1] before task-scope filtering. In task mode, that event
can be outside the current isolation scope, which could warn for an event that
is not part of the actual hand-off. Would it be safer to inspect the last
applicable event after events_to_process is built?

It may also be useful to add a round-trip regression test that starts with an
ADK event containing an output_key state delta, converts it to an A2A
artifact, and verifies that the caller emits the warning while preserving the
response content. That would directly lock down Direction 1 from #6854.

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.

Session state does not cross a RemoteA2aAgent boundary in either direction, silently

3 participants