microsoft/autogen · error · ValueError
Handoff names must be unique from tool names
Error message
Handoff names must be unique from tool names
What it means
One of three same-message guards: this one fires when a handoff given as a plain string equals an existing tool name. A string handoff's target doubles as its handoff tool name, so registering it alongside a tool of the same name would create an ambiguous tool schema for the model.
Source
Thrown at python/packages/autogen-agentchat/src/autogen_agentchat/agents/_assistant_agent.py:820
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")
if workbench is not None:
if self._tools:
raise ValueError("Tools cannot be used with a workbench.")
if isinstance(workbench, Sequence):
self._workbench = workbench
else:
self._workbench = [workbench]
else:
self._workbench = [StaticStreamWorkbench(self._tools)]
if model_context is not None:
self._model_context = model_contextView on GitHub (pinned to 027ecf0a37)
Solutions
- Rename the target agent (or the tool) so the handoff string differs from every tool name.
- Namespace names, e.g. 'web_search_tool' vs 'web_search_agent'.
- Audit all names in one place when building teams: tool names, agent names, handoff targets.
Example fix
# before agent = AssistantAgent(name="a", model_client=client, tools=[search], handoffs=["search"]) # after agent = AssistantAgent(name="a", model_client=client, tools=[search], handoffs=["search_agent"])
Defensive patterns
Strategy: validation
Validate before calling
tool_names = {t.name if hasattr(t, "name") else t.__name__ for t in tools or []}
bad = [h for h in handoffs or [] if isinstance(h, str) and h in tool_names]
if bad:
raise ValueError(f"handoff targets collide with tool names: {bad}") Type guard
def handoff_names_are_disjoint_from_tools(handoffs, tools) -> bool:
tool_names = {t.name if hasattr(t, "name") else t.__name__ for t in tools or []}
return all(not (isinstance(h, str) and h in tool_names) for h in handoffs or []) Try / catch
try:
agent = AssistantAgent(name="a", model_client=client, tools=tools, handoffs=handoffs)
except ValueError as e:
if "unique from tool names" in str(e):
handoffs = [f"{h}_agent" if isinstance(h, str) else h for h in handoffs]
agent = AssistantAgent(name="a", model_client=client, tools=tools, handoffs=handoffs)
else:
raise Prevention
- Use distinct vocabularies: verbs for tools, nouns/role names for agents.
- Run a name-collision audit (tools vs agent names) in team-builder code.
When it happens
Trigger: AssistantAgent(tools=[search_web], handoffs=["search_web"]) — the string matches a tool name in tools.
Common situations: Generic names like 'search' or 'execute' used both for a tool and as an agent name targeted by handoff; auto-generated teams where agent and tool naming collide.
Related errors
- The model does not support function calling.
- Unsupported tool type: {type(tool)}
- Tool names must be unique: {tool_names}
- The model does not support function calling, which is needed
- Unsupported handoff type: {type(handoff)}
AI-assisted analysis of microsoft/autogen@027ecf0a37 (2026-08-15).
Data as JSON: /api/errors/b8f5d87cc7179f3f.
Report an issue: GitHub.