zed-industries/zed · error

Anthropic does not support custom tool calls

Error message

Anthropic does not support custom tool calls

What it means

When converting a conversation into Anthropic Messages API requests, tool_use content must carry structured JSON input (Anthropic requires an 'input' object). LanguageModelToolUseInput::Text — free-form text produced by custom/untyped tools — has no faithful Anthropic encoding, so the conversion refuses it rather than sending a malformed request.

Source

Thrown at crates/anthropic/src/completion.rs:171

                Ok(None)
            }
        }
        MessageContent::Image(image) => Ok(Some(RequestContent::Image {
            source: ImageSource {
                source_type: "base64".to_string(),
                media_type: "image/png".to_string(),
                data: image.source.to_string(),
            },
            cache_control: None,
        })),
        MessageContent::ToolUse(tool_use) => match tool_use.input {
            LanguageModelToolUseInput::Json(input) => Ok(Some(RequestContent::ToolUse {
                id: tool_use.id.to_string(),
                name: tool_use.name.to_string(),
                input,
                cache_control: None,
            })),
            LanguageModelToolUseInput::Text(_) => Err(anyhow::anyhow!(
                "Anthropic does not support custom tool calls"
            )),
        },
        MessageContent::ToolResult(tool_result) => {
            let content = match tool_result.content.as_slice() {
                [LanguageModelToolResultContent::Text(text)] => {
                    ToolResultContent::Plain(text.to_string())
                }
                _ => {
                    let parts = tool_result
                        .content
                        .into_iter()
                        .map(|part| match part {
                            LanguageModelToolResultContent::Text(text) => ToolResultPart::Text {
                                text: text.to_string(),
                            },
                            LanguageModelToolResultContent::Image(image) => ToolResultPart::Image {
                                source: ImageSource {

View on GitHub (pinned to bc538def45)

Solutions

  1. Use tools whose inputs are JSON (structured input schema) when Anthropic is the backend.
  2. Start a new thread after switching to Anthropic instead of replaying old tool calls.
  3. As a developer: convert Text input before serialization (e.g. wrap it as a JSON object) or skip incompatible turns with a warning.

Example fix

// before
LanguageModelToolUseInput::Text(_) => Err(anyhow::anyhow!(
    "Anthropic does not support custom tool calls"
)),
// after: wrap free-form text as JSON input
LanguageModelToolUseInput::Text(text) => Ok(Some(RequestContent::ToolUse {
    id: tool_use.id.to_string(),
    name: tool_use.name.to_string(),
    input: serde_json::json!({ "text": text.to_string() }),
    cache_control: None,
})),
Defensive patterns

Strategy: type-guard

Validate before calling

for message in &request.messages {
    for content in &message.content {
        if let MessageContent::ToolUse(tool_use) = content {
            if matches!(tool_use.input, LanguageModelToolUseInput::Text(_)) {
                // convert to JSON or reject before handing the request to Anthropic
            }
        }
    }
}

Type guard

fn is_anthropic_compatible(request: &LanguageModelRequest) -> bool {
    request
        .messages
        .iter()
        .flat_map(|message| message.content.iter())
        .all(|content| match content {
            MessageContent::ToolUse(tool_use) => {
                matches!(tool_use.input, LanguageModelToolUseInput::Json(_))
            }
            _ => true,
        })
}

Prevention

When it happens

Trigger: Replaying a thread that contains a tool call with text input into the Anthropic backend; switching models/providers mid-thread; custom tools that attach unstructured text as tool input.

Common situations: Switching the agent from another provider to Anthropic on an existing thread; custom tools without JSON schemas; imported transcripts or fixtures containing Text tool uses.

Related errors


AI-assisted analysis of zed-industries/zed@bc538def45 (2026-08-16). Data as JSON: /api/errors/d5c584e59bb35c9a. Report an issue: GitHub.