#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
#5961 was closed as stale after a repro was requested but never provided. This is that repro.
The bug
When two
single_turnsub-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_contentsstarts atlen(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_contentsis then called withevents[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_contentsfield-override — a different code path. This scan is untouched.To reproduce
No API key. No model. No LiteLLM.
Output (see
poc_output.txt):Scan log at the moment
sub_agent_bcalls the function whilesub_agent_ahas already appended:Fix
Snapshot
len(session.events)when each sub-agent'sInvocationContextis created and use that as the scan start index. Scanning from there instead oflen(events)-1keeps the anchor search bounded to events that existed before the sibling started appending.adk_parallel_context_bug.zip