Skip to content

[Bug]: TerminateTarget ignored by AutoPattern #2575

@UMainLove

Description

@UMainLove

Describe the bug

DESCRIPTION

When using AutoPattern with set_after_work(TerminateTarget()) on an agent, the termination signal is silently ignored. The workflow runs to max_rounds instead of stopping after the agent speaks.

SEVERITY - HIGH 🔴

TerminateTarget is a core API primitive. It silently does nothing instead of failing visibly, making the bug hard to diagnose.

MITIGATIONS

The workaround found consists in a custom is_termination_msg callback on the GroupChatManager via group_manager_args, which bypasses the after_work mechanism entirely.

Steps to reproduce

AG2 version: 0.11.4

python

from autogen import ConversableAgent
from autogen.agentchat.group.patterns import AutoPattern
from autogen.agentchat.group.multi_agent_chat import initiate_group_chat
from autogen.agentchat.group.targets.transition_target import TerminateTarget

llm_config = {"model": "factory-model_name-version-release", "api_type": "factory"}

agent_a = ConversableAgent(
    name="agent_a",
    system_message="Say hello in one sentence.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)

agent_b = ConversableAgent(
    name="agent_b",
    system_message="Say goodbye in one sentence.",
    llm_config=llm_config,
    human_input_mode="NEVER",
)

# agent_b should terminate the workflow after speaking

agent_b.handoffs.set_after_work(TerminateTarget())
user = ConversableAgent(name="user", llm_config=None, human_input_mode="TERMINATE")

pattern = AutoPattern(
    initial_agent=agent_a,
    agents=[agent_a, agent_b],
    user_agent=user,
    group_manager_args={"llm_config": llm_config},
  )

result, ctx, last = initiate_group_chat(
    pattern=pattern,
    messages="Start the conversation.",
    max_rounds=10,
)

# Check how many rounds actually ran                                                                                                                                           
print(f"Messages: {len(result.chat_history)}")

# Expected: ~3-4 (user prompt, agent_a, agent_b, done)                                                                                                                         
# Actual: runs to max_rounds=10

Model Used

claude-sonnet-4-5-20250929 - claude-haiku-4-5-20251001

Expected Behavior

After agent_b speaks, TerminateTarget should stop the workflow. The chat history should contain ~3-4 messages.

Screenshots and logs

No response

Additional Information

SUGGESTED FIX

Use a sentinel to distinguish "no after_work configured" from "terminate":

python

_NO_AFTER_WORK = object()
                                                                                                                                                                                 
def _evaluate_after_works_conditions(...):
  if not hasattr(agent, "handoffs") or not agent.handoffs.after_works:
      return _NO_AFTER_WORK  # ← sentinel instead of None

# ... rest unchanged ...
                                                                                                                                                                                 
# In determine_next_agent:                                                                                                                                                   
after_works_result = _evaluate_after_works_conditions(...)                                                                                                                     
  if after_works_result is not _NO_AFTER_WORK:
      return after_works_result  # None (terminate) passes through correctly

This lets None from TerminateTarget propagate to group_transition()_prepare_and_select_agents()NoEligibleSpeakerError → clean termination.

NOTE: OnContextCondition with AgentNameTarget works correctly because it resolves to a non-None agent reference. Only TerminateTarget is affected because its termination signal maps to None.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingclassic

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions