Skip to content

_get_current_turn_contents picks wrong anchor when single_turn agents run in parallel #7488

Description

@behnam1990adel-hash

#5961 was closed as stale after a repro was requested but never provided. This is that repro.

The bug

When two single_turn sub-agents run on the same session in parallel, one ends up with the other's output in its context window. The reverse scan in _get_current_turn_contents starts at len(events) - 1 — the tail of the shared session list. If agent A finishes first and appends, agent B's scan starts at A's event, skips it on a branch mismatch, and anchors on the parent event directly above. _get_contents is then called with events[anchor:], which includes A's output. ADK wraps it in a safety block, but the content is still there.

Confirmed on v2.11.0. PR #6047 (v2.11.0) fixed include_contents field-override — a different code path. This scan is untouched.

To reproduce

pip install google-adk
python3 parallel_agent_context_contamination.py

No API key. No model. No LiteLLM.

Output (see poc_output.txt):

[FAIL] Unconditional tail-anchored reverse scan found:
  >>>  41|   for i in range(len(events) - 1, -1, -1):

[FAIL] sub_agent_b's context contains sub_agent_a's output!

Scan log at the moment sub_agent_b calls the function while sub_agent_a has already appended:

SCAN   sub_agent_a   root.a   no
SCAN   parent        root     YES   ← anchor — but events[anchor:] includes sub_agent_a's event
       ─── BUILD phase ───
BUILD  parent        root     YES
BUILD  sub_agent_a   root.a   no    ← safety-wrapped into sub_agent_b's context

Fix

Snapshot len(session.events) when each sub-agent's InvocationContext is created and use that as the scan start index. Scanning from there instead of len(events)-1 keeps the anchor search bounded to events that existed before the sibling started appending.

adk_parallel_context_bug.zip

Activity

  1. er-s-an commented on Oct 10, 2026

    @er-s-an

    Hi — I'd like to work on this. Plan: snapshot len(session.events) when each single_turn sub-agent's InvocationContext is created and use that as the reverse-scan start in _get_current_turn_contents, so a sibling that finishes first can't pull the scan into the shared tail. I'll add a focused regression test matching the zip repro (no API key). Please assign if that sounds good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions