zed-industries/zed · error
Anthropic does not support custom tools
Error message
Anthropic does not support custom tools
What it means
Thrown by Zed's Anthropic provider while converting a LanguageModelRequest into a Messages API call. The adapter only maps LanguageModelRequestToolInput::Function tools (name, description, JSON Schema); the Custom variant used for MCP-style client-executed tools has no Anthropic equivalent, so the request fails during tool conversion before any network call is made.
Source
Thrown at crates/anthropic/src/completion.rs:334
Some(StringOrContents::String(system_message))
};
let mut tools: Vec<Tool> = request
.tools
.into_iter()
.map(|tool| match tool.input {
LanguageModelRequestToolInput::Function {
input_schema,
use_input_streaming,
} => Ok(Tool {
name: tool.name,
description: tool.description,
input_schema,
eager_input_streaming: use_input_streaming,
cache_control: None,
}),
LanguageModelRequestToolInput::Custom { .. } => {
Err(anyhow::anyhow!("Anthropic does not support custom tools"))
}
})
.collect::<Result<_>>()?;
if let Some(cache_control) = long_lived_cache
&& let Some(last_tool) = tools.last_mut()
{
last_tool.cache_control = Some(cache_control);
}
let thinking = if request.thinking_allowed {
match mode {
AnthropicModelMode::Thinking { budget_tokens } => {
Some(Thinking::Enabled { budget_tokens })
}
AnthropicModelMode::AdaptiveThinking => Some(Thinking::Adaptive {
display: Some(AdaptiveThinkingDisplay::Summarized),
}),
AnthropicModelMode::Default => None,View on GitHub (pinned to bc538def45)
Solutions
- Route the request to a provider that supports custom tools (e.g. an OpenAI-compatible or Google model) instead of Anthropic.
- Convert the custom tool into a function tool: give it a JSON Schema input_schema, let the model call it by name, and execute it client-side on receipt.
- Upgrade Zed - later adapters may translate custom tools into Anthropic function-calling form instead of rejecting them.
- Filter custom tools before dispatch and surface a targeted message so the user knows which tool is unsupported.
Example fix
// before
request.tools.push(LanguageModelRequestTool {
name: "read_file".into(),
description: None,
input: LanguageModelRequestToolInput::Custom { /* ... */ }, // rejected by Anthropic
});
// after: express it as a function tool the model calls by name
request.tools.push(LanguageModelRequestTool {
name: "read_file".into(),
description: Some("Read a file from disk".into()),
input: LanguageModelRequestToolInput::Function {
input_schema: json_schema!({
"type": "object",
"properties": { "path": { "type": "string" } },
"required": ["path"]
}),
use_input_streaming: false,
},
}); Defensive patterns
Strategy: validation
Validate before calling
let uses_custom_tools = request
.tools
.iter()
.any(|tool| matches!(tool.input, LanguageModelRequestToolInput::Custom { .. }));
if uses_custom_tools && provider_id.is_anthropic() {
return Err(anyhow::anyhow!(
"the Anthropic provider does not support custom tools; convert them to function tools or pick another provider"
));
} Type guard
fn has_only_function_tools(request: &LanguageModelRequest) -> bool {
request
.tools
.iter()
.all(|tool| matches!(tool.input, LanguageModelRequestToolInput::Function { .. }))
} Try / catch
match provider.complete(request).await {
Err(ref e) if e.to_string().contains("does not support custom tools") => {
// degrade gracefully: strip custom tools and retry, or surface a targeted message
}
other => other,
} Prevention
- Check provider tool capabilities before registering custom tools
- Convert MCP-style custom tools to schema-backed function tools for Anthropic
- Add a per-provider integration test that sends both tool variants
When it happens
Trigger: Sending a LanguageModelRequest through the Anthropic provider where request.tools contains a tool whose input is LanguageModelRequestToolInput::Custom; the collect::<Result<_>>() over the tool-mapping closure returns this error immediately.
Common situations: An assistant profile or MCP integration registers custom tools and the active model is a Claude model; switching a workspace from an OpenAI-compatible provider (which accepts custom tools) to Anthropic; a newer client emitting Custom tool input against this adapter.
Related errors
- Claude returned no tool_use block for tool '{tool['name']}'
- output token limit reached
- Project state not found for session
- No models available
- Attempted to read an image, but this model doesn't support i
AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16).
Data as JSON: /api/errors/69f75f3698262b28.
Report an issue: GitHub.