Skip to content

[Bug] Anthropic models: tool calls fail with "Input tag 'input_json_delta' ... does not match any of the expected tags" (streamed tool_use never assembled) #6480

Description

@sepivip

MaxKB Version

v2.10.4-lts (also reproduced on v2.10.2-lts)

Problem Description

When an application has a custom tool attached and uses an Anthropic model (model_anthropic_provider), every message that triggers a tool call fails. The Anthropic API rejects MaxKB's follow-up request:

BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error',
'message': "messages.1.content.1: Input tag 'input_json_delta' found using 'type' does not match any of the expected tags"}}

and, in the other variant:

BadRequestError: Error code: 400 - {'type': 'error', 'error': {'type': 'invalid_request_error',
'message': 'messages: text content blocks must be non-empty'}}

MaxKB returns this to the caller as HTTP 200 with the error text as the answer body, so it reaches end users as the assistant's reply.

Cause

input_json_delta is an Anthropic streaming event type, not a message content type. Anthropic streams tool arguments as a series of content_block_delta events of type input_json_delta, each carrying a partial_json fragment. These must be accumulated and assembled into a completed tool_use content block before the assistant turn is replayed in messages.

MaxKB appears to replay the raw streamed deltas instead. A search of the v2.10.4-lts tree finds no handling for either field:

grep -rn "input_json_delta\|partial_json" apps/     # zero hits

_yield_mcp_response() in apps/application/flow/tools.py handles only OpenAI-shaped tool deltas (tool_call_chunks / tool_calls / invalid_tool_calls). There is no branch for Anthropic content blocks, which is consistent with both error messages: the unassembled delta is sent verbatim, and the accompanying text block is empty.

Steps to Reproduce

  1. Register an Anthropic model (reproduced with claude-sonnet-5, model_anthropic_provider).
  2. Create a SIMPLE agent using that model.
  3. Create a custom Python tool and attach it (tool_enable: true), e.g.
def live_price(query):
    return 'DJI Neo: 4242.42 GEL, in stock.'
  1. Set the system prompt so the tool is actually used, e.g. "For any question about price or stock you MUST call the live_price tool."
  2. Call the OpenAI-compatible endpoint with stream: true (required — with tools attached, stream: false is unsupported per [Bug] Exception:'generator' object has no attribute 'content' #6300 / [Bug] agent添加mcp,调用对话API 报错 #4846 / [Bug] Using non-streaming parameters when using MCP will return an error #4363):
curl -N "$MAXKB/chat/api/$APP_ID/chat/completions" \
  -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
  -d '{"model":"gpt-3.5-turbo","stream":true,"messages":[{"role":"user","content":"How much is the DJI Neo?"}]}'

Expected: the answer quotes the tool's value (4242.42 GEL).
Actual: the answer is the BadRequestError text above.

The same setup works on an OpenAI-shaped provider

Identical agent, identical tool, identical prompt, only the model swapped to model_openai_provider (gpt-4o-mini): no error, and the answer contains 4242.42 GEL, confirming the tool executed. This isolates the defect to the Anthropic provider's streamed tool-call handling rather than to tools, sandboxing, or the endpoint.

Impact

Custom tools and MCP cannot be used at all with Anthropic models. Because tools require stream: true, and streaming is exactly where the assembly fails, there is no working combination for Anthropic users.

Tested on v2.10.2-lts and v2.10.4-lts (CE), Docker, single-node.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions