microsoft/autogen · error · ValueError

Handoff names must be unique: {handoff_tool_names}

Error message

Handoff names must be unique: {handoff_tool_names}

What it means

AssistantAgent checks that handoff tool names are unique among themselves; duplicates (e.g. two handoffs to the same target, which produce identically named handoff tools) raise ValueError listing all handoff tool names.

Source

Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/agents/_assistant_agent.py:808

        # Handoff tools.
        self._handoff_tools: List[BaseTool[Any, Any]] = []
        self._handoffs: Dict[str, HandoffBase] = {}
        if handoffs is not None:
            if model_client.model_info["function_calling"] is False:
                raise ValueError("The model does not support function calling, which is needed for handoffs.")
            for handoff in handoffs:
                if isinstance(handoff, str):
                    handoff = HandoffBase(target=handoff)
                if isinstance(handoff, HandoffBase):
                    self._handoff_tools.append(handoff.handoff_tool)
                    self._handoffs[handoff.name] = handoff
                else:
                    raise ValueError(f"Unsupported handoff type: {type(handoff)}")
        # Check if handoff tool names are unique.
        handoff_tool_names = [tool.name for tool in self._handoff_tools]
        if len(handoff_tool_names) != len(set(handoff_tool_names)):
            raise ValueError(f"Handoff names must be unique: {handoff_tool_names}")
        # Create sets for faster lookup
        tool_names_set = set(tool_names)
        handoff_tool_names_set = set(handoff_tool_names)

        # Check if there's any overlap between handoff tool names and tool names
        overlap = tool_names_set.intersection(handoff_tool_names_set)

        # Also check if any handoff target name matches a tool name
        # This handles the case where a handoff is specified directly with a string that matches a tool name
        for handoff in handoffs or []:
            if isinstance(handoff, str) and handoff in tool_names_set:
                raise ValueError("Handoff names must be unique from tool names")
            elif isinstance(handoff, HandoffBase) and handoff.target in tool_names_set:
                raise ValueError("Handoff names must be unique from tool names")

        if overlap:
            raise ValueError("Handoff names must be unique from tool names")

View on GitHub (pinned to 027ecf0a37)

Solutions

  1. Remove duplicate handoff entries; each target agent should appear once.
  2. If two distinct handoffs to the same target are needed, give them distinct names via HandoffBase subclassing so the generated tools differ.
  3. De-duplicate string lists before passing: handoffs=list(dict.fromkeys(handoffs)).

Example fix

# before
agent = AssistantAgent(name="a", model_client=client, handoffs=["b", "b"])

# after
agent = AssistantAgent(name="a", model_client=client, handoffs=["b"])
Defensive patterns

Strategy: validation

Validate before calling

handoffs = list(dict.fromkeys(handoffs)) if all(isinstance(h, str) for h in handoffs) else handoffs
names = [h.target for h in handoffs]
assert len(names) == len(set(names)), f"duplicate handoff targets: {names}"

Type guard

def has_unique_handoff_targets(handoffs) -> bool:
    targets = [h if isinstance(h, str) else h.target for h in handoffs or []]
    return len(targets) == len(set(targets))

Try / catch

try:
    agent = AssistantAgent(name="a", model_client=client, handoffs=handoffs)
except ValueError as e:
    if "Handoff names must be unique" in str(e) and all(isinstance(h, str) for h in handoffs):
        agent = AssistantAgent(name="a", model_client=client, handoffs=list(dict.fromkeys(handoffs)))
    else:
        raise

Prevention

When it happens

Trigger: Passing handoffs=["agent_b", "agent_b"], or two HandoffBase instances whose handoff tools share a name (commonly the same target specified twice, since the tool name is derived from the target).

Common situations: Programmatically generating handoff lists and accidentally including a target twice, or refactoring team definitions that merge handoff lists with overlapping targets.

Related errors


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