{"record":{"id":"1675337937ba38c3","repo":"zed-industries/zed","slug":"bedrock-does-not-support-custom-tools","errorCode":null,"errorMessage":"Bedrock does not support custom tools","messagePattern":"Bedrock does not support custom tools","errorType":"exception","errorClass":"anyhow::Error","httpStatus":null,"severity":"error","filePath":"crates/language_models/src/provider/bedrock.rs","lineNumber":1976,"sourceCode":"            }\n            other => other,\n        }\n    })\n}\n\npub fn into_bedrock(\n    request: LanguageModelRequest,\n    model: String,\n    default_temperature: f32,\n    max_output_tokens: u64,\n    thinking_mode: BedrockModelMode,\n    supports_caching: bool,\n    supports_tool_use: bool,\n    guardrail_identifier: Option<String>,\n    guardrail_version: Option<String>,\n) -> Result<bedrock::Request> {\n    if request.contains_custom_tool_input() {\n        anyhow::bail!(\"Bedrock does not support custom tools\");\n    }\n\n    let mut new_messages: Vec<BedrockMessage> = Vec::new();\n    let mut system_message = String::new();\n\n    // Track whether messages contain tool content - Bedrock requires toolConfig\n    // when tool blocks are present, so we may need to add a dummy tool\n    let mut messages_contain_tool_content = false;\n\n    for message in request.messages {\n        if message.contents_empty() {\n            continue;\n        }\n\n        match message.role {\n            Role::User | Role::Assistant => {\n                let mut bedrock_message_content: Vec<BedrockInnerContent> = message\n                    .content","sourceCodeStart":1958,"sourceCodeEnd":1994,"githubUrl":"https://github.com/zed-industries/zed/blob/f4178619acd0d47ea1f76a2025c42962c6d6638c/crates/language_models/src/provider/bedrock.rs#L1958-L1994","documentation":"into_bedrock converts a LanguageModelRequest into a Bedrock converse request and hard-rejects requests whose contains_custom_tool_input() is true: Bedrock's toolConfig accepts only JSON-schema function tools, so Zed's freeform 'custom' tool variant cannot be translated. The check runs first, before any message conversion.","triggerScenarios":"Selecting an AWS Bedrock model while a custom (prompt-style) tool is active in the request — e.g. an agent/tool extension that registers a Custom tool input instead of a Function with an input_schema.","commonSituations":"Enabling tools built for providers with custom-tool support (Anthropic direct, OpenAI) and then switching the model to Bedrock; extension upgrades adding custom tools to flows that also run on Bedrock.","solutions":["Switch the tool to a function-style tool (LanguageModelRequestToolInput::Function with a JSON input schema)","Disable the custom tool / extension before using a Bedrock model","Use a provider that supports custom tools (e.g. Anthropic direct) for that agent","Gate the feature in extension code on the current model's tool capabilities"],"exampleFix":"// before\nif request.contains_custom_tool_input() {\n    anyhow::bail!(\"Bedrock does not support custom tools\");\n}\n\n// after (caller-side guard)\nif model.provider_is_bedrock() && request.contains_custom_tool_input() {\n    request.tools.retain(|tool| matches!(tool.input, LanguageModelRequestToolInput::Function { .. }));\n}","handlingStrategy":"validation","validationCode":"if provider.is_bedrock() && request.contains_custom_tool_input() {\n    anyhow::bail!(\"custom tools unsupported for Bedrock; falling back to function tools\");\n    // or: request.tools.retain(|t| matches!(t.input, LanguageModelRequestToolInput::Function { .. }));\n}","typeGuard":"fn is_function_only_request(request: &LanguageModelRequest) -> bool {\n    !request.contains_custom_tool_input()\n}","tryCatchPattern":"match into_bedrock(request.clone(), ... ) {\n    Ok(bedrock_request) => send(bedrock_request).await,\n    Err(e) if e.to_string().contains(\"custom tools\") => disable_custom_tools_and_retry().await,\n    Err(e) => Err(e),\n}","preventionTips":["Check contains_custom_tool_input() in the dispatch layer before choosing the provider","Author shared tools as function tools with JSON Schemas — the universally supported shape","Advertise capability per model and let the UI gray out incompatible tool+model combinations"],"tags":["bedrock","aws","llm","tools","capability-mismatch"],"backgroundTag":"llm-provider-unsupported-tool-type","analyzedSha":"f4178619acd0d47ea1f76a2025c42962c6d6638c","analyzedAt":"2026-08-20T19:29:52.058Z","contentChangedAt":"2026-08-20T19:29:52.058Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}