Skip to content

fix(a2a): emit only new artifact parts on streaming artifact updates#6386

Open
Brumbelow wants to merge 1 commit into
google:mainfrom
Brumbelow:fix/a2a-artifact-chunk-duplication
Open

fix(a2a): emit only new artifact parts on streaming artifact updates#6386
Brumbelow wants to merge 1 commit into
google:mainfrom
Brumbelow:fix/a2a-artifact-chunk-duplication

Conversation

@Brumbelow

Copy link
Copy Markdown
Contributor

Link to Issue or Description of Change

1. Link to an existing issue (if applicable):

Problem:

With RemoteA2aAgent on the default (legacy) response handler, a streaming remote agent that sends an artifact in multiple chunks gets its first chunk duplicated in the response. The artifact-update branch in _handle_a2a_response converts the whole accumulated task — task.artifacts[-1] carries the merged parts of every chunk received so far — so a stream like append=False/last_chunk=False ("Hello, ") followed by append=True/last_chunk=True ("world!") renders "Hello, Hello, world!". Streams with 3+ chunks additionally lose their middle chunks until the final re-emission, because the old not update.append or update.last_chunk filter dropped them.

This is why the issue only reproduces with streaming=True, and why use_legacy=False works around it: the v2 handler already converts only the update's own parts (convert_a2a_artifact_update_to_event).

Solution:

Bring the legacy branch in line with v2: convert only the parts carried by the incoming TaskArtifactUpdateEvent (via _compat.make_message, mirroring the message construction convert_a2a_task_to_event itself uses), and skip updates that carry no parts. Each chunk is emitted exactly once, so the rendered and persisted content is the exact concatenation of what the server streamed. The (task, None) initial-response branch, status-update handling, task metadata stamping, and the v2 path are unchanged.

Testing Plan

Unit Tests:

  • I have added or updated unit tests for my change.
  • All unit tests pass locally.

New TestRemoteA2aAgentStreamingArtifactChunks drives _handle_a2a_response with real converters and a two-chunk artifact stream, asserting the emitted text is exactly "Hello, world!" — on main it fails with "Hello, Hello, world!". A second case asserts an artifact update with no parts emits nothing. The existing artifact-update tests were updated to assert per-update conversion, and the stale "partial updates are ignored" test now verifies an appended chunk emits its own parts.

  • pytest tests/unittests/agents/test_remote_a2a_agent.py — 109 passed (a2a-sdk 1.1.0)
  • pytest tests/unittests/a2a tests/unittests/agents/test_remote_a2a_agent.py -n auto — 475 passed, 20 skipped (a2a-sdk 1.1.0)
  • Same suites plus tests/unittests/integrations/agent_registry under a2a-sdk 0.3.26 (mirrors the unit-test-a2a-v0-3 CI job) — 525 passed, 17 skipped
  • pytest tests/unittests/agents -n auto — 616 passed, 2 xfailed
  • pre-commit run clean on touched files; mypy reports the same pre-existing errors as main (no new ones)

Manual End-to-End (E2E) Tests:

Reproduced the report with a minimal harness feeding a chunked artifact stream — (task, update) pairs exactly as the client yields them — through the legacy handler: main renders 'Hello, Hello, world!', this branch renders 'Hello, world!'.

Checklist

  • I have read the CONTRIBUTING.md document.
  • I have performed a self-review of my own code.
  • I have commented my code, particularly in hard-to-understand areas.
  • I have added tests that prove my fix is effective or that my feature works.
  • New and existing unit tests pass locally with my changes.
  • I have manually tested my changes end-to-end.
  • Any dependent changes have been merged and published in downstream modules.

@adk-bot adk-bot added the core [Component] This issue is related to the core interface and implementation label Jul 14, 2026
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.

A2A Duplicate first part of text in the response from a2a agent

3 participants