Skip to content

Feature: inject reasoning_content pad on assistant tool-call messages when client doesn't echo it #676

Description

@a-bali

Context

GoModel is used as an OpenAI-compatible gateway in front of several backends behind a single virtual model alias, so clients have no way to know which upstream serves a given request. When a request is routed to the official DeepSeek API in thinking mode, tool-calling calls fail with:

400 invalid_request_error: The reasoning_content in the thinking mode must be passed back to the API.

Root cause

The official DeepSeek API enforces that every assistant message in a tool-calling request echoes reasoning_content. This only surfaces on the direct DeepSeek route: other routes (e.g. OpenRouter, OpenCode Zen) terminate the request at their own API surface, so the DeepSeek validator never sees the client payload.

Clients can't unconditionally attach DeepSeek-specific fields because the model name is a virtual alias and the upstream can rotate. GoModel is the only component that knows the actual backend.

Request

When GoModel forwards a chat/completions request to the direct DeepSeek provider and the request includes tools, ensure assistant messages with tool_calls carry reasoning_content:

  • Preserve the client-sent value if present.
  • Otherwise synthesize a placeholder — a single space " " (DeepSeek V4 rejects the empty string "" with the same 400).
  • Apply only on the DeepSeek route; never inject for other providers.
  • Natural insertion point: the DeepSeek provider's adaptChatRequest hook (internal/providers/deepseek/deepseek.go).

Related: #623 covers the case where the client already sends reasoning; this covers the case where it can't.

Metadata

Metadata

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions