Repository navigation
fix: nested parallel agents can't see output from earlier parallel stages (#3470) - #7242
dannovikov wants to merge 1 commit into
Conversation
|
Thanks for your pull request! It looks like this may be your first contribution to a Google open source project. Before we can look at your pull request, you'll need to sign a Contributor License Agreement (CLA). View this failed invocation of the CLA check for more information. For the most up to date status, view the checks section at the bottom of the pull request. |
c599351 to
2cb2c76
Compare
Only ParallelAgent writes branches, always as parallel_agent.sub_agent pairs. Walk both branches to the first mismatch: an odd index means sibling lanes of the same ParallelAgent (hidden); an even index or no mismatch means visible. Event.branch stays a plain string. Fixes google#3470
2cb2c76 to
b9a004f
Compare
|
For reviewers; this PR supersedes my older PR #3889 which offered a far more complicated approach. This one is way simpler and much more elegant. |
|
The failing check ( |
Link to Issue or Description of Change
1. Link to an existing issue (if applicable):
Problem:
Agents cannot see finished output from other branches of a
ParallelAgent. #3470 reports two shapes:The events exist in the session.
_is_event_belongs_to_branchinflows/llm_flows/contents.pyfilters them out of the LLM request because it uses prefix matching: an agent on branchXsees an event on branchYonly ifYis a prefix ofX. That answers "is the event from above me?", but the question it needs to answer is "are we in isolated lanes?"Solution:
Change one function. No new types, no new fields, no storage or schema change.
Event.branchstays a plain string.The fix rests on one fact.
ParallelAgentis the only agent that writes tobranch(agents/parallel_agent.py:35), and it always appends exactly one dot-separated pair:parallel_agent_name.sub_agent_name.SequentialAgentandLoopAgentnever touch it. So a branch string is a sequence of these pairs, and the segments alternate: even positions name aParallelAgent, odd positions name one of its sub-agents.Walk both branch strings segment by segment to the first mismatch. The index of that mismatch tells you everything:
The odd case is the only thing that creates isolation. Two sub-agents of the same
ParallelAgentare in sibling lanes and never see each other's output, regardless of whether one finished before the other started.The even case is where directionality matters. If the first mismatch is at an even index, the two branches name different
ParallelAgents at that position. But every segment before that point matched — sameParallelAgents, same sub-agents, all the way up. That means noParallelAgentabove them forked them into different lanes. Whatever container holds these twoParallelAgents is aSequentialAgentorLoopAgent, which runs children one after another. They are not isolated.The fourth example in the table below shows why the walk must go left to right.
gp.x.p1.aandgp.y.p2.dhave differentParallelAgents at index 2 (p1vsp2), but the walk never reaches index 2 — it stops at index 1 (xvsy), where the two are sub-agents of the sameParallelAgentgp. That odd-index mismatch means they are in sibling lanes ofgp, and the event is hidden.Prior approaches:
stage2.candstage1.aare not prefixes of each other). It also drops the.-delimiter guard, soagent_0matchesagent_00.Event.branch, which reaches session storage, the Vertex session service, the BigQuery plugin, and the web UI. This PR gets the same result from the string already stored.Testing Plan
Unit Tests:
tests/unittests/flows/llm_flows/test_contents_branch.pytest_is_event_belongs_to_branch: nine-row parametrized truth table over the function — one row per case in the table above, plus no-branch, same-branch, and name-prefix-collision rows.test_branch_filtering_parent_sees_finished_children(renamed fromtest_branch_filtering_parent_cannot_see_child— the old assertion was the reported bug).test_branch_filtering_grandchild_sees_grandparentupdated to useparallel.subpair shapes.tests/unittests/agents/test_parallel_branch_visibility.py(new)test_reducer_nested_in_parallel_sees_its_workers— the exact architecture from Inconsistent Event Visibility in Parallel Agent Branching and LLM Context #3470.test_sequence_of_parallel_stages_sees_earlier_stages— the follow-up case from Inconsistent Event Visibility in Parallel Agent Branching and LLM Context #3470.test_visibility_matches_tree_structure[0..19]— 20 seeded random Sequential/Parallel trees run throughInMemoryRunner. Expected visibility is derived from the tree structure alone, then checked against what the real runner put in each agent's LLM request. 231 agents, 2,684 pairs checked.The new tests reject the alternatives:
Full suite: 6846 passed (v1 baseline: 6815; difference is the new tests).
Checklist
Additional context
This targets
v1.LoopAgentreuses the same branch strings across iterations, soLoop[Parallel[a, b]]has a separate visibility gap — that is a pre-existing issue and will be a separate PR.