feat(termination): add pluggable termination conditions for multi-age…#118
feat(termination): add pluggable termination conditions for multi-age…#118davidmonterocrespo24 wants to merge 1 commit intogoogle:mainfrom
Conversation
…nt workflows Add a new google.adk_community.termination module with pluggable termination conditions for use with LoopAgent and Runner-based multi-agent workflows. 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 (set() method) - OrTerminationCondition / AndTerminationCondition composites (via | and &) All conditions implement check(events), reset(), and the terminated property. reset() is called automatically at the start of each run so the same instance can be reused across invocations. Related: google/adk-python#5211 Related: google/adk-python#5213 Cross-repo: google/adk-js#193
|
@gemini-cli /review |
|
🤖 Hi @DeanChensj, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
There was a problem hiding this comment.
Thanks for the PR! The termination conditions are well-implemented and the test coverage is excellent.
I've left a few minor suggestions regarding state consistency in compound conditions and more descriptive termination reasons. Overall, this is a great addition to the community package.
| self, | ||
| left: TerminationCondition, | ||
| right: TerminationCondition, | ||
| ) -> None: |
There was a problem hiding this comment.
In OrTerminationCondition, if the left condition matches, the right condition is never checked. While this works for the immediate termination, it means the right condition misses these events, which could lead to inconsistent internal state (e.g., token counts or iteration counts) if the condition is reused or part of a more complex logic.
Consider checking both sides even if the first one returns a result:
left_result = await self._left.check(events)
right_result = await self._right.check(events)
if left_result:
self._terminated = True
return left_result
if right_result:
self._terminated = True
return right_result|
|
||
| @property | ||
| def terminated(self) -> bool: | ||
| return self._terminated |
There was a problem hiding this comment.
The generic reason "All termination conditions met" loses the specific context of why the underlying conditions terminated. It might be helpful to combine the reasons from both left and right.
Summary
Adds a new
google.adk_community.terminationmodule with pluggable terminationconditions for use with
LoopAgentandRunner-based multi-agent workflows.This contribution was originally submitted to
google/adk-pythonasPR #5213 (referencing
issue #5211 and
adk-js#193), and was redirected
here by maintainer @rohityan.
New Module:
google.adk_community.terminationTermination Conditions
MaxIterationsTerminationTextMentionTerminationTimeoutTerminationTokenUsageTerminationFunctionCallTerminationExternalTermination.set()OrTerminationConditiona | b— stops if either condition is metAndTerminationConditiona & b— stops only when both are metAll conditions implement:
check(events: list[Event]) -> TerminationResultreset()— called automatically at run start, safe to reuse across invocationsterminatedpropertyUsage Example