microsoft/autogen · error · TerminatedException

Termination condition has already been reached.

Error message

Termination condition has already been reached.

What it means

AndTerminationCondition is stateful: once all its sub-conditions report terminated, calling it again raises TerminatedException. The check happens before evaluating the remaining sub-conditions, so any invocation after full termination is a programming error, not a normal signal. Reset (condition.reset()) clears the state of all sub-conditions.

Source

Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/base/_termination.py:107

    conditions: List[ComponentModel]


class AndTerminationCondition(TerminationCondition, Component[AndTerminationConditionConfig]):
    component_config_schema = AndTerminationConditionConfig
    component_type = "termination"
    component_provider_override = "autogen_agentchat.base.AndTerminationCondition"

    def __init__(self, *conditions: TerminationCondition) -> None:
        self._conditions = conditions
        self._stop_messages: List[StopMessage] = []

    @property
    def terminated(self) -> bool:
        return all(condition.terminated for condition in self._conditions)

    async def __call__(self, messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> StopMessage | None:
        if self.terminated:
            raise TerminatedException("Termination condition has already been reached.")
        # Check all remaining conditions.
        stop_messages = await asyncio.gather(
            *[condition(messages) for condition in self._conditions if not condition.terminated]
        )
        # Collect stop messages.
        for stop_message in stop_messages:
            if stop_message is not None:
                self._stop_messages.append(stop_message)
        if any(stop_message is None for stop_message in stop_messages):
            # If any remaining condition has not reached termination, it is not terminated.
            return None
        content = ", ".join(stop_message.content for stop_message in self._stop_messages)
        source = ", ".join(stop_message.source for stop_message in self._stop_messages)
        return StopMessage(content=content, source=source)

    async def reset(self) -> None:
        for condition in self._conditions:
            await condition.reset()

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Check condition.terminated (cheap property) before invoking the condition
  2. Call await condition.reset() — or await team.reset() — between runs
  3. Create fresh condition instances per run/team instead of sharing them

Example fix

# before
for task in tasks:
    await team.run(task=task)  # AndTerminationCondition reused, raises on 2nd run

# after
for task in tasks:
    await team.reset()  # resets termination state
    await team.run(task=task)
Defensive patterns

Strategy: validation

Validate before calling

# before invoking an AndTerminationCondition
if and_cond.terminated:
    await and_cond.reset()  # or skip evaluation
stop = await and_cond(messages)

Try / catch

from autogen_agentchat.conditions import TerminatedException

try:
    stop = await and_cond(messages)
except TerminatedException:
    await and_cond.reset()
    stop = await and_cond(messages)

Prevention

When it happens

Trigger: Calling await condition(messages) manually after a team run has finished; sharing one AndTerminationCondition (or a sub-condition instance) between two teams or two runs without reset; wrapping the same sub-condition in both a team's condition and a separate And/Or composite so it terminates twice.

Common situations: Reusing a single condition object across sequential team.run() calls; logging/monitoring code that probes conditions by invoking them; combining MaxMessageTermination instances shared between OrTerminationCondition and AndTerminationCondition.

Related errors


AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15). Data as JSON: /api/errors/88b44a31c81b75a9. Report an issue: GitHub.