diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7032d101a63..2b8a0648882 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ Docs: https://docs.openclaw.ai
- Cron: split runtime execution state into `jobs-state.json` so `jobs.json` stays stable for git-tracked job definitions. (#63105) Thanks @Feelw00.
- Agents/compaction: send opt-in start and completion notices during context compaction. (#67830) Thanks @feniix.
- Moonshot/Kimi: default bundled Moonshot setup, web search, and media-understanding surfaces to `kimi-k2.6` while keeping `kimi-k2.5` available for compatibility. (#69477) Thanks @scoootscooob.
+- Moonshot/Kimi: allow `thinking.keep = "all"` on `moonshot/kimi-k2.6`, and strip it for other Moonshot models or requests where pinned `tool_choice` disables thinking. (#68816) Thanks @aniaan.
### Fixes
diff --git a/docs/concepts/model-providers.md b/docs/concepts/model-providers.md
index 0eb87f22ba9..ec81192abd2 100644
--- a/docs/concepts/model-providers.md
+++ b/docs/concepts/model-providers.md
@@ -431,7 +431,7 @@ See [/providers/kilocode](/providers/kilocode) for setup details.
`input: ["text", "image"]`; the bundled provider catalog keeps the chat refs
text-only until that provider config is materialized
- Moonshot: `moonshot` (`MOONSHOT_API_KEY`)
-- Example model: `moonshot/kimi-k2.5`
+- Example model: `moonshot/kimi-k2.6`
- Kimi Coding: `kimi` (`KIMI_API_KEY` or `KIMICODE_API_KEY`)
- Example model: `kimi/kimi-code`
- Qianfan: `qianfan` (`QIANFAN_API_KEY`)
@@ -488,13 +488,14 @@ need to override the base URL or model metadata:
- Provider: `moonshot`
- Auth: `MOONSHOT_API_KEY`
-- Example model: `moonshot/kimi-k2.5`
+- Example model: `moonshot/kimi-k2.6`
- CLI: `openclaw onboard --auth-choice moonshot-api-key` or `openclaw onboard --auth-choice moonshot-api-key-cn`
Kimi K2 model IDs:
[//]: # "moonshot-kimi-k2-model-refs:start"
+- `moonshot/kimi-k2.6`
- `moonshot/kimi-k2.5`
- `moonshot/kimi-k2-thinking`
- `moonshot/kimi-k2-thinking-turbo`
@@ -505,7 +506,7 @@ Kimi K2 model IDs:
```json5
{
agents: {
- defaults: { model: { primary: "moonshot/kimi-k2.5" } },
+ defaults: { model: { primary: "moonshot/kimi-k2.6" } },
},
models: {
mode: "merge",
@@ -514,7 +515,7 @@ Kimi K2 model IDs:
baseUrl: "https://api.moonshot.ai/v1",
apiKey: "${MOONSHOT_API_KEY}",
api: "openai-completions",
- models: [{ id: "kimi-k2.5", name: "Kimi K2.5" }],
+ models: [{ id: "kimi-k2.6", name: "Kimi K2.6" }],
},
},
},
diff --git a/docs/gateway/configuration-reference.md b/docs/gateway/configuration-reference.md
index 959cec5e85f..6729e00d9b4 100644
--- a/docs/gateway/configuration-reference.md
+++ b/docs/gateway/configuration-reference.md
@@ -2673,8 +2673,8 @@ Set `ZAI_API_KEY`. `z.ai/*` and `z-ai/*` are accepted aliases. Shortcut: `opencl
env: { MOONSHOT_API_KEY: "sk-..." },
agents: {
defaults: {
- model: { primary: "moonshot/kimi-k2.5" },
- models: { "moonshot/kimi-k2.5": { alias: "Kimi K2.5" } },
+ model: { primary: "moonshot/kimi-k2.6" },
+ models: { "moonshot/kimi-k2.6": { alias: "Kimi K2.6" } },
},
},
models: {
@@ -2686,8 +2686,8 @@ Set `ZAI_API_KEY`. `z.ai/*` and `z-ai/*` are accepted aliases. Shortcut: `opencl
api: "openai-completions",
models: [
{
- id: "kimi-k2.5",
- name: "Kimi K2.5",
+ id: "kimi-k2.6",
+ name: "Kimi K2.6",
reasoning: false,
input: ["text", "image"],
cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
diff --git a/docs/providers/moonshot.md b/docs/providers/moonshot.md
index b144e674d41..28b597b61e9 100644
--- a/docs/providers/moonshot.md
+++ b/docs/providers/moonshot.md
@@ -10,7 +10,7 @@ title: "Moonshot AI"
# Moonshot AI (Kimi)
Moonshot provides the Kimi API with OpenAI-compatible endpoints. Configure the
-provider and set the default model to `moonshot/kimi-k2.5`, or use
+provider and set the default model to `moonshot/kimi-k2.6`, or use
Kimi Coding with `kimi/kimi-code`.
@@ -23,6 +23,7 @@ Moonshot and Kimi Coding are **separate providers**. Keys are not interchangeabl
| Model ref | Name | Reasoning | Input | Context | Max output |
| --------------------------------- | ---------------------- | --------- | ----------- | ------- | ---------- |
+| `moonshot/kimi-k2.6` | Kimi K2.6 | No | text, image | 262,144 | 262,144 |
| `moonshot/kimi-k2.5` | Kimi K2.5 | No | text, image | 262,144 | 262,144 |
| `moonshot/kimi-k2-thinking` | Kimi K2 Thinking | Yes | text | 262,144 | 262,144 |
| `moonshot/kimi-k2-thinking-turbo` | Kimi K2 Thinking Turbo | Yes | text | 262,144 | 262,144 |
@@ -61,7 +62,7 @@ Choose your provider and follow the setup steps.
{
agents: {
defaults: {
- model: { primary: "moonshot/kimi-k2.5" },
+ model: { primary: "moonshot/kimi-k2.6" },
},
},
}
@@ -81,9 +82,10 @@ Choose your provider and follow the setup steps.
env: { MOONSHOT_API_KEY: "sk-..." },
agents: {
defaults: {
- model: { primary: "moonshot/kimi-k2.5" },
+ model: { primary: "moonshot/kimi-k2.6" },
models: {
// moonshot-kimi-k2-aliases:start
+ "moonshot/kimi-k2.6": { alias: "Kimi K2.6" },
"moonshot/kimi-k2.5": { alias: "Kimi K2.5" },
"moonshot/kimi-k2-thinking": { alias: "Kimi K2 Thinking" },
"moonshot/kimi-k2-thinking-turbo": { alias: "Kimi K2 Thinking Turbo" },
@@ -101,6 +103,15 @@ Choose your provider and follow the setup steps.
api: "openai-completions",
models: [
// moonshot-kimi-k2-models:start
+ {
+ id: "kimi-k2.6",
+ name: "Kimi K2.6",
+ reasoning: false,
+ input: ["text", "image"],
+ cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
+ contextWindow: 262144,
+ maxTokens: 262144,
+ },
{
id: "kimi-k2.5",
name: "Kimi K2.5",
@@ -218,7 +229,7 @@ search.
| Setting | Options |
| ------------------- | -------------------------------------------------------------------- |
| API region | `https://api.moonshot.ai/v1` (international) or `https://api.moonshot.cn/v1` (China) |
- | Web search model | Defaults to `kimi-k2.5` |
+ | Web search model | Defaults to `kimi-k2.6` |
@@ -234,7 +245,7 @@ Config lives under `plugins.entries.moonshot.config.webSearch`:
webSearch: {
apiKey: "sk-...", // or use KIMI_API_KEY / MOONSHOT_API_KEY
baseUrl: "https://api.moonshot.ai/v1",
- model: "kimi-k2.5",
+ model: "kimi-k2.6",
},
},
},
@@ -266,7 +277,7 @@ Config lives under `plugins.entries.moonshot.config.webSearch`:
agents: {
defaults: {
models: {
- "moonshot/kimi-k2.5": {
+ "moonshot/kimi-k2.6": {
params: {
thinking: { type: "disabled" },
},
@@ -288,6 +299,28 @@ Config lives under `plugins.entries.moonshot.config.webSearch`:
When Moonshot thinking is enabled, `tool_choice` must be `auto` or `none`. OpenClaw normalizes incompatible `tool_choice` values to `auto` for compatibility.
+ Kimi K2.6 also accepts an optional `thinking.keep` field that controls
+ multi-turn retention of `reasoning_content`. Set it to `"all"` to keep full
+ reasoning across turns; omit it (or leave it `null`) to use the server
+ default strategy. OpenClaw only forwards `thinking.keep` for
+ `moonshot/kimi-k2.6` and strips it from other models.
+
+ ```json5
+ {
+ agents: {
+ defaults: {
+ models: {
+ "moonshot/kimi-k2.6": {
+ params: {
+ thinking: { type: "enabled", keep: "all" },
+ },
+ },
+ },
+ },
+ },
+ }
+ ```
+
@@ -306,7 +339,7 @@ Config lives under `plugins.entries.moonshot.config.webSearch`:
| Kimi Coding| `kimi/` | Kimi Coding endpoint | `KIMI_API_KEY` |
| Web search | N/A | Same as Moonshot API region | `KIMI_API_KEY` or `MOONSHOT_API_KEY` |
- - Kimi web search uses `KIMI_API_KEY` or `MOONSHOT_API_KEY`, and defaults to `https://api.moonshot.ai/v1` with model `kimi-k2.5`.
+ - Kimi web search uses `KIMI_API_KEY` or `MOONSHOT_API_KEY`, and defaults to `https://api.moonshot.ai/v1` with model `kimi-k2.6`.
- Override pricing and context metadata in `models.providers` if needed.
- If Moonshot publishes different context limits for a model, adjust `contextWindow` accordingly.
diff --git a/docs/tools/kimi-search.md b/docs/tools/kimi-search.md
index 63ebeb12b96..4df4c5a062a 100644
--- a/docs/tools/kimi-search.md
+++ b/docs/tools/kimi-search.md
@@ -34,7 +34,7 @@ When you choose **Kimi** during `openclaw onboard` or
- the Moonshot API region:
- `https://api.moonshot.ai/v1`
- `https://api.moonshot.cn/v1`
-- the default Kimi web-search model (defaults to `kimi-k2.5`)
+- the default Kimi web-search model (defaults to `kimi-k2.6`)
## Config
@@ -47,7 +47,7 @@ When you choose **Kimi** during `openclaw onboard` or
webSearch: {
apiKey: "sk-...", // optional if KIMI_API_KEY or MOONSHOT_API_KEY is set
baseUrl: "https://api.moonshot.ai/v1",
- model: "kimi-k2.5",
+ model: "kimi-k2.6",
},
},
},
@@ -74,7 +74,7 @@ with `tools.web.search.kimi.baseUrl` when you need a different search base URL.
Gateway environment. For a gateway install, put it in `~/.openclaw/.env`.
If you omit `baseUrl`, OpenClaw defaults to `https://api.moonshot.ai/v1`.
-If you omit `model`, OpenClaw defaults to `kimi-k2.5`.
+If you omit `model`, OpenClaw defaults to `kimi-k2.6`.
## How it works
diff --git a/docs/tools/web.md b/docs/tools/web.md
index 36c8f88bf59..da82454645c 100644
--- a/docs/tools/web.md
+++ b/docs/tools/web.md
@@ -220,7 +220,7 @@ When you choose **Kimi** during `openclaw onboard` or
`openclaw configure --section web`, OpenClaw can also ask for:
- the Moonshot API region (`https://api.moonshot.ai/v1` or `https://api.moonshot.cn/v1`)
-- the default Kimi web-search model (defaults to `kimi-k2.5`)
+- the default Kimi web-search model (defaults to `kimi-k2.6`)
For `x_search`, configure `plugins.entries.xai.config.xSearch.*`. It uses the
same `XAI_API_KEY` fallback as Grok web search.
diff --git a/src/agents/pi-embedded-runner-extraparams-moonshot.test.ts b/src/agents/pi-embedded-runner-extraparams-moonshot.test.ts
index 666dec3218f..40e94e423f0 100644
--- a/src/agents/pi-embedded-runner-extraparams-moonshot.test.ts
+++ b/src/agents/pi-embedded-runner-extraparams-moonshot.test.ts
@@ -3,6 +3,7 @@ import { runExtraParamsPayloadCase } from "./pi-embedded-runner-extraparams.test
import { __testing as extraParamsTesting } from "./pi-embedded-runner/extra-params.js";
import {
createMoonshotThinkingWrapper,
+ resolveMoonshotThinkingKeep,
resolveMoonshotThinkingType,
} from "./pi-embedded-runner/moonshot-stream-wrappers.js";
@@ -15,7 +16,10 @@ beforeEach(() => {
configuredThinking: params.context.extraParams?.thinking,
thinkingLevel: params.context.thinkingLevel,
});
- return createMoonshotThinkingWrapper(params.context.streamFn, thinkingType);
+ const thinkingKeep = resolveMoonshotThinkingKeep({
+ configuredThinking: params.context.extraParams?.thinking,
+ });
+ return createMoonshotThinkingWrapper(params.context.streamFn, thinkingType, thinkingKeep);
}
return params.context.streamFn;
},
@@ -83,4 +87,87 @@ describe("applyExtraParamsToAgent Moonshot", () => {
expect(payload.thinking).toEqual({ type: "disabled" });
});
+
+ it("forwards thinking.keep=all to kimi-k2.6 requests", () => {
+ const payload = runExtraParamsPayloadCase({
+ provider: "moonshot",
+ modelId: "kimi-k2.6",
+ thinkingLevel: "low",
+ payload: { model: "kimi-k2.6" },
+ cfg: {
+ agents: {
+ defaults: {
+ models: {
+ "moonshot/kimi-k2.6": {
+ params: {
+ thinking: { type: "enabled", keep: "all" },
+ },
+ },
+ },
+ },
+ },
+ },
+ });
+
+ expect(payload.thinking).toEqual({ type: "enabled", keep: "all" });
+ });
+
+ it("omits thinking.keep on kimi-k2.6 when not configured", () => {
+ const payload = runExtraParamsPayloadCase({
+ provider: "moonshot",
+ modelId: "kimi-k2.6",
+ thinkingLevel: "low",
+ payload: { model: "kimi-k2.6" },
+ });
+
+ expect(payload.thinking).toEqual({ type: "enabled" });
+ });
+
+ it("strips thinking.keep for non-k2.6 models even when configured", () => {
+ const payload = runExtraParamsPayloadCase({
+ provider: "moonshot",
+ modelId: "kimi-k2.5",
+ thinkingLevel: "low",
+ payload: { model: "kimi-k2.5" },
+ cfg: {
+ agents: {
+ defaults: {
+ models: {
+ "moonshot/kimi-k2.5": {
+ params: {
+ thinking: { type: "enabled", keep: "all" },
+ },
+ },
+ },
+ },
+ },
+ },
+ });
+
+ expect(payload.thinking).toEqual({ type: "enabled" });
+ });
+
+ it("drops thinking.keep on kimi-k2.6 when thinking is forced off by pinned tool_choice", () => {
+ const payload = runExtraParamsPayloadCase({
+ provider: "moonshot",
+ modelId: "kimi-k2.6",
+ thinkingLevel: "low",
+ payload: { model: "kimi-k2.6", tool_choice: { type: "tool", name: "read" } },
+ cfg: {
+ agents: {
+ defaults: {
+ models: {
+ "moonshot/kimi-k2.6": {
+ params: {
+ thinking: { type: "enabled", keep: "all" },
+ },
+ },
+ },
+ },
+ },
+ },
+ });
+
+ expect(payload.thinking).toEqual({ type: "disabled" });
+ });
});
diff --git a/src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts b/src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts
index 07c495eab47..e6cd30048c5 100644
--- a/src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts
+++ b/src/agents/pi-embedded-runner/moonshot-stream-wrappers.ts
@@ -5,6 +5,7 @@ import { streamWithPayloadPatch } from "./stream-payload-utils.js";
export {
createMoonshotThinkingWrapper,
+ resolveMoonshotThinkingKeep,
resolveMoonshotThinkingType,
} from "./moonshot-thinking-stream-wrappers.js";
diff --git a/src/agents/pi-embedded-runner/moonshot-thinking-stream-wrappers.ts b/src/agents/pi-embedded-runner/moonshot-thinking-stream-wrappers.ts
index 504b0f7e0f7..1c46a283089 100644
--- a/src/agents/pi-embedded-runner/moonshot-thinking-stream-wrappers.ts
+++ b/src/agents/pi-embedded-runner/moonshot-thinking-stream-wrappers.ts
@@ -4,6 +4,8 @@ import { normalizeOptionalLowercaseString } from "../../shared/string-coerce.js"
import { streamWithPayloadPatch } from "./stream-payload-utils.js";
type MoonshotThinkingType = "enabled" | "disabled";
+type MoonshotThinkingKeep = "all";
+const MOONSHOT_THINKING_KEEP_MODEL_ID = "kimi-k2.6";
let piAiRuntimePromise: Promise | undefined;
async function loadDefaultStreamFn(): Promise {
@@ -35,6 +37,17 @@ function normalizeMoonshotThinkingType(value: unknown): MoonshotThinkingType | u
return undefined;
}
+function normalizeMoonshotThinkingKeep(value: unknown): MoonshotThinkingKeep | undefined {
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
+ return undefined;
+ }
+ const keepValue = (value as Record).keep;
+ if (typeof keepValue !== "string") {
+ return undefined;
+ }
+ return normalizeOptionalLowercaseString(keepValue) === "all" ? "all" : undefined;
+}
+
function isMoonshotToolChoiceCompatible(toolChoice: unknown): boolean {
if (toolChoice == null || toolChoice === "auto" || toolChoice === "none") {
return true;
@@ -68,9 +81,16 @@ export function resolveMoonshotThinkingType(params: {
return params.thinkingLevel === "off" ? "disabled" : "enabled";
}
+export function resolveMoonshotThinkingKeep(params: {
+ configuredThinking: unknown;
+}): MoonshotThinkingKeep | undefined {
+ return normalizeMoonshotThinkingKeep(params.configuredThinking);
+}
+
export function createMoonshotThinkingWrapper(
baseStreamFn: StreamFn | undefined,
thinkingType?: MoonshotThinkingType,
+ thinkingKeep?: MoonshotThinkingKeep,
): StreamFn {
return async (model, context, options) => {
const underlying = baseStreamFn ?? (await loadDefaultStreamFn());
@@ -90,6 +110,19 @@ export function createMoonshotThinkingWrapper(
payloadObj.tool_choice = "auto";
} else if (isPinnedToolChoice(payloadObj.tool_choice)) {
payloadObj.thinking = { type: "disabled" };
+ effectiveThinkingType = "disabled";
+ }
+ }
+
+ // thinking.keep is only valid on kimi-k2.6 when thinking is enabled. Gate
+ // by the final payload.model and final type so stray config never leaks.
+ const isKeepCapableModel = payloadObj.model === MOONSHOT_THINKING_KEEP_MODEL_ID;
+ if (payloadObj.thinking && typeof payloadObj.thinking === "object") {
+ const thinkingObj = payloadObj.thinking as Record;
+ if (isKeepCapableModel && effectiveThinkingType === "enabled" && thinkingKeep === "all") {
+ thinkingObj.keep = "all";
+ } else if ("keep" in thinkingObj) {
+ delete thinkingObj.keep;
}
}
});
diff --git a/src/plugin-sdk/provider-stream.test.ts b/src/plugin-sdk/provider-stream.test.ts
index 0f064990198..115152c013e 100644
--- a/src/plugin-sdk/provider-stream.test.ts
+++ b/src/plugin-sdk/provider-stream.test.ts
@@ -83,13 +83,16 @@ describe("buildProviderStreamFamilyHooks", () => {
let capturedPayload: Record | undefined;
let capturedModelId: string | undefined;
let capturedHeaders: Record | undefined;
+ let payloadSeed: Record | undefined;
const baseStreamFn: StreamFn = (model, _context, options) => {
capturedModelId = model.id;
- const payload = { config: { thinkingConfig: { thinkingBudget: -1 } } } as Record<
- string,
- unknown
- >;
+ const payload = {
+ model: model.id,
+ config: { thinkingConfig: { thinkingBudget: -1 } },
+ ...payloadSeed,
+ } as Record;
+ payloadSeed = undefined;
options?.onPayload?.(payload as never, model as never);
capturedPayload = payload;
capturedHeaders = options?.headers;
@@ -172,6 +175,47 @@ describe("buildProviderStreamFamilyHooks", () => {
thinking: { type: "disabled" },
});
+ const moonshotKeepStream = requireStreamFn(
+ requireWrapStreamFn(moonshotHooks.wrapStreamFn)({
+ streamFn: baseStreamFn,
+ thinkingLevel: "low",
+ extraParams: { thinking: { type: "enabled", keep: "all" } },
+ } as never),
+ );
+ await moonshotKeepStream(
+ { api: "openai-completions", id: "kimi-k2.6" } as never,
+ {} as never,
+ {},
+ );
+ expect(capturedPayload).toMatchObject({
+ config: { thinkingConfig: { thinkingBudget: -1 } },
+ thinking: { type: "enabled", keep: "all" },
+ });
+
+ await moonshotKeepStream(
+ { api: "openai-completions", id: "kimi-k2.5" } as never,
+ {} as never,
+ {},
+ );
+ expect(capturedPayload).toMatchObject({
+ config: { thinkingConfig: { thinkingBudget: -1 } },
+ thinking: { type: "enabled" },
+ });
+ expect((capturedPayload?.thinking as Record) ?? {}).not.toHaveProperty("keep");
+
+ payloadSeed = { tool_choice: { type: "tool", name: "read" } };
+ await moonshotKeepStream(
+ { api: "openai-completions", id: "kimi-k2.6" } as never,
+ {} as never,
+ {},
+ );
+ expect(capturedPayload).toMatchObject({
+ config: { thinkingConfig: { thinkingBudget: -1 } },
+ tool_choice: { type: "tool", name: "read" },
+ thinking: { type: "disabled" },
+ });
+ expect((capturedPayload?.thinking as Record) ?? {}).not.toHaveProperty("keep");
+
const openAiHooks = OPENAI_RESPONSES_STREAM_HOOKS;
void requireStreamFn(
requireWrapStreamFn(openAiHooks.wrapStreamFn)({
diff --git a/src/plugin-sdk/provider-stream.ts b/src/plugin-sdk/provider-stream.ts
index 92c5798a930..6bed976e90a 100644
--- a/src/plugin-sdk/provider-stream.ts
+++ b/src/plugin-sdk/provider-stream.ts
@@ -3,6 +3,7 @@ import {
sanitizeGoogleThinkingPayload,
} from "../agents/pi-embedded-runner/google-stream-wrappers.js";
import { createMinimaxFastModeWrapper } from "../agents/pi-embedded-runner/minimax-stream-wrappers.js";
+import { resolveMoonshotThinkingKeep } from "../agents/pi-embedded-runner/moonshot-thinking-stream-wrappers.js";
import {
createCodexNativeWebSearchWrapper,
createOpenAIAttributionHeadersWrapper,
@@ -73,7 +74,10 @@ export function buildProviderStreamFamilyHooks(
configuredThinking: ctx.extraParams?.thinking,
thinkingLevel: ctx.thinkingLevel,
});
- return createMoonshotThinkingWrapper(ctx.streamFn, thinkingType);
+ const thinkingKeep = resolveMoonshotThinkingKeep({
+ configuredThinking: ctx.extraParams?.thinking,
+ });
+ return createMoonshotThinkingWrapper(ctx.streamFn, thinkingType, thinkingKeep);
},
};
case "kilocode-thinking":