OpenBMB/ChatDev · error · ValueError

Tool name ' ' conflicts with a built-in skill tool

Error message

Tool name '{spec.name}' conflicts with a built-in skill tool

What it means

Raised when merging skill tool specs into the agent's tool list: a skill-provided tool has the same name as one of the built-in/baseline tools already present. The executor refuses duplicate tool names because the model would have ambiguous tool targets.

Solutions

  1. Rename your custom tool so it does not collide with names returned by AgentSkillManager.build_tool_specs() (e.g. 'activate_skill', 'read_skill_file')
  2. Filter your tool_specs against skill_manager.build_tool_specs() names before passing them in
  3. Disable Agent Skills for the node if you intend to provide your own tools with those names

Example fix

# before
tools = [{"name": "activate_skill", ...}]  # collides

# after
tools = [{"name": "my_activate_skill", ...}]
Defensive patterns

Strategy: validation

Validate before calling

skill_names = {s.name for s in skill_manager.build_tool_specs()}
assert not ({t['name'] for t in tool_specs} & skill_names), 'name collision'

Prevention

When it happens

Trigger: Calling the agent executor with tool_specs containing a tool named 'activate_skill' or 'read_skill_file' (or any name AgentSkillManager.build_tool_specs() also returns) while Agent Skills are enabled for the node.

Common situations: Custom tool list built by a user that happens to include a tool named like a skill tool; upgrading to a runtime version that newly enables Agent Skills; copy-pasting tool names from skill docs into your own tool registry.

Related errors


AI-assisted analysis of OpenBMB/ChatDev@4fb2db0ea9 (2026-08-27). Data as JSON: /api/errors/10d1b4933aac5479. Report an issue: GitHub.

Appendix: source

Thrown at runtime/node/executor/agent_executor.py:304

                )

        if not parts:
            return None
        return "\n\n".join(part for part in parts if part)

    def _merge_skill_tool_specs(
        self,
        tool_specs: List[ToolSpec],
        skill_manager: AgentSkillManager | None,
    ) -> List[ToolSpec]:
        if skill_manager is None:
            return tool_specs

        merged = list(tool_specs)
        existing_names = {spec.name for spec in merged}
        for spec in skill_manager.build_tool_specs():
            if spec.name in existing_names:
                raise ValueError(f"Tool name '{spec.name}' conflicts with a built-in skill tool")
            existing_names.add(spec.name)
            merged.append(spec)
        return merged

    def _build_agent_invoker(
        self,
        provider: ModelProvider,
        client: Any,
        base_call_options: Dict[str, Any],
        default_tool_specs: List[ToolSpec],
        node: Node,
    ) -> Callable[[List[Message]], Message]:
        """Create a callable that other components can use to invoke the model."""

        def invoke(
            conversation: List[Message],
            *,
            tools: Optional[List[ToolSpec]] = None,

View on GitHub (pinned to 4fb2db0ea9)