Skip to content

Fix invalid parallel_tool_calls field in Anthropic requests (#11) - #12

Open
benwoody wants to merge 1 commit into
EthereumPhone:mainfrom
benwoody:fix/issue-11-parallel-tool-calls
Open

Fix invalid parallel_tool_calls field in Anthropic requests (#11)#12
benwoody wants to merge 1 commit into
EthereumPhone:mainfrom
benwoody:fix/issue-11-parallel-tool-calls

Conversation

@benwoody

Copy link
Copy Markdown

Fixes #11.

Problem

The Claude (OAuth) provider was failing every request with HTTP 400:

{
  "type": "error",
  "error": {
    "type": "invalid_request_error",
    "message": "parallel_tool_calls: Extra inputs are not permitted"
  },
  "request_id": "<...>"
}

AnthropicClient.serializeRequest was unconditionally adding parallel_tool_calls to every Anthropic request whenever tools was non-null. That field belongs to OpenAI's Chat Completions API — Anthropic's
Messages API rejects it as an unknown input.

Fix

Translate to Anthropic's equivalent: tool_choice.disable_parallel_tool_use (inverted). Only set when the user has opted out of parallel tool calls, so the default (parallel allowed) stays implicit in
the request body.

  request.tools?.let { tools ->
      put("tools", kotlinx.serialization.json.JsonArray(tools))
      if (!request.parallelToolCalls) {
          put("tool_choice", kotlinx.serialization.json.buildJsonObject {
              put("type", kotlinx.serialization.json.JsonPrimitive("auto"))
              put("disable_parallel_tool_use", kotlinx.serialization.json.JsonPrimitive(true))
          })
      }
  }

This preserves the existing Budget Mode "parallel tool calls" toggle behavior — when the user disables parallel tools in the UI, it now correctly translates to the Anthropic API's serial-tool-use
directive instead of being silently malformed.

Notes

  • OpenAiFormatAdapter.kt deliberately untouched. It also calls put("parallel_tool_calls", ...) but that field is valid in OpenAI-format requests — only the Anthropic client was wrong.
  • No test added. AnthropicClient has no existing test coverage and the repo doesn't yet use MockWebServer-style HTTP testing. Happy to follow up with a small test (and bump serializeRequest from
    private to internal) if you'd prefer.

Verified

Tested locally on a dGEN1 with the Claude (OAuth) provider and claude-sonnet-4-6: tool-using requests now complete instead of failing at body validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Claude (OAuth) provider sends OpenAI-only parallel_tool_calls field, causing 400 from Anthropic

1 participant