{"record":{"id":"b8f5d87cc7179f3f","repo":"microsoft/autogen","slug":"handoff-names-must-be-unique-from-tool-names","errorCode":null,"errorMessage":"Handoff names must be unique from tool names","messagePattern":"Handoff names must be unique from tool names","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/packages/autogen-agentchat/src/autogen_agentchat/agents/_assistant_agent.py","lineNumber":820,"sourceCode":"                    self._handoffs[handoff.name] = handoff\n                else:\n                    raise ValueError(f\"Unsupported handoff type: {type(handoff)}\")\n        # Check if handoff tool names are unique.\n        handoff_tool_names = [tool.name for tool in self._handoff_tools]\n        if len(handoff_tool_names) != len(set(handoff_tool_names)):\n            raise ValueError(f\"Handoff names must be unique: {handoff_tool_names}\")\n        # Create sets for faster lookup\n        tool_names_set = set(tool_names)\n        handoff_tool_names_set = set(handoff_tool_names)\n\n        # Check if there's any overlap between handoff tool names and tool names\n        overlap = tool_names_set.intersection(handoff_tool_names_set)\n\n        # Also check if any handoff target name matches a tool name\n        # This handles the case where a handoff is specified directly with a string that matches a tool name\n        for handoff in handoffs or []:\n            if isinstance(handoff, str) and handoff in tool_names_set:\n                raise ValueError(\"Handoff names must be unique from tool names\")\n            elif isinstance(handoff, HandoffBase) and handoff.target in tool_names_set:\n                raise ValueError(\"Handoff names must be unique from tool names\")\n\n        if overlap:\n            raise ValueError(\"Handoff names must be unique from tool names\")\n\n        if workbench is not None:\n            if self._tools:\n                raise ValueError(\"Tools cannot be used with a workbench.\")\n            if isinstance(workbench, Sequence):\n                self._workbench = workbench\n            else:\n                self._workbench = [workbench]\n        else:\n            self._workbench = [StaticStreamWorkbench(self._tools)]\n\n        if model_context is not None:\n            self._model_context = model_context","sourceCodeStart":802,"sourceCodeEnd":838,"githubUrl":"https://github.com/microsoft/autogen/blob/027ecf0a379bcc1d09956d46d12d44a3ad9cee14/python/packages/autogen-agentchat/src/autogen_agentchat/agents/_assistant_agent.py#L802-L838","documentation":"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.","triggerScenarios":"AssistantAgent(tools=[search_web], handoffs=[\"search_web\"]) — the string matches a tool name in tools.","commonSituations":"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.","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."],"exampleFix":"# before\nagent = AssistantAgent(name=\"a\", model_client=client, tools=[search], handoffs=[\"search\"])\n\n# after\nagent = AssistantAgent(name=\"a\", model_client=client, tools=[search], handoffs=[\"search_agent\"])","handlingStrategy":"validation","validationCode":"tool_names = {t.name if hasattr(t, \"name\") else t.__name__ for t in tools or []}\nbad = [h for h in handoffs or [] if isinstance(h, str) and h in tool_names]\nif bad:\n    raise ValueError(f\"handoff targets collide with tool names: {bad}\")","typeGuard":"def handoff_names_are_disjoint_from_tools(handoffs, tools) -> bool:\n    tool_names = {t.name if hasattr(t, \"name\") else t.__name__ for t in tools or []}\n    return all(not (isinstance(h, str) and h in tool_names) for h in handoffs or [])","tryCatchPattern":"try:\n    agent = AssistantAgent(name=\"a\", model_client=client, tools=tools, handoffs=handoffs)\nexcept ValueError as e:\n    if \"unique from tool names\" in str(e):\n        handoffs = [f\"{h}_agent\" if isinstance(h, str) else h for h in handoffs]\n        agent = AssistantAgent(name=\"a\", model_client=client, tools=tools, handoffs=handoffs)\n    else:\n        raise","preventionTips":["Use distinct vocabularies: verbs for tools, nouns/role names for agents.","Run a name-collision audit (tools vs agent names) in team-builder code."],"tags":["python","handoffs","tools","naming","autogen"],"backgroundTag":null,"analyzedSha":"027ecf0a379bcc1d09956d46d12d44a3ad9cee14","analyzedAt":"2026-08-15T03:38:00.719Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}