openinterpreter 中 Kimi CLI 压缩提示词全解:编码 Agent 如何安全地“瘦身”超长会话上下文
本篇围绕 openinterpreter(codex-rs 内核)中 Kimi CLI harness 专用的上下文压缩提示词 kimi_cli_compaction_prompt.md 展开:先讲清“压缩优先级、压缩规则、结构化输出契约”这份提示词本身的设计,再结合 compact.rs 与 kimi_cli.rs 的源码,说明它如何被编译进二进制、如何被识别为压缩请求、以及摘要生成之后会话历史如何被重建替换。读完后你将掌握编码 Agent 上下文压缩(compaction)的完整工作机制,并能给自己的 Agent 写出同样高质量的压缩提示词。
为什么编码 Agent 需要上下文压缩
编码 Agent 的会话天然是“长会话 + 高密度”的:用户指令、成百上千次的工具调用、命令输出、文件内容与报错信息都会不断追加到历史里。一旦活跃上下文逼近模型窗口上限,就有两条路可走:要么报错中断,要么先对历史做一轮“有损但可控”的压缩,用一份结构化摘要替换掉冗长细节。
openinterpreter 的核心实现了完整的压缩管线。从 compact.rs 的源码结构看:
- 手动压缩:run_compact_task 以
CompactionTrigger::Manual触发,独立成一个压缩轮次; - 自动压缩:run_inline_auto_compact_task 在会话接近 token 上限时内联触发,压缩轮次的输入提示词取
config.compact_prompt,未配置时回退到默认的 SUMMARIZATION_PROMPT(模板文件为 prompt.md); - 压缩请求在发出前后分别执行
pre_compact/post_compacthooks(见 run_compact_task_inner),并全程记录分析事件(压缩前后 token 数、耗时、触发原因、状态等); - 若压缩过程中仍报
ContextWindowExceeded,源码会从历史头部逐项丢弃最老条目后重试(compact.rs#L312-L321),以保住缓存前缀与最近消息。
而本文的主角,是面向 Kimi CLI harness(即面向 Kimi K3 一类开放模型走 Chat 协议接入的场景)专门定制的压缩系统提示词。它回答的问题是:让模型把一大段 agent 对话压缩成摘要时,该保留什么、合并什么、删掉什么,以及必须以什么结构输出。
压缩优先级:先保“当前正在干什么”
提示词开篇(kimi_cli_compaction_prompt.md)声明:上方是一份 agent 会话消息列表,现在要求你按特定优先级和规则压缩这段会话上下文。随后给出六个压缩优先级(按序排列):
| 优先级 | 内容 | 意图 |
|---|---|---|
| 1 | Current Task State(当前任务状态) | 正在做的那件事(RIGHT NOW),是摘要中价值最高的信息 |
| 2 | Errors & Solutions(错误与解法) | 所有遇到过的错误及其最终解决方案 |
| 3 | Code Evolution(代码演进) | 只保留最终可用版本,删除中间试错过程 |
| 4 | System Context(系统上下文) | 项目结构、依赖、环境配置 |
| 5 | Design Decisions(设计决策) | 架构选择及其理由(rationale) |
| 6 | TODO Items(待办事项) | 未完成任务与已知问题 |
这套排序体现了编码场景的信息价值判断:恢复会话时,模型最需要知道的是“现在干到哪一步了、之前踩了哪些坑怎么解的、最终代码长什么样”,而早期闲聊和失败的中间尝试则价值最低。这与通用摘要提示词 prompt.md(要求“当前进度与关键决策 / 重要上下文与约束 / 待办下一步 / 继续工作所需的关键数据”)取向一致,但 Kimi CLI 版本更强调代码与错误的保真。
压缩规则:MUST KEEP / MERGE / REMOVE / CONDENSE
提示词的第二部分把“可操作规则”拆成四个动词类别:
- MUST KEEP(必须保留):错误信息、堆栈追踪(stack traces)、可用解法、当前任务;
- MERGE(合并):把相似的讨论合并为单条总结点;
- REMOVE(删除):冗余解释、失败的尝试(但保留其经验教训)、啰嗦注释;
- CONDENSE(浓缩):长代码块只保留函数签名 + 关键逻辑。
注意 REMOVE 中“失败的尝试(保留教训)”这个细节——删除的是试错过程本身,但从中得出的结论要沉淀进摘要,避免后续 Agent 重复踩坑。
特殊处理策略:代码、错误与讨论的差异化压缩
Special Handling 一节给出三类内容的差异化策略,这是整份提示词中最具工程价值的设计:
- 代码:少于 20 行的代码块保留完整版本;超过 20 行则只保留签名 + 关键逻辑。20 行是一个明确的量化阈值,让模型的“保真 vs 压缩”决策没有歧义;
- 错误:保留完整错误信息 + 最终解法。这与优先级 2 呼应——错误现场是排查问题最稀缺的信息,摘要中宁可多占 token 也要原样保留;
- 讨论:只抽取决策(decisions)与行动项(action items),讨论过程本身丢弃。
这三条规则共同保证:摘要在体积上大幅缩水,但在“恢复任务所需的最小充分信息”上不打折。
输出契约:七个 XML 标签的结构化摘要
提示词最后强制规定摘要必须按如下结构输出(原文即为该契约模板,此处完整给出并逐段解读):
<current_focus>
[What we're working on now]
</current_focus>
<environment>
- [Key setup/config points]
- ...more...
</environment>
<completed_tasks>
- [Task]: [Brief outcome]
- ...more...
</completed_tasks>
<active_issues>
- [Issue]: [Status/Next steps]
- ...more...
</active_issues>
<code_state>
<file>
[filename]
**Summary:**
[What this code file does]
**Key elements:**
- [Important functions/classes]
- ...more...
**Latest version:**
[Critical code snippets in this file]
</file>
...more files...
</code_state>
<important_context>
- [Any crucial information not covered above]
- ...more...
</important_context>
各标签对应压缩优先级中的不同维度,可理解为“摘要的字段定义”:
<current_focus>:当前正在做什么,对应优先级 1,恢复会话的第一眼信息;<environment>:关键环境与配置要点,对应优先级 4 的 System Context;<completed_tasks>:已完成任务及简要结果,让后续 Agent 不必重复已做的工作;<active_issues>:未决问题及其状态/下一步,对应优先级 6 的 TODO;<code_state>:按文件组织的代码状态。每个<file>子块包含四要素——文件名、该文件职责的 Summary、Key elements(重要函数/类)、Latest version(关键代码片段)。这正是前文“代码压缩规则”的落地载体:每个文件只留最新关键代码;<important_context>:兜底字段,收纳上面六个维度未覆盖但至关重要的信息。
用 XML 标签而非自由文本,好处是确定性:后续模型读取摘要时能按标签定位“当前焦点”“环境”“文件状态”,而 compact.rs 的替换逻辑也依赖摘要作为历史中的最后一个消息项这一稳定约定。
源码视角:压缩提示词如何接入请求链路
编译期注入。该提示词通过 include_str! 在编译期嵌入二进制,成为 KIMI_CLI_COMPACTION_SYSTEM_PROMPT 常量(compact.rs#L48-L49)。这意味着它是 Kimi CLI harness 的内建行为,用户不可在线改写,也不依赖任何运行时文件。
压缩请求的识别。kimi_cli.rs 的 build_system_prompt 中有一段关键判断:当请求的工具列表为空、且 base instructions 的文本恰好等于 KIMI_CLI_COMPACTION_SYSTEM_PROMPT 时,直接把该常量作为系统提示词返回,跳过普通模板渲染(普通轮次会渲染 kimi_cli_prompt.md 并填充工作目录、目录列表、AGENTS.md、skills 等占位符)。换言之,“无工具 + 专属系统提示词”构成了 kimi-cli 压缩轮次的请求指纹;从源码结构看,可以推断压缩轮次由会话层把该常量设为 base instructions 后发起,从而走这条捷径。
请求形态。进入 build_request 后,kimi-cli 请求固定以 Chat 协议组织:首条 system 消息 + 完整历史 messages,max_tokens 取常量 KIMI_CLI_DEFAULT_MAX_TOKENS = 32_000(kimi_cli.rs#L29),带 prompt_cache_key(取会话 id)与流式 usage 统计;推理强度会按 reasoning_effort 映射为 low/medium/high 并启用 thinking。压缩轮次因为工具为空,tools 字段为空数组——模型只需产出一份纯文本摘要,不调用任何工具。
一个值得注意的细节:提示词首句写“The above is a list of messages...”(消息列表在上方),而从 build_request 看系统消息被放在 messages 数组首位。这属于提示词措辞与实际拼装顺序的差异,对通用指令遵循能力较强的模型影响不大,但从实现上说明该模板的措辞沿袭了“先贴会话、后附指令”的原始设计。
摘要生成之后:历史如何被重建替换
压缩请求完成后,管线在 run_compact_task_inner_impl 的后半段完成“换血”:
- 提取摘要:取本轮最后一条 assistant 消息作为
summary_suffix(compact.rs#L350-L353)——即上文那七个标签组成的结构化文本; - 挑选保留的用户消息:collect_user_messages 收集历史中的用户消息(跳过旧摘要),build_compacted_history_with_limit 从最近的消息往前取,直到逼近
COMPACT_USER_MESSAGE_MAX_TOKENS = 20_000token 上限,超出部分按 token 截断(compact.rs#L62); - 拼接替换历史:build_harness_compacted_history 对非 zcode harness 走通用分支——保留的用户消息 + 一条带 SUMMARY_PREFIX 前缀的摘要消息。该前缀会告诉接管的新模型:“另一个语言模型先解决了这个问题并产出了思考摘要,请基于它继续、不要重复劳动”,使摘要在语义上成为“前任模型的工作交接”;
- 重注入初始上下文:insert_initial_context_before_last_real_user_or_summary 把规范化的初始上下文(如环境信息)插回新历史中最后一条真实用户消息之前,保证摘要永远位于历史末尾;
- 持久化与收尾:replace_compacted_history 用新历史替换会话状态并推进 auto-compact 窗口号,随后重算 token 用量,并向前端发送一条提醒——“长线程与多次压缩可能降低模型准确性,请尽量开新线程”(compact.rs#L395-L398)。
也就是说,Kimi CLI 压缩提示词定义的 XML 摘要并不是“给人看的日志”,而是会原样进入替换后的会话历史、成为下一轮推理的输入的一部分。这解释了为什么提示词对输出结构的要求如此刚性:结构清晰直接决定后续轮次的可恢复性。
自定义压缩提示词的配置项及其边界
除了 harness 内建提示词,openinterpreter 还开放了用户级自定义:
compact_prompt:内联字符串,覆盖默认压缩指令,会作为压缩轮次的输入提示词(config_toml.rs#L245、解析逻辑见 config/mod.rs#L3900 附近);experimental_compact_prompt_file:从文件读取压缩提示词(config_toml.rs#L516),便于维护多行提示词;对应单测见 config_tests.rs 的loads_compact_prompt_from_file。
需要注意边界:这两个配置影响的是 run_inline_auto_compact_task 中的通用压缩指令来源;而 Kimi CLI 的 KIMI_CLI_COMPACTION_SYSTEM_PROMPT 走的是 harness 层的系统提示词通道,二者作用面不同。对面向 Kimi K3 等开放模型的接入(harness 为 kimi-cli),建议优先理解并沿用内建提示词的结构,再考虑通过 compact_prompt 补充项目特有的摘要要求(例如固定保留某些约定文件的状态)。
结语:把“压缩”当作交接文档来设计
Kimi CLI 压缩提示词的设计可以归纳为三点可复用的经验:
- 优先级量化:明确“当前任务 > 错误与解法 > 最终代码 > 环境 > 设计决策 > TODO”的保留顺序,让模型在 token 紧张时知道先丢什么;
- 规则动词化:MUST KEEP / MERGE / REMOVE / CONDENSE 四类操作 + “20 行以内保留完整代码”这类可判定阈值,减少模型的自由裁量;
- 输出契约结构化:用固定 XML 标签把摘要变成“字段化交接文档”,并与运行时的历史重建逻辑(摘要置于历史末尾、初始上下文重注入、20k token 用户消息保留)形成闭环。
这套机制与 openinterpreter 面向 Kimi K3 等开放模型的编码 Agent 定位(参见 docs/kimi-k3.md)一致:在不依赖专有模型“隐式记忆”的前提下,用确定性工程手段维持长会话的可用性与可控性。若你想为自己的 Agent 设计压缩机制,这份提示词与 compact.rs 的替换管线是两条都值得对照实现的主线。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00