Inference APIs
Reference/Errors/Moonshot AI (Kimi)

"thinking is enabled but reasoning_content is missing in assistant tool call message": Kimi K2 tool loops fail on the second turn

Kimi K2 models think before they call a tool, and Moonshot returns that thinking as reasoning_content on the assistant message. On the next turn Moonshot expects the same field back, so the model can see what it was thinking when it made the call. Most OpenAI-compatible clients were written for an API where assistant messages have only content and tool_calls, so they drop the field when they rebuild the history, and the second request fails with this 400. Every tool call in a session then dies on its first result, which looks like the model "not working" rather than a serialisation problem.

Last verified September 18, 2026 against earendil-works/pi #4251 (👍18), microsoft/vscode #312746: Copilot drops reasoning_content (👍15), zed-industries/zed #51743 (👍13), Moonshot docs: thinking and reasoning_content · 4 min read

ProviderMoonshot AI (api.moonshot.ai) and hosts that reuse the Kimi chat template
HTTP status400 Bad Request
Messagethinking is enabled but reasoning_content is missing in assistant tool call message at index N
ModelsKimi K2.5, K2.6, K2.7 Code, K3 (thinking on)
When it happensOn the second turn of a tool loop: the client sends the conversation back with the assistant's tool call but without the reasoning_content that came with it
Who hits itopencode and pi, GitHub Copilot custom endpoints, Zed, Goose, and hand-written loops that copy only content and tool_calls
Can you wait it out?No. It is a validation rule, not capacity
Short answer
  • Own code: copy reasoning_content onto the assistant message you replay. One line.
  • A tool you do not control: update it (pi and opencode closed their reports as fixed) or use a host that does not require the field back.
  • Copilot custom endpoints dropped the field when the reports were filed (microsoft/vscode #312746); check your version, or use another host or model there.

What the error looks like

HTTP 400 · Moonshot AI (api.moonshot.ai) and hosts that reuse its template
{
  "error": {
    "message": "thinking is enabled but reasoning_content is missing in assistant tool call message at index 3",
    "type": "invalid_request_error"
  }
}

The index points at the assistant message in your messages array that carries tool_calls but no reasoning_content. A history that fails typically looks like this:

What the client sent back: the previous assistant turn without its reasoning
[
  {"role": "user", "content": "Run the tests and fix what fails."},
  {"role": "assistant", "content": null,
   "tool_calls": [{"id": "call_1", "type": "function", "function": {"name": "exec", "arguments": "{\"cmd\":\"pytest -q\"}"}}]},
  {"role": "tool", "tool_call_id": "call_1", "content": "2 failed, 8 passed"}
]

Why Moonshot requires it

With thinking enabled, the model's reasoning is part of its context for the turn that follows. DeepSeek, GLM and MiniMax treat a missing reasoning_content as "no reasoning to show" and carry on. Moonshot treats it as an invalid message and refuses, which is stricter but not wrong: the alternative is a model that silently loses the plan it was following.

The same rule is why Copilot's custom-endpoint mode failed with Kimi and DeepSeek thinking models: it rebuilt the history from its own representation without the field (microsoft/vscode #312746, 👍15).

Fix 1: keep the field when you replay

Python · keep reasoning_content on the replayed assistant message
msg = resp.choices[0].message
history.append({
    "role": "assistant",
    "content": msg.content,
    "tool_calls": [tc.model_dump() for tc in msg.tool_calls],
    "reasoning_content": getattr(msg, "reasoning_content", None),   # keep it; Moonshot requires it back
})

In streaming code, accumulate delta.reasoning_content the same way you accumulate delta.content, and store it on the message. If you use the OpenAI SDK, the field is preserved on the response object under model_extra; read it from there.

Fix 2: a host that does not require it

Hosts differ. On September 18, 2026 we replayed the history above, without reasoning_content, to each model we serve and asked for the tool result to be read back:

ModelReplay without reasoning_content
Kimi K2.7 CodeWorks
DeepSeek V4 Flash, V4.1 Flash, V4 ProWorks
GLM 5.3, GLM 5.3 FlashWorks
MiniMax M3Works
GPT-OSS 120BWorks
Llama 3.3 70BWorks (does not reason)

The full matrix, with streaming, tool_choice and JSON output, is on the model capabilities page.

Frequently asked questions

Can I just turn thinking off?

On Moonshot, yes: with thinking disabled the field is not required. You lose the reasoning, which for a coding agent is most of what you are paying Kimi for.

I send reasoning_content and still get the error.

Check the index in the message: one assistant message earlier in the history is probably missing it, often the first one, created before your fix.

Does the Responses API have this problem?

Only if the translation layer drops reasoning items. Ours keeps them, and Codex CLI sends them back on every turn.

Where Inference APIs fits

Kimi K2.7 Code runs here on a host that accepts the replayed tool call with or without reasoning_content. We tested the exact history above against every chat model we serve on September 18, 2026: all nine answered the second turn correctly. If the tool you use strips the field and you cannot change it, pointing it at our endpoint is a base URL change; the opencode and VS Code guides have the configs.

Something changed or wrong? Tell us and we will re-verify the entry.