{"record":{"id":"88b44a31c81b75a9","repo":"microsoft/autogen","slug":"termination-condition-has-already-been-reached","errorCode":null,"errorMessage":"Termination condition has already been reached.","messagePattern":"Termination condition has already been reached\\.","errorType":"exception","errorClass":"TerminatedException","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/base/_termination.py","lineNumber":107,"sourceCode":"    conditions: List[ComponentModel]\n\n\nclass AndTerminationCondition(TerminationCondition, Component[AndTerminationConditionConfig]):\n    component_config_schema = AndTerminationConditionConfig\n    component_type = \"termination\"\n    component_provider_override = \"autogen_agentchat.base.AndTerminationCondition\"\n\n    def __init__(self, *conditions: TerminationCondition) -> None:\n        self._conditions = conditions\n        self._stop_messages: List[StopMessage] = []\n\n    @property\n    def terminated(self) -> bool:\n        return all(condition.terminated for condition in self._conditions)\n\n    async def __call__(self, messages: Sequence[BaseAgentEvent | BaseChatMessage]) -> StopMessage | None:\n        if self.terminated:\n            raise TerminatedException(\"Termination condition has already been reached.\")\n        # Check all remaining conditions.\n        stop_messages = await asyncio.gather(\n            *[condition(messages) for condition in self._conditions if not condition.terminated]\n        )\n        # Collect stop messages.\n        for stop_message in stop_messages:\n            if stop_message is not None:\n                self._stop_messages.append(stop_message)\n        if any(stop_message is None for stop_message in stop_messages):\n            # If any remaining condition has not reached termination, it is not terminated.\n            return None\n        content = \", \".join(stop_message.content for stop_message in self._stop_messages)\n        source = \", \".join(stop_message.source for stop_message in self._stop_messages)\n        return StopMessage(content=content, source=source)\n\n    async def reset(self) -> None:\n        for condition in self._conditions:\n            await condition.reset()","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/base/_termination.py#L89-L125","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check condition.terminated (cheap property) before invoking the condition","Call await condition.reset() — or await team.reset() — between runs","Create fresh condition instances per run/team instead of sharing them"],"exampleFix":"# before\nfor task in tasks:\n    await team.run(task=task)  # AndTerminationCondition reused, raises on 2nd run\n\n# after\nfor task in tasks:\n    await team.reset()  # resets termination state\n    await team.run(task=task)","handlingStrategy":"validation","validationCode":"# before invoking an AndTerminationCondition\nif and_cond.terminated:\n    await and_cond.reset()  # or skip evaluation\nstop = await and_cond(messages)","typeGuard":null,"tryCatchPattern":"from autogen_agentchat.conditions import TerminatedException\n\ntry:\n    stop = await and_cond(messages)\nexcept TerminatedException:\n    await and_cond.reset()\n    stop = await and_cond(messages)","preventionTips":["Never share condition instances between teams or And/Or composites","Call await team.reset() between runs","Check .terminated before manual evaluation","Treat conditions as stateful single-run objects"],"tags":["termination","stateful","and-termination","agentchat"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}