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
- Remove duplicate handoff entries; each target agent should appear once.
- If two distinct handoffs to the same target are needed, give them distinct names via HandoffBase subclassing so the generated tools differ.
- 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
- Deduplicate string handoff targets before constructing the agent.
- When merging handoff lists from multiple modules, union by target name.
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
- Tool names must be unique: {tool_names}
- The model does not support function calling, which is needed
- Unsupported handoff type: {type(handoff)}
- Handoff names must be unique from tool names
- Expected Memory, List[Memory], or None, got {type(memory)}
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/8af3ac2cc67194b9.
Report an issue: GitHub.