{"record":{"id":"d45ff4dfb1ed32da","repo":"agentscope-ai/agentscope","slug":"tool-groups-must-not-contain-duplicate-tool-groups","errorCode":null,"errorMessage":"Tool groups must not contain duplicate tool groups.","messagePattern":"Tool groups must not contain duplicate tool groups\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/agentscope/tool/_toolkit.py","lineNumber":140,"sourceCode":"                \"group. Don't include 'basic' in the tool_groups argument \"\n                \"when you also provide tools, skills or mcps in the \"\n                \"constructor.\",\n            )\n\n        self.tool_groups = [\n            ToolGroup(\n                name=\"basic\",\n                tools=tools or [],\n                skills_or_loaders=skills_or_loaders or [],\n                mcps=mcps or [],\n            ),\n        ] + (tool_groups or [])\n\n        # Check name conflict for tool groups\n        if len(set(_.name for _ in self.tool_groups)) != len(\n            self.tool_groups,\n        ):\n            raise ValueError(\n                \"Tool groups must not contain duplicate tool groups.\",\n            )\n\n        # The stateful MCP clients should be initialized already\n        for group in self.tool_groups:\n            for client in group.mcps:\n                if client.is_stateful and not client.is_connected:\n                    raise ValueError(\n                        f\"The MCP client '{client.name}' is stateful, but \"\n                        f\"not connected.\",\n                    )\n\n        self.meta_tool_response_template = meta_tool_response_template\n        self.skill_instruction_template = skill_instruction_template\n\n        self.builtin_meta_tool = RegisteredTool(\n            tool=ResetTools(\n                # An inference value for groups so that it can generate the","sourceCodeStart":122,"sourceCodeEnd":158,"githubUrl":"https://github.com/agentscope-ai/agentscope/blob/e90f1c7592896cc95f6e5ee506194f533378247d/src/agentscope/tool/_toolkit.py#L122-L158","documentation":"Raised by Toolkit.__init__ when two or more tool groups passed to the toolkit share the same name. The toolkit relies on group names being unique to route tool registration and activation, so duplicates are rejected eagerly at construction time.","triggerScenarios":"Constructing a Toolkit (or agent with tool_groups=...) where the list contains two ToolGroup objects with identical .name values, e.g. a default group plus a user-supplied group both named 'default'.","commonSituations":"Appending a custom group that inadvertently reuses the default group name; copying example code that already includes a built-in group; merging group lists from different config sources without de-duplicating.","solutions":["Check the names of every ToolGroup you pass: [g.name for g in tool_groups] and remove/rename the duplicate","If building the list dynamically, de-duplicate by name before constructing the Toolkit: seen=set(); groups=[g for g in groups if not (g.name in seen or seen.add(g.name))]","Give custom groups a distinct name in the ToolGroup constructor, e.g. ToolGroup(name='my-default', ...)"],"exampleFix":"// before\ntoolkit = Toolkit(tool_groups=[default_group, ToolGroup(name='default', tools=[...])])\n// after\ntoolkit = Toolkit(tool_groups=[default_group, ToolGroup(name='extra', tools=[...])])","handlingStrategy":"validation","validationCode":"names = [g.name for g in tool_groups]\nassert len(names) == len(set(names)), f'duplicate group names: {names}'\ntoolkit = Toolkit(tool_groups=tool_groups)","typeGuard":null,"tryCatchPattern":null,"preventionTips":["De-duplicate group lists by name before constructing Toolkit","Use constants/enums for group names to avoid accidental reuse"],"tags":["toolkit","duplicate","tool-groups","config"],"backgroundTag":"duplicate-name-config","analyzedSha":"e90f1c7592896cc95f6e5ee506194f533378247d","analyzedAt":"2026-08-28T18:24:12.087Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}