Skip to content

feat: add termination conditions for multi-agent workflows#193

Open
davidmonterocrespo24 wants to merge 5 commits intogoogle:mainfrom
davidmonterocrespo24:feat/termination-conditions
Open

feat: add termination conditions for multi-agent workflows#193
davidmonterocrespo24 wants to merge 5 commits intogoogle:mainfrom
davidmonterocrespo24:feat/termination-conditions

Conversation

@davidmonterocrespo24
Copy link
Copy Markdown

@davidmonterocrespo24 davidmonterocrespo24 commented Mar 12, 2026

Introduces a TerminationCondition system that lets developers control when LoopAgent loops and Runner invocations stop.

Built-in conditions:

  • MaxIterationsTermination: stops after N events
  • TextMentionTermination: stops when a keyword appears (e.g. 'TERMINATE')
  • TokenUsageTermination: stops when prompt/completion/total token limits exceeded
  • TimeoutTermination: stops after a wall-clock duration
  • FunctionCallTermination: stops when a named tool is executed
  • ExternalTermination: programmatic stop via .set() (e.g. UI stop button)

Conditions compose with .and() / .or() for combined logic:
new MaxIterationsTermination(10).or(new TextMentionTermination('DONE'))

Integration:

  • LoopAgentConfig.terminationCondition: checked after every sub-agent event
  • Runner.runAsync / runEphemeral support terminationCondition param
  • EventActions gains terminationReason field
  • All types exported from common.ts / @google/adk
  • Full test coverage in core/test/termination/

Closes #29

Summary

Implements a TerminationCondition system that gives developers fine-grained
control over when LoopAgent loops and Runner invocations stop, aligned
with the Python and Java ADK equivalents.

Built-in conditions

Class Stops when
MaxIterationsTermination N events have been emitted
TextMentionTermination A keyword appears in agent output (e.g. 'TERMINATE')
TokenUsageTermination Prompt / completion / total token limits are exceeded
TimeoutTermination A wall-clock duration elapses
FunctionCallTermination A named tool is called
ExternalTermination .set() is called programmatically (e.g. UI stop button)

Composition

Conditions compose with .and() / .or() for combined logic:
new MaxIterationsTermination(10).or(new TextMentionTermination('DONE'))

const condition = new MaxIterationsTermination(10)
  .or(new TextMentionTermination('DONE'));

const agent = new LoopAgent({ ..., terminationCondition: condition });

Changes

New core/src/termination/ module with all built-in conditions and base class
LoopAgentConfig.terminationCondition — checked after every sub-agent event
Runner.runAsync / runEphemeral — accept optional terminationCondition param
EventActions.terminationReason — surfaces the stop reason in the final event
All types exported from common.ts / @google/adk
Full unit test coverage in core/test/termination/

Testing

npm test
All existing tests pass. New tests cover each condition individually, edge cases (already-terminated state, reset behavior), and .and() / .or() composition.

Introduces a TerminationCondition system that lets developers control
when LoopAgent loops and Runner invocations stop.

Built-in conditions:
- MaxIterationsTermination: stops after N events
- TextMentionTermination: stops when a keyword appears (e.g. 'TERMINATE')
- TokenUsageTermination: stops when prompt/completion/total token limits exceeded
- TimeoutTermination: stops after a wall-clock duration
- FunctionCallTermination: stops when a named tool is executed
- ExternalTermination: programmatic stop via .set() (e.g. UI stop button)

Conditions compose with .and() / .or() for combined logic:
  new MaxIterationsTermination(10).or(new TextMentionTermination('DONE'))

Integration:
- LoopAgentConfig.terminationCondition: checked after every sub-agent event
- Runner.runAsync / runEphemeral support terminationCondition param
- EventActions gains terminationReason field
- All types exported from common.ts / @google/adk
- Full test coverage in core/test/termination/
@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a robust and flexible termination condition system for multi-agent workflows. It empowers developers to precisely define when agent loops and runner invocations should cease, preventing unintended infinite execution and providing clear reasons for termination. This system offers a variety of pre-built conditions and the ability to combine them, significantly enhancing control and predictability in agent-based applications.

Highlights

  • New Termination Condition System: Introduced a new TerminationCondition system for controlling multi-agent workflow execution in LoopAgent and Runner.
  • Built-in Termination Conditions: Implemented six distinct built-in termination conditions: MaxIterationsTermination, TextMentionTermination, TokenUsageTermination, TimeoutTermination, FunctionCallTermination, and ExternalTermination.
  • Condition Composition: Enabled logical composition of termination conditions using .and() and .or() operators for complex termination logic.
  • Integration with Core Components: Integrated the termination condition mechanism into LoopAgentConfig and Runner.runAsync/runEphemeral methods, and added a terminationReason field to EventActions.
  • Comprehensive Test Coverage: Added full unit test coverage for all new termination conditions and their composition.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • core/src/agents/loop_agent.ts
    • Imported termination-related utilities and TerminationCondition.
    • Added terminationCondition property to LoopAgentConfig and LoopAgent.
    • Implemented logic to reset and check the termination condition within the agent's run loop, yielding a termination event if met.
  • core/src/common.ts
    • Exported all newly introduced termination condition classes and types for broader use.
  • core/src/events/event_actions.ts
    • Added an optional terminationReason field to the EventActions interface.
  • core/src/runner/runner.ts
    • Imported TerminationCondition.
    • Extended runEphemeral and runAsync methods to accept an optional terminationCondition parameter.
    • Incorporated termination condition checking and event generation into the runner's execution flow.
  • core/src/termination/external_termination.ts
    • Added ExternalTermination class, allowing programmatic termination.
  • core/src/termination/function_call_termination.ts
    • Added FunctionCallTermination class, terminating on specific function calls.
  • core/src/termination/max_iterations_termination.ts
    • Added MaxIterationsTermination class, terminating after a set number of events.
  • core/src/termination/termination_condition.ts
    • Added the abstract base class TerminationCondition, TerminationResult interface, and composite conditions AndTerminationCondition and OrTerminationCondition.
  • core/src/termination/text_mention_termination.ts
    • Added TextMentionTermination class, terminating when specific text is found.
  • core/src/termination/timeout_termination.ts
    • Added TimeoutTermination class, terminating after a specified time duration.
  • core/src/termination/token_usage_termination.ts
    • Added TokenUsageTermination class, terminating based on cumulative token usage limits.
  • core/test/termination/termination_conditions_test.ts
    • Added comprehensive unit tests for the new termination condition system and its various implementations.
Activity
  • No specific activity (comments, reviews, progress) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a comprehensive and well-designed TerminationCondition system, allowing for fine-grained control over when agent loops and runner invocations stop. The implementation is clean, includes a variety of useful built-in conditions, and supports composition through .and() and .or() operators. The integration into LoopAgent and Runner is thoughtfully done, and the addition of thorough unit tests is commendable. I have one minor suggestion for a potential performance improvement.

# Conflicts:
#	core/src/agents/loop_agent.ts
@davidmonterocrespo24 davidmonterocrespo24 force-pushed the feat/termination-conditions branch from 7759b76 to 2c7e325 Compare March 12, 2026 19:56
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@kalenkevich kalenkevich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@kalenkevich kalenkevich self-requested a review March 12, 2026 22:24
Copy link
Copy Markdown
Collaborator

@kalenkevich kalenkevich left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the false "approving" alarm. We need to make sure this is aligned with others ADKs. I will come back with the feedback.

Thanks

@davidmonterocrespo24
Copy link
Copy Markdown
Author

Sorry for the false "approving" alarm. We need to make sure this is aligned with others ADKs. I will come back with the feedback.

Thanks

Hi @kalenkevich , if I do it for Python too, wouldn't it be aligned? Or would something else be missing?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature Request: Add Explicit Termination Mechanism for Multi-Agent Workflows (Similar to AutoGen “TERMINATE”)

2 participants