-
Notifications
You must be signed in to change notification settings - Fork 324
Description
Description
When an agent has multiple toolsets that produce tools with the same name, the Anthropic API rejects the request with HTTP 400: "tools: Tool names must be unique.". There is no deduplication anywhere in the tool collection pipeline.
Issue #1969 fixed this for the specific case of multiple LSP toolsets (via the LSP multiplexer in teamloader.go), but the general problem remains for all other toolset combinations.
Observed in session: cca99566-4277-457a-92fe-cfd877825c0b
Error:
all models failed: error receiving from stream: HTTP 400: POST
"https://ai-backend-service-stage.docker.com/proxy/v1/messages?beta=true": 400
Bad Request {"type":"error","error":{"type":"invalid_request_error",
"message":"tools: Tool names must be unique."}}
Steps to Reproduce
Option 1 — Duplicate built-in toolsets:
agents:
root:
model: anthropic/claude-sonnet-4-0
instruction: You are a helpful assistant.
toolsets:
- type: filesystem
- type: filesystemBoth filesystem toolsets produce identical tool names (read_file, write_file, edit_file, directory_tree, etc.).
Option 2 — Two unnamed MCP servers exposing the same tool names:
agents:
root:
model: anthropic/claude-sonnet-4-0
instruction: You are a helpful assistant.
toolsets:
- type: mcp
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]
- type: mcp
command: npx
args: ["-y", "@modelcontextprotocol/server-filesystem", "/home"]Both MCP servers expose identically-named tools and neither has a name prefix configured.
Option 3 — MCP server colliding with a built-in:
agents:
root:
model: anthropic/claude-sonnet-4-0
instruction: You are a helpful assistant.
toolsets:
- type: fetch
- type: mcp
command: npx
args: ["-y", "@modelcontextprotocol/server-fetch"]The built-in fetch toolset and the MCP fetch server both produce a tool named fetch.
Root Cause
Agent.Tools() in pkg/agent/agent.go collects tools from all toolsets via simple append with no deduplication. No downstream code checks for uniqueness either:
Agent.Tools()(pkg/agent/agent.go) — appends from all toolsets, no dedupgetTools()(pkg/runtime/loop.go) — passes tools through as-isconvertTools()(pkg/model/provider/anthropic/client.go) — maps 1:1 to API params, no dedup- Anthropic API rejects the request
Scenarios that produce duplicates
- Two MCP servers without a
nameprefix (or with the same prefix) exposing same-named tools - An MCP server returning a tool that collides with a built-in name
- Same toolset type configured twice in agent config
- Dynamic MCP
ToolListChangednotifications adding tools that collide with existing names
Suggested Fix
Add deduplication in Agent.Tools() — the single collection point where all tools converge before being sent to any provider. Keep the first occurrence of each tool name and log a warning for dropped duplicates.