Running openclaw against a self-hosted Kimi-K2 (sglang with --tool-call-parser kimi_k2 --reasoning-parser kimi_k2):
openclaw's wire format to OpenAI-compatible endpoints has two issues that break Kimi's chat template and cause the model to emit a preamble then halt with finish_reason=stop mid-task (no tool_calls, no further progress). Same model + same server work fine from other harnesses, so this is on the openclaw side.
-
Tool call IDs are stripped of punctuation
Session transcript stores functions.read:0 but the request wire sends functionsread0 — all dots and colons removed. Kimi's tool-call-parser kimi_k2 expects the native functions.<name>:<index> format, and the mangled IDs break tool-result matching on subsequent turns. -
reasoning_content is replayed in history
Every historical assistant message in the request carries its reasoning_content. Kimi's template treats reasoning_content as output-only; replaying it on input confuses the parser. Combined with (1), the model emits a text preamble like "Task 1 — …" then stops with finish_reason=stop. -
Top-level thinking: {type: "enabled"}
openclaw adds a top-level thinking field to the request body. Not an OpenAI field; upstreams can ignore it but worth dropping.
Any ideas why or how to fix?