Repository navigation
fix(agents): route next turn to the target of an unfinished transfer_to_agent - #7459
Open
erickleal-azos wants to merge 1 commit into
Open
erickleal-azos wants to merge 1 commit into
erickleal-azos wants to merge 1 commit into
Conversation
…to_agent When the target of transfer_to_agent fails before yielding any event, the transfer is already persisted but the target never authored an event, so find_agent_to_run sent the next turn back to the transferring agent. Route to the target of the latest valid transfer when it has not replied since, and skip content-less error events, whose author is inherited from the parent context. Fixes google#7458
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.
Link to Issue
Problem:
If the target of
transfer_to_agentfails before yielding any event (for example a503on its first model call), the transfer is already persisted but the target never authored an event.find_agent_to_runreturns the author of the newest eligible event, so the next user message goes back to the transferring agent, whose history says the transfer succeeded. The conversation stays stuck there.The node-failure event makes it worse: it has no content and inherits the transferring agent as its author, so it becomes the newest eligible event. See the issue for the full reproduction.
Solution:
In
agents/_agent_router.py::find_agent_to_run:actions.transfer_to_agent, return the target if it is one of the author's transfer targets (_get_transfer_targets(author)) andis_transferable_across_agent_tree(target)holds. Otherwise fall through to the existing author-based logic.This follows the direction of the existing
TODO: use wait_for_output to decide the agent to run: route by who should produce the next output, not only by who wrote last.Why the target is resolved among the author's transfer targets: it is the same set the transfer tool and scheduler allow. A transfer the scheduler would have rejected (for example one forbidden by
disallow_transfer_to_parentordisallow_transfer_to_peers) therefore never reroutes the session.Why it is safe:
root -> A -> B,BfailsB(the newest transfer wins)sub -> root, root failed before replyingdisallow_transfer_to_parent/disallow_transfer_to_peersMAX_TOKENSpartial reply)WorkflowrootNo change to event persistence, LLM contents, or the
transfer_to_agenttool.Testing Plan
Unit Tests:
New tests in
tests/unittests/agents/test_agent_router.py(routing unit tests, using the existing_make_agent_tree()):test_find_agent_to_run_routes_to_target_of_unfinished_transfertest_find_agent_to_run_ignores_contentless_error_event_after_transfertest_find_agent_to_run_ignores_contentless_error_event_without_transfertest_find_agent_to_run_routes_to_root_on_unfinished_transfer_to_parenttest_find_agent_to_run_routes_to_last_target_of_chained_transfertest_find_agent_to_run_routes_by_author_of_error_event_with_contenttest_find_agent_to_run_prefers_later_reply_over_older_transfertest_find_agent_to_run_unfinished_transfer_to_non_transferable_targettest_find_agent_to_run_ignores_transfer_rejected_by_peer_restrictiontest_find_agent_to_run_ignores_transfer_rejected_by_parent_restrictionNew end-to-end test in
tests/unittests/workflow/test_agent_transfer.py, using a realRunnerand aMockModelthat raisesServerError(503)on the target:test_transfer_target_failing_before_first_event_owns_next_turn[True/False](resumable and non-resumable): the first turn raises, then with a healthy model the second turn is answered by the target and the root model is not called again. Fails without the fix.Without the fix, 7 of these fail (5 routing + 2 end-to-end); with it, all pass:
Manual End-to-End (E2E) Tests:
Setup: the
repro.pyfrom issue #7458 (a rootLlmAgentwith one sub-agent, mock models, the sub-agent raisingServerError(503)on the first turn only). Run it withpython repro.pyagainst this branch and againstmain.Before (
main):After (this PR):
The relevant line is the answer to
hello?: it now comes fromsub_agent, the target of the earlier transfer.Checklist
Additional context
Out of scope for this PR, to keep it to one concern. Possible follow-ups:
event_author(NodeRunner._enrich_event). This does not replace the routing change, because cancellations and process crashes record no error event.HttpRetryOptions/on_model_error_callbackfor transient errors.