feat(agents): add termination conditions for multi-agent workflows#5213
Open
davidmonterocrespo24 wants to merge 2 commits intogoogle:mainfrom
Open
feat(agents): add termination conditions for multi-agent workflows#5213davidmonterocrespo24 wants to merge 2 commits intogoogle:mainfrom
davidmonterocrespo24 wants to merge 2 commits intogoogle:mainfrom
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. |
Add a new google.adk.termination module with pluggable termination conditions that stop a LoopAgent or the Runner mid-run when a configured criterion is met. New termination conditions: - MaxIterationsTermination: stops after N events - TextMentionTermination: stops when a keyword appears in event content - TimeoutTermination: stops after a wall-clock duration - TokenUsageTermination: stops when token budgets are exceeded - FunctionCallTermination: stops when a specific function is called - ExternalTermination: stops on external signal (asyncio-based) - Composite OrTerminationCondition and AndTerminationCondition (also exposed via | and & operators) Integration points: - LoopAgent.termination_condition field: checked after each sub-agent event; emits a synthetic escalation event with ermination_reason set - Runner.run_async(..., termination_condition=...) parameter: checked after every event yielded by the root agent The ermination_reason field is added to EventActions to carry the human-readable reason on synthetic termination events. All conditions implement eset(), which is called automatically at the start of each run so the same instance can be reused across invocations. Cross-repo: aligned with adk-js implementation in google/adk-js#193. Closes google#5211
29ceadc to
3037c2c
Compare
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.
Add a new
google.adk.terminationmodule with pluggable termination conditionsthat stop a
LoopAgentor theRunnermid-run when a configured criterion is met.New termination conditions:
MaxIterationsTermination: stops after N eventsTextMentionTermination: stops when a keyword appears in event contentTimeoutTermination: stops after a wall-clock durationTokenUsageTermination: stops when token budgets are exceededFunctionCallTermination: stops when a specific function is calledExternalTermination: stops on external signal (asyncio-based)OrTerminationConditionandAndTerminationCondition(also exposed via|and&operators)Integration points:
LoopAgent.termination_conditionfield: checked after each sub-agent event; emits a synthetic escalation event withtermination_reasonsetRunner.run_async(..., termination_condition=...)parameter: checked after every event yielded by the root agentThe
termination_reasonfield is added toEventActionsto carry the human-readable reason on synthetic termination events.All conditions implement
reset(), which is called automatically at the start of each run so the same instance can be reused across invocations.Cross-repo: aligned with adk-js implementation in google/adk-js#193.
Link to Issue or Description of Change
Problem:
In multi-agent workflows, agents can fall into infinite or long-running loops
with no built-in signal to indicate task completion. There is no simple
mechanism for agents to signal "task completed," which leads to runaway
conversations, wasted tokens, and stalled workflows.
Solution:
Introduce a pluggable
TerminationConditionabstraction (modeled afterAutoGen's termination system) that integrates into
LoopAgentandRunner.run_async(). Conditions are composable via|(OR) and&(AND),reset automatically between runs, and emit a synthetic event with
actions.termination_reasonwhen triggered.Testing Plan
Unit Tests:
pytestresults summary:New test files:
tests/unittests/termination/test_termination_conditions.py— covers all 7 condition types,OrTerminationCondition,AndTerminationCondition,reset()behavior, and operator overloadstests/unittests/agents/test_loop_agent.py— 3 new tests forLoopAgent.termination_condition: stops loop, text keyword detection, resets between runstests/unittests/runners/test_runner_termination.py— 5 new tests forRunner.run_async(..., termination_condition=...): baseline without condition, stops run, text mention, keyword absent, resets between runsManual End-to-End (E2E) Tests:
Example usage verified locally:
When the condition fires, the loop/runner emits a final event with:
event.actions.escalate = Trueevent.actions.termination_reason = "Text 'TERMINATE' mentioned"Checklist