Repository navigation
fix(workflow): keep a node's branch when it relays sub-agent events - #7940
Closed
AtulJoshi1206 wants to merge 1 commit into
Closed
AtulJoshi1206 wants to merge 1 commit into
AtulJoshi1206 wants to merge 1 commit into
Conversation
A structured agent run as a node, such as a ParallelAgent or a SequentialAgent that contains one, re-yields the events its sub-agents emit. That happens for a Workflow node and for a sub-agent that a root LlmAgent transfers to. NodeRunner._enrich_event moved the node onto the branch of every event it enqueued, so after a ParallelAgent finished the node was left on the sub-branch of whichever sub-agent spoke last. The node's later events were stamped with that branch, and the workflow handed it to the node's successors. An agent after the parallel step then read history filtered by that one sub-branch and saw only that sub-agent's output, and on later turns only that sub-agent saw the replies stamped after it. The same agent tree run as a legacy root agent keeps those replies on the parent's branch. It also undid a dispatcher agent re-stamping a sub-agent's final answer onto its own branch: the tool events had already moved the node, so the branch-less answer was stamped with the sub-branch again. Route and transfer_to_agent are already taken only from the node's own events, for the same reason. Apply that rule to the branch too, and keep it in one helper so the two uses can't drift apart.
copybara-service Bot
pushed a commit
that referenced
this pull request
Nov 3, 2026
Merge #7940 A node that relays its sub-agents' events (such as a ParallelAgent or a SequentialAgent containing one, run as a Workflow node or transferred to from a root LlmAgent) no longer moves onto the branch of whichever sub-agent spoke last. Relayed events keep their own sub-branch; the node's later events and its successors stay on the node's branch, so an agent after a parallel step sees every sub-agent's output. Resuming a paused workflow recovers the same branch, so a node after the parallel step that paused for a tool confirmation resumes where it paused and runs the confirmed tool. PiperOrigin-RevId: 1013319278
Collaborator
|
Thank you @AtulJoshi1206 for your contribution! 🎉 Your changes have been successfully imported and merged via Copybara in commit 27edb47. Closing this PR as the changes are now in the main branch. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Please ensure you have read the contribution guide before creating a pull request.
Link to Issue or Description of Change
No existing issue; described below following the bug-report structure.
Describe the Bug:
When an agent that runs its sub-agents on their own branches is run as a node, the node ends up on the branch of whichever sub-agent spoke last. In practice that's a
ParallelAgent, on its own or inside aSequentialAgent, either as aWorkflownode or as a sub-agent that a rootLlmAgenttransfers to.NodeRunner._enrich_eventmoves the node onto the branch of every event it enqueues, including the sub-agent events the node is only relaying. So after the parallel step, the node's later events are stamped with that sub-branch, and the workflow hands the same sub-branch to the node's successors._track_event_in_contextalready ignores relayed events forrouteandtransfer_to_agent, for the same reason (6d7bab6), but the branch never got that check.Impact:
BaseAgentsettingevent.branch = parent_branchon its sub-agent's final answer) gets undone when the dispatcher runs as a node.Workflowor a rootLlmAgentcoordinator.Observed Behavior:
research.researcher_b, and its LLM request only containsfinding from b.LlmAgentthat transfers toSequentialAgent([ParallelAgent([worker_a, worker_b]), merger]), the merger's reply is stampedfan_out.worker_b. With the same pipeline as the root agent it'sNone.Workflownode, the final answer stays ondispatcher.bookingsnext to its tool call.Expected Behavior:
A relayed event keeps its own sub-branch, but the node stays on its own branch. The summarizer sees both findings, the merger's reply stays on the pipeline's branch (as on the legacy root path), and a re-stamped answer stays where the dispatcher put it.
Solution:
I moved the existing "is this the node's own event" check out of
_track_event_in_contextintoNodeRunner._is_native_event, and used it in_enrich_eventtoo. Only an event the node authors, or one with no author, can move the node's branch now. A relayed event is still stamped with its own branch; it just doesn't drag the node along.Unchanged:
test_child_event_branch_does_not_mutate_parent_icand a new test cover this.""-to-root normalization.The change is in
NodeRunner, so it covers every agent that relays its sub-agents' events, without touching the agents themselves. That includes static and dynamic nodes, and live mode.Testing Plan
Unit Tests:
New tests:
test_node_runner_ctx.py::test_own_event_branch_moves_node_branch: pins the behaviour that stays, and passes before and after.test_node_runner_ctx.py::test_relayed_event_branch_does_not_move_node_branchtest_workflow_agent_as_node.py::test_node_after_parallel_agent_node_sees_every_branch: end to end throughRunner, checking the summarizer's actual LLM request.test_workflow_agent_as_node.py::test_answer_relayed_onto_parent_branch_stays_there: the [Feature] Opt-in visibility of sibling agents' final responses across branches #6496 pattern as a node.test_agent_transfer.py::test_auto_to_sequential_with_parallel_keeps_merger_branch[True/False]On
mainthe new tests give5 failed, 1 passed; with the fix,6 passed.pyinkandisortare clean.Manual End-to-End (E2E) Tests:
Not run against a real model; the tests use
MockModel.Checklist
Additional context
#3470 looks similar but is a different problem: branch-prefix matching between nested legacy agents on the legacy path. This one is the node runtime picking up a relayed event's branch.
🤖 Generated with Claude Code