feat(agents): annotate events with the LoopAgent iteration#6268
Open
ferponse wants to merge 2 commits into
Open
feat(agents): annotate events with the LoopAgent iteration#6268ferponse wants to merge 2 commits into
ferponse wants to merge 2 commits into
Conversation
LoopAgent re-runs its sub-agents each iteration, but events from different iterations are indistinguishable in the stream (same author, branch and invocation_id), so consumers cannot tell iterations apart — e.g. a ParallelAgent nested in a LoopAgent, whose branch ids repeat every iteration. Record the current 0-based iteration under Event.custom_metadata['loop_iteration'] as each sub-agent event bubbles up. Additive and behavior-preserving; setdefault means the nearest enclosing loop wins when loops are nested. Fixes google#6266.
This was referenced Jul 2, 2026
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.
What
LoopAgentre-runs its sub-agents each iteration, but events produced in different iterations are indistinguishable in the stream — sameauthor,branch, andinvocation_id. So a consumer cannot tell iteration 1 from iteration 2. This is most visible with aParallelAgentnested in aLoopAgent, whose branch ids (par.p,par.q) repeat every iteration.This records the current 0-based iteration under
Event.custom_metadata['loop_iteration']as each sub-agent event bubbles up through the loop.Fixes #6266.
Why
We're building the AG-UI ↔ ADK middleware (
ag-ui-adk), which maps ADK workflow nodes to AG-UISTEP_STARTED/STEP_FINISHEDevents. It infers node boundaries from therunner.run_asyncstream (author= node,branch= structural path). This works for every serial and parallel topology except a parallel block inside a loop, where iterations are indistinguishable, so per-iteration steps can't be reconstructed. Verified ongoogle-adk 2.3.0.How
LoopAgent.LOOP_ITERATION_KEY = 'loop_iteration'constant._annotate_loop_iteration(event, times_looped)stampsevent.custom_metadataviasetdefault, so the nearest enclosing loop wins when loops are nested.Additive and behavior-preserving: no new events, no schema change (
custom_metadatais the existing custom bucket).LoopAgent(max_iterations=2, sub_agents=[ParallelAgent(sub_agents=[p, q])])— after this change:Tests
tests/unittests/agents/test_loop_agent.py: addedtest_run_async_annotates_loop_iteration(iterations 0/1/2) andtest_run_async_loop_iteration_survives_nested_loops(nested loops — inner wins). The fulltest_loop_agent.pypasses.Notes
LoopAgentis@deprecatedin favor ofWorkflow; this fixes the still-widely-used classic loop. The same iteration signal would be valuable from the Workflow graph engine (out of scope here).