From ea55911062eefcb0414cfddb84c8a4494c45f363 Mon Sep 17 00:00:00 2001 From: Kai Date: Thu, 2 Jul 2026 13:44:29 +0800 Subject: [PATCH] feat(agent-core): sharpen the compaction handoff prompt (#1283) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat(agent-core): sharpen the compaction handoff prompt Refine the first-person handoff note the model writes at compaction so it preserves what actually gets dropped instead of what already survives: - Lead with the intent of the latest request, not a verbatim re-transcription (the recent user messages are already kept verbatim beside the summary); name which request governs when several are in play. - Carry forward tool results — the concrete values, key lines, schemas — not just the commands that produced them. - Keep settled decisions separate from still-open questions, and name the context the next turn must go and re-check. - Write in the conversation's language, keep the note proportional to the task, and don't re-transcribe the auto-attached TODO list. Also correct the system prompt's description of the post-compaction shape: the recent user messages come first, followed by a first-person summary (not a rigidly sectioned report), and a newer kept message supersedes the summary. Update the affected inline snapshots and the compaction request token count. * fix(agent-core): preserve an oversized latest request in the handoff note selectRecentUserMessages truncates a kept user message to the size cap, keeping only its prefix, so when the latest request itself exceeds the cap only its head survives verbatim beside the summary. Telling the summary "don't re-transcribe, it survives verbatim" then permanently dropped the tail — often the actual ask. Keep the intent-not-transcription guidance, but require preserving the at-risk parts of a long current request. --- .../sharpen-compaction-handoff-prompt.md | 5 ++ .../compaction/compaction-instruction.md | 43 +++++++++++++---- .../agent-core/src/profile/default/system.md | 2 +- .../test/agent/compaction/full.test.ts | 46 +++++++++---------- 4 files changed, 64 insertions(+), 32 deletions(-) create mode 100644 .changeset/sharpen-compaction-handoff-prompt.md diff --git a/.changeset/sharpen-compaction-handoff-prompt.md b/.changeset/sharpen-compaction-handoff-prompt.md new file mode 100644 index 000000000..b89fb25f3 --- /dev/null +++ b/.changeset/sharpen-compaction-handoff-prompt.md @@ -0,0 +1,5 @@ +--- +"@moonshot-ai/kimi-code": patch +--- + +Sharpen the conversation-compaction handoff prompt so resumed sessions continue more reliably: the summary now leads with the intent of the latest request instead of re-transcribing it, carries forward tool results (not just the commands that produced them), separates settled decisions from still-open questions, names the context the next turn must re-check, matches the conversation's language, and stays proportional to the task. Also corrects the system prompt's description of the post-compaction shape. diff --git a/packages/agent-core/src/agent/compaction/compaction-instruction.md b/packages/agent-core/src/agent/compaction/compaction-instruction.md index 921068742..f0ee851f2 100644 --- a/packages/agent-core/src/agent/compaction/compaction-instruction.md +++ b/packages/agent-core/src/agent/compaction/compaction-instruction.md @@ -7,31 +7,58 @@ conversation is cleared. Write the note as your own continuing train of thought — first person, present tense, the way you would reason through the next move. Do not write a third-party report about someone else's work, and do not impose rigid section -headings; let the shape follow the task. +headings; let the shape follow the task. Write the note in the same language the +conversation has been using — do not switch to English just because these +instructions happen to be in English. Make the note self-sufficient: the next turn will see only your most recent user messages and this note — every assistant message, tool call, and tool result above will be gone. In your own words, preserve what you genuinely need to continue: -- The latest user request, quoted verbatim, and what it is actually asking for. +- What the latest request is actually asking for: your reading of its intent and + any ambiguity you have already resolved — not a re-transcription, since what + fits is kept verbatim in your most recent messages. But those kept messages are + size-capped, so a long request is truncated there: if the latest request is + large (a big paste or file), preserve the parts at risk of being dropped — + above all the actual ask. If several requests are in play, say which one governs + the next move, and re-quote any still-relevant earlier request that may have + scrolled out of the kept messages. - The instructions and constraints currently in force (user preferences, project rules, environment and tooling limits) — condensed to what still - matters. + matters, keeping decisions you have already settled (what you chose and why) + separate from questions still open, so you neither silently reopen a closed + choice nor treat an undecided point as decided. - What has actually been done, at high fidelity: keep the exact commands that - were run, the exact file paths touched, and whether each succeeded or failed. - Keep only the final working version of any code; drop intermediate attempts - and already-resolved errors. + were run, the exact file paths touched, and whether each succeeded or failed — + and the results themselves, not just the commands: the concrete values + returned, the key lines or error text, the schema or signature a lookup + revealed, since re-running to recover them may be slow or impossible. Keep only + the final working version of any code; drop intermediate attempts and + already-resolved errors. +- What you still don't know: context the next step depends on that this + conversation never established — files or paths referenced but not yet read, + schemas or APIs assumed but unseen, questions the user has not answered. Name + these gaps so the next turn goes and checks them instead of assuming. - The precise next action — including the exact next command or tool call you intend to make — and any required format for the final answer. +Your TODO list is re-attached automatically below this note from its live +source, so do not transcribe it — copying it wastes space and can contradict the +live version. What that list cannot hold is the reasoning between tasks — why one +was reordered or dropped, or a decision on one that constrains another — so +record that instead. + Be honest about uncertainty. If an earlier step claimed something was done but was never verified (tests "passing", a fix "working", a file "created"), say so plainly and treat it as unverified rather than fact — re-check before relying on it. -Be concise. Include the critical data, identifiers, and references needed to -continue, and omit anything that does not change the next move. +Be concise, and keep the note proportional to the task: a long multi-step task +warrants detail, but a trivial or nearly finished exchange needs only a sentence +or two — do not pad it out. Include the critical data, identifiers, and +references needed to continue, and omit anything that does not change the next +move. Respond with text only. Do not call any tools — you already have everything you need in the conversation history. diff --git a/packages/agent-core/src/profile/default/system.md b/packages/agent-core/src/profile/default/system.md index 9934290dc..bc71b2e88 100644 --- a/packages/agent-core/src/profile/default/system.md +++ b/packages/agent-core/src/profile/default/system.md @@ -56,7 +56,7 @@ The user may ask you to research on certain topics, process or generate certain When the conversation grows long, the system automatically condenses the older part of it. This happens on its own near the context limit — you do not trigger it, decide when it runs, or see any marker where it occurred. Your instructions, tool schemas, and working directory information are unaffected; only the earlier turns are rewritten. -After this happens, the start of your visible history is a single structured summary of the work so far (current focus, environment, completed steps, active issues, key file states, and any TODO list), followed verbatim by the most recent messages. Treat that summary as an accurate record of what already happened: do not redo work it reports as done, re-read files whose relevant contents it captured, or re-ask the user for information it contains. +After this happens, your most recent user messages are kept verbatim, followed by a single first-person summary of the work so far — the current request, the constraints in force, what you did (exact commands, paths, and outcomes), what you still don't know, and your next move, usually closing with a "## TODO List". Treat that summary as an accurate record of what already happened: do not redo work it reports as done, re-read files whose relevant contents it captured, or re-ask the user for information it contains. Where one of the kept messages is newer than the summary, follow the newer message and treat the summary as the older context it updates. The summary preserves conclusions, not live tool state. If you depended on something transient from before the summary — an open file's contents, a command's status, background work you started — re-establish it from the current project with your tools rather than trusting a value that may predate the summary. diff --git a/packages/agent-core/test/agent/compaction/full.test.ts b/packages/agent-core/test/agent/compaction/full.test.ts index fb2b8894e..a625ec114 100644 --- a/packages/agent-core/test/agent/compaction/full.test.ts +++ b/packages/agent-core/test/agent/compaction/full.test.ts @@ -76,10 +76,10 @@ describe('FullCompaction', () => { [wire] context.append_message { "message": { "role": "user", "content": [ { "type": "text", "text": "recent user three" } ], "toolCalls": [], "origin": { "kind": "user" } }, "time": "