Skip to content

[Bug] Assistant reasoning_content stripped on forwarding -> 400 (DeepSeek V4 thinking mode) #3547

Description

@RemyHaijie

Proposed Workgroup

Unsure / Maintainer triage

Describe the bug

Summary

When a request goes through the semantic router (vllm-sr) to an OpenAI-compatible upstream that serves a DeepSeek V4 model (deepseek-v4-flash) over the Chat Completions API, long multi-turn agent / tool-calling conversations start failing with:

HTTP 400
{"message":"The `reasoning_content` in the thinking mode must be passed back to the API.","type":"invalid_request_error","param":"","code":"invalid_request_error"}

The same client request sent directly to the same upstream (same messages, same tools, same reasoning_content fields) succeeds. Capturing the request after the router showed why: the router's ext_proc layer removes reasoning_content from every assistant message before forwarding upstream, so the upstream sees a tool-using conversation history with no reasoning content at all, which DeepSeek-V4-style gateways reject in thinking mode.

Environment

  • vllm-sr v0.3 (CLI vllm-sr validate reports Version: v0.3)
  • Images: ghcr.io/vllm-project/semantic-router/vllm-sr:latest, .../dashboard:latest, envoyproxy/envoy:v1.34-latest (2026-09)
  • Topology: Envoy :8891 -> ext_proc (router) -> upstream OpenAI-compatible gateway (in our case a New API-based self-hosted gateway) -> deepseek-v4-flash

To Reproduce

Repro

  1. Configure a cloud model card whose backend is an OpenAI-compatible DeepSeek V4 endpoint, e.g.:
providers:
  models:
    - name: cloud/frontier
      provider_model_id: deepseek-v4-flash
      api_format: openai
      backend_refs:
        - name: cloud-gateway
          base_url: <your-openai-compatible-gateway>/v1
          provider: openai
          type: openai
          api_key_env: OPENAI_API_KEY
          weight: 100
  1. Send a multi-turn agent-style request through vllm-sr/auto: several assistant turns with reasoning_content (real text and empty string) plus tool_calls, followed by tool result messages, e.g. 10+ assistant turns / 10 tool calls, max_completion_tokens ~8k.
  2. The router selects the cloud backend; the upstream answers 400 with the message above.

Direct vs routed comparison

messages' assistant reasoning_content
Client request sent to the router present on every assistant message (15/15, incl. real text and empty strings)
Request as actually forwarded by the router to upstream (captured) removed on every assistant message (0/15)

model was rewritten (vllm-sr/auto -> deepseek-v4-flash), everything else was preserved — only reasoning_content is stripped.

Notes observed from testing

  • The same upstream tolerates the request when it is sent directly (with or without reasoning_content in many shapes), but in thinking mode (the model returns reasoning_content and the conversation uses tools) its strict validation requires the field to be passed back on the assistant messages; once one request fails, later turns in the same conversation keep failing because the (rc-less) assistant messages are replayed.
  • Official DeepSeek (api.deepseek.com) currently tolerates missing reasoning_content, which is why the issue is only visible with stricter OpenAI-compatible gateways — but the protocol explicitly documents that reasoning_content must be passed back in thinking mode, so any conforming DeepSeek V4 endpoint will exhibit this.
  • Setting use_reasoning: true/false on the model decisions did not change the stripping.

Expected behavior

Add a way to preserve / pass through reasoning_content on assistant messages to the upstream — either per model/backend (e.g. a flag on the model card, since OpenAI-compatible DeepSeek-V4 style endpoints need the round-trip) or a global toggle — and/or document that the router always strips this field so operators can pick a compatible upstream.

Impact

Multi-turn agent / tool-calling traffic (the main use case for routing autonomous agents) routed to DeepSeek V4 thinking-model endpoints over OpenAI-compatible gateways is currently broken after the first tool round.

Additional context

Upstream error response (body returned on the failing request, 173 bytes):

{"message":"The `reasoning_content` in the thinking mode must be passed back to the API.","type":"invalid_request_error","param":"","code":"invalid_request_error"}

Envoy access log line for the failing request (hostnames sanitized):

[2026-09-07T10:34:02.136Z] "POST /v1/chat/completions HTTP/1.1" 400 - 186842 173 496 241 "-" "<client-user-agent>" "<request-id>" "<gateway-host>" "<gateway-ip>:443"

Router decision for the same request (trimmed):

{"msg":"routing_decision","request_id":"<request-id>","original_model":"vllm-sr/auto","decision":"long-context-to-cloud","selected_model":"cloud/frontier","reasoning_enabled":false}

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingwg/data-plane-networkingOwned by the Data Plane and Networking Workgroup.

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions