1. 上下文管理的挑战
上下文(Context)是 Agent 的「工作记忆」——它决定了模型在每个 turn 中能「看到」多少信息,从而影响推理质量和决策能力。然而,上下文管理并非简单地「把所有历史消息塞给模型」,而是一道在容量、成本、准确性之间持续权衡的优化问题。
1.1 上下文窗口的物理限制
尽管主流 LLM 的上下文窗口已经扩展到了 128K、200K 甚至 1M token,但窗口的本质仍然是固定的有限资源。对于 kimi-code 这种可以执行长时间任务的 Agent 来说,一个 session 可能包含数百个 turn,累积的文本量远超单次可容纳的范围。当上下文窗口被占满时,模型将无法接收新的输入——这意味着 Agent 会「失忆」,丧失对对话前因后果的理解能力。
1.2 Token 成本的经济账
上下文长度不仅影响能力,还直接影响运行成本。当前主流 LLM 的定价模型通常将输入 token 和输出 token 分开计费,而输入 token 的数量与上下文长度成正比。一个有 50 轮对话的 session,如果每轮平均 2000 token,仅在输入端的消耗就达到 10 万 token——而这还没算工具调用返回的大量文本数据。
| 场景 | 平均 token / turn | 50 turn 累计输入 token | 估算输入成本(参考) |
|---|---|---|---|
| 简单问答 | ~800 | ~40,000 | 可忽略 |
| 代码分析(含文件内容) | ~3,000 | ~150,000 | 中等 |
| 多文件重构(含工具返回) | ~8,000 | ~400,000 | 较高 |
| 长篇调试(含大量日志) | ~15,000+ | ~750,000+ | 高 |
设计目标:上下文管理不是「越少越好」,而是在 token 预算 和 信息完整性 之间找到最优平衡——保留关键信息,裁剪冗余噪音。
1.3 注意力衰减
LLM 的注意力机制并非均匀分布——研究与实践表明,模型对上下文靠前和靠后的内容关注度更高,而对中间部分容易产生注意力衰减(又称"迷失在中间"效应)。这意味着即使上下文窗口足够大,将越积越多的历史全部堆进去,远端的关键信息也可能被模型忽略。
上下文管理需要解决的三个核心问题是:
- 容量约束:Token 总数不能超过模型上限
- 成本约束:在保证质量的前提下,尽可能减少 token 消耗
- 信息密度约束:上下文中每一段内容都应该「物有所值」,对推理有实质贡献
1.4 Prompt Cache 的价值
多数 LLM 提供商支持 Prompt Cache——对上下文中不变的前缀部分进行缓存,后续请求只需为增量部分付费。这意味着将稳定内容放在前端、变化内容放在后端可以显著降低成本。这是接下来要讨论的上下文字段排序和 compaction 策略的重要约束。
2. ContextMemory 设计
ContextMemory 是 kimi-code 上下文系统的核心数据结构,承担着「对话历史的存储器」角色。它不是简单的消息数组,而是一个具备容量感知、优先级排序和压缩能力的智能缓存。
2.1 数据结构
ContextMemory 的核心是一个按时间顺序排列的消息列表,每条消息包含角色标记、内容体、以及用于压缩决策的元数据:
// ContextMemory 的核心数据模型(简化伪代码)
interface ContextMemory {
// 按时间顺序排列的消息列表
messages: Message[];
// 当前累计 token 数(缓存值,避免每次重新计数)
tokenCount: number;
// 元信息
metadata: {
sessionId: string;
totalTurns: number;
lastCompactionAt: number;
compactionCount: number;
};
}
interface Message {
id: string;
role: 'system' | 'user' | 'assistant' | 'tool';
content: string | ToolResult[];
timestamp: number;
// —— 压缩策略用到的关键字段 ——
// 优先级:数值越高,越不容易被压缩裁剪
priority: MessagePriority;
// 是否可以被压缩(某些特殊消息需要强制保留)
compressible: boolean;
// 消息的「保质期」——过期后可安全压缩
ttl?: number;
// 工具调用相关
toolCallId?: string;
toolName?: string;
}
enum MessagePriority {
Critical = 100, // 系统关键信息,永远不压缩
High = 75, // 用户指令、工具调用的关键结果
Normal = 50, // 一般对话内容
Low = 25, // 中间推理步骤、冗余信息
Trivial = 0, // 可随时丢弃的确认消息
}
2.2 Token 计数机制
精确的 token 计数是压缩决策的前提。kimi-code 使用 tiktoken 作为 tokenizer(与多数 OpenAI 模型使用的分词器一致),对消息内容进行实时计数。由于 token 计数本身也有开销,系统采用以下优化策略:
- 增量计数:新增消息时只计算该消息的 token 数并累加到总额,而非每次重新计算全集
- 缓存命中:已被计数过的消息(内容未变化时)直接使用缓存值
- 估算兜底:对于不支持 tokenizer 的模型或超长内容,使用字符数/4 的粗略估算作为 fallback
// Token 计数的简化实现
class TokenCounter {
private encoder: Tiktoken;
private cache: Map<string, number>;
count(text: string): number {
// 缓存命中
if (this.cache.has(text)) return this.cache.get(text)!;
// 精确计数
const tokens = this.encoder.encode(text).length;
this.cache.set(text, tokens);
return tokens;
}
// 计算整条消息的 token 开销(包含角色标记的 overhead)
countMessage(msg: Message): number {
const overhead = 4; // 每条消息的格式开销(role 标记等)
return overhead + this.count(this.extractContent(msg));
}
}
2.3 消息的角色与组织
ContextMemory 中的消息严格遵循 LLM 的对话格式,支持四种角色:
| 角色 | 说明 | 优先级 | 压缩策略 |
|---|---|---|---|
system |
系统提示词、注入的策略规则 | Critical | 始终保留(使用 cache 锚定) |
user |
用户的原始输入 | High | 保留最新 N 条,更早的合并为摘要 |
assistant |
模型生成的推理和工具调用 | Normal | 保留工具调用结果,裁剪纯文本推理 |
tool |
工具执行返回的结果 | 按内容定 | 保留关键结果,裁剪冗余输出 |
2.4 消息的优先级与保留策略
MessagePriority 不是静态赋值的,而是在消息创建时根据其内容和上下文动态确定的:
- 用户的明确指令:优先级 High——这是任务的核心定义,不能丢失
- 工具调用的关键返回值:优先级 High——包含执行结果和后续决策依据
- 模型的中间推理链:优先级 Normal 到 Low——有价值但可被摘要替代
- 纯确认类消息:优先级 Trivial——如"已成功创建文件"的简单回执
- 系统注入的策略内容:优先级 Critical——如 Goal 状态、Plan 进度,不可压缩
设计洞察:优先级系统是压缩策略的「交通灯」。当 token 预算紧张时,系统从最低优先级的消息开始裁剪,逐步释放空间,而非一刀切地丢弃前 N 条。这种细粒度的裁剪方式最大程度保留了对话的核心脉络。
3. 上下文注入系统
在构建发送给 LLM 的最终上下文时,对话历史并非唯一成分。kimi-code 的 InjectionManager 负责在每个 turn 开始前,将来自多个子系统运行时信息动态注入到上下文中,确保模型始终掌握最新的执行状态和环境上下文。
3.1 InjectionManager 的职责
InjectionManager 是上下文组装管线的最后一环:
┌──────────────────────────────────────────────────┐ │ 上下文组装管线 │ │ │ │ ContextMemory ──┐ │ │ ├──▶ 上下文合并 ──▶ 注入排序 ──▶ 去重 ──▶ LLM │ 注入源 1 ────────┤ │ │ 注入源 2 ────────┤ │ │ 注入源 3 ────────┘ │ │ │ │ ▲ │ │ │ InjectionManager 调度 │ │ ┌─────────┴──────────────────────────┐ │ │ │ • 插件提醒 (Plugin Hints) │ │ │ │ • 技能提示 (Skill Prompts) │ │ │ │ • 配置文件规则 (Settings Rules) │ │ │ │ • Goal 状态摘要 (Active Goals) │ │ │ │ • Plan 进度 (Current Plan State) │ │ │ │ • Swarm 协调状态 (Swarm Status) │ │ │ └────────────────────────────────────┘ │ └──────────────────────────────────────────────────┘
3.2 注入来源详解
| 注入来源 | 内容 | 触发时机 | 优先级 |
|---|---|---|---|
| 插件提醒 | 活跃插件注入的上下文提示,如"请使用 git worktree 进行隔离开发" | 插件注册时 | Normal |
| 技能提示 | 当前激活 skill 提供的领域知识或约束规则 | skill 匹配触发时 | Normal |
| 配置规则 | 从 project/user settings 读取的常驻规则,如 CODEBUDDY.md 文件内容 | session 启动时 | High |
| Goal 状态 | 当前 active goal 的描述、进度、里程碑状态 | 每个 turn 开始前 | High |
| Plan 状态 | 当前执行计划的步骤列表与完成进度 | 每个 turn 开始前(Plan Mode 启用时) | High |
| Swarm 状态 | 并行子 Agent 的任务分配、完成状态、需要汇总的结果 | 子 Agent 返回结果时 | High |
3.3 注入时机与去重
所有注入操作在每个 turn 的「上下文组装阶段」统一执行——即 LLM 调用发起之前。InjectionManager 维护一个内容指纹集合,对注入项进行去重:如果两个注入源产生了相同或高度相似的内容,只保留优先级更高的那一份。
// InjectionManager 的注入与去重逻辑(简化)
class InjectionManager {
private sources: Map<string, InjectionSource>;
private fingerprints: Set<string>; // 已注入内容的指纹集合
collectInjections(): InjectItem[] {
const items: InjectItem[] = [];
for (const [name, source] of this.sources) {
const content = source.generate(this.context);
if (!content) continue;
const fp = this.hash(content);
if (this.fingerprints.has(fp)) {
// 重复内容 → 跳过
continue;
}
this.fingerprints.add(fp);
items.push({
source: name,
content,
priority: source.priority,
});
}
// 按优先级降序排列
return items.sort((a, b) => b.priority - a.priority);
}
private hash(content: string): string {
// 使用简单的规范化哈希检测重复
return this.normalize(content);
}
}
为什么不提前注入?延迟到每个 turn 组装时才收集注入内容,可以确保信息是最新的——例如 Goal 的状态可能在上一轮工具执行后发生了变化,提前注入会携带过时信息。
4. Compaction 压缩机制
压缩(Compaction)是 kimi-code 上下文管理中最重要的子系统。当对话历史积累到一定规模后,系统必须对其进行有损压缩——即用更少的 token 换取尽可能多的信息保留。Kimi-code 实现了两级压缩策略:微压缩和完全压缩,两者在不同阈值触发,形成渐进式的信息降级机制。
4.1 完全压缩(Full Compaction)
完全压缩是最深度的一级压缩,当 token 数接近模型上下文窗口上限时触发。其核心思想是用模型自身的能力对历史对话进行总结,将数千 token 的对话历史浓缩为一段几百 token 的结构化摘要。
触发条件
// 完全压缩的触发判断(简化)
function shouldFullCompact(memory: ContextMemory): boolean {
const usage = memory.tokenCount / memory.contextWindowSize;
return usage > 0.85; // 使用率达到 85% 时触发
// 或者连续微压缩后 token 仍在增长,触发升级
}
压缩算法
完全压缩并非简单地截断历史,而是走一个精心设计的流程:
1
选择压缩范围
从最早的消息开始,向最新的消息方向扫描,标记出可以被压缩的消息段(压缩窗口),同时跳过不可压缩的消息(如正在执行中的工具调用)。
2
提取关键信息
对压缩窗口内的消息进行分类提取:用户的核心意图、Assistant 做出的关键决策、工具调用的名称和结果摘要、用户提供的修正意见。
3
生成摘要
调用 LLM 将提取的关键信息整合为一段结构化的摘要文本。摘要包含:已完成任务的描述、进行中的任务状态、关键决策记录、未解决的问题列表。
4
替换消息
用生成的摘要替换压缩窗口内的所有消息(删除旧消息,在对应位置插入摘要消息),更新 token 计数。
// 完全压缩的简化伪代码
async function fullCompaction(memory: ContextMemory): Promise<void> {
// 1. 确定压缩窗口
const compactionWindow = selectCompressionWindow(memory.messages);
// 2. 分离不可压缩的消息
const { compressible, protected } = splitByCompressible(compactionWindow);
// 3. 构建总结请求
const summaryPrompt = buildSummaryPrompt(compressible, {
format: 'structured',
maxTokens: memory.contextWindowSize * 0.15, // 摘要占预算的 15%
});
// 4. 调用模型生成摘要
const summary = await llm.complete(summaryPrompt);
// 5. 用摘要替换压缩窗口
memory.messages = [
...memory.messages.slice(0, compactionWindow.start),
createSummaryMessage(summary),
...protected, // 受保护的消息紧接摘要之后
...memory.messages.slice(compactionWindow.end),
];
// 6. 更新元数据
memory.metadata.lastCompactionAt = Date.now();
memory.metadata.compactionCount++;
memory.tokenCount = recount(memory.messages);
}
保留与丢弃规则
| 保留 | 丢弃 / 压缩 |
|---|---|
| 用户最近 N 条原始消息 | 早期纯文本推理过程 |
| 重要的工具调用结果(如文件修改结果、测试输出) | 已完成工具调用的中间参数细节 |
| 关键决策点(如"我将使用 React 而非 Vue") | 重复的确认和纠错消息 |
| 任务目标定义和约束 | 已经被后续操作覆盖的早期内容 |
| 当前正在执行中的工具调用链 | 已解决且不再相关的错误诊断 |
摘要的格式与注入
生成的摘要以 system 消息的形式注入到上下文的前部(紧跟系统提示词之后),使用标准化的格式:
// 压缩摘要在上下文中的注入格式
[压缩摘要 — 用于替代早期对话]
- 已完成的任务: [摘要]
- 进行中的任务: [摘要]
- 关键决策: [摘要]
- 未解决的问题: [摘要]
- 重要文件: [变更记录]
4.2 微压缩(Micro Compaction)
微压缩是轻量级的中间预处理,在 token 数达到中间阈值时触发。与完全压缩不同,微压缩不对内容进行语义级总结,而是通过内容层面的裁剪和合并来释放空间。
触发条件
function shouldMicroCompact(memory: ContextMemory): boolean {
const usage = memory.tokenCount / memory.contextWindowSize;
return usage > 0.50; // 达到 50% 时开始微压缩
// 注意:微压缩和完全压缩的阈值可以级联 ——
// 微压缩后如果使用率仍然 > 85%,自动升级到完全压缩
}
微压缩的具体策略
微压缩执行以下操作,每一项都是低风险的优化:
- 工具结果截断:对于过长的工具返回内容(如 5000+ 字符的终端输出),保留前 N 行和后 N 行,中间用
[...truncated...]标记替换。这适用于日志输出、编译结果等包含大量重复模式的内容。 - 合并相似消息:将连续的 short assistant messages(如"好的""继续执行""让我检查一下")合并为一条描述性消息,减少 message overhead。
- 移除空白与格式冗余:对代码块中的多余空行进行压缩,对工具输出的纯 whitespace 行进行裁剪。
- 最低优先级消息裁剪:如果以上操作仍不够,从标记为 Trivial 优先级的消息开始移除。
// 微压缩的简化伪代码
async function microCompaction(memory: ContextMemory): Promise<boolean> {
let savings = 0;
for (const msg of memory.messages) {
// 跳过不可压缩的消息
if (!msg.compressible) continue;
// 策略1: 截断过长的工具输出
if (msg.role === 'tool' && msg.content.length > 5000) {
const before = tokenCounter.count(msg.content);
msg.content = truncateMiddle(msg.content, 2000);
const after = tokenCounter.count(msg.content);
savings += (before - after);
}
// 策略2: 移除 Trivial 优先级消息
if (msg.priority === MessagePriority.Trivial) {
const before = tokenCounter.countMessage(msg);
memory.messages = memory.messages.filter(m => m.id !== msg.id);
savings += before;
}
}
memory.tokenCount -= savings;
return true;
}
4.3 微压缩 vs 完全压缩
| 维度 | 微压缩 | 完全压缩 |
|---|---|---|
| 触发阈值 | 50% 上下文使用率 | 85% 上下文使用率 |
| 压缩方式 | 内容裁剪、合并 | 语义总结 |
| 信息损失 | 低(主要去冗余) | 中(细节被概括化) |
| LLM 调用 | 不需要 | 需要 1 次额外调用 |
| Token 节省 | 10-30% | 50-80%(对压缩段) |
| 是否需要升级 | 如果使用率仍 > 85%,升级为完全压缩 | 压缩后 token 大幅下降,无需再升级 |
为什么需要两级?单独使用完全压缩会频繁调用 LLM 生成摘要,增加延迟和成本。微压缩作为第一道防线,用几乎零成本的裁剪操作应对大部分轻微的超额。当微压缩不再有效时,才升级到完全压缩——这是一种渐进式降级策略。
4.4 压缩的边界条件
不是所有内容都可以压缩。以下「安全边界」确保了压缩不会破坏 Agent 的正确性:
- 不可压缩的消息:正在执行中的工具调用链——如果压缩掉了 tool_call 的上下文,模型将无法处理对应的 tool_result
- 未完成的 turn:如果当前 turn 还有 pending 的工具调用等待结果,该 turn 的 assistant 消息不能压缩
- 上下文一致性:压缩后的摘要必须保留原有的因果链——压缩到一半的任务必须在摘要中标明"进行中"而非"已完成"
与 Goal Mode 的交互
当 Agent 处于 Goal Mode 时,active goal 相关的上下文受到特殊保护。Goal 的描述、里程碑状态、进度信息被标记为 compressible = false,优先级为 Critical。这是因为 Goal 定义了任务的根本目标——如果压缩导致目标丢失,Agent 的行为将失去方向。
// Goal 相关消息的保护逻辑
function protectGoalContext(messages: Message[], activeGoal: Goal): void {
for (const msg of messages) {
// 任何引用了 active goal 的消息都被保护
if (msg.content?.includes(activeGoal.id)) {
msg.compressible = false;
msg.priority = MessagePriority.Critical;
}
}
}
5. Prompt Cache 优化
Prompt Cache(也称为 Context Caching)是现代 LLM API 的一个关键性能特性。它的工作方式类似于 HTTP 缓存:API 提供方对请求上下文的前缀部分进行哈希缓存,后续请求如果前缀相同,该部分不会重复计算,用户也只需为增量 token 付费。
5.1 利用 Cache 的上下文字段排序
kimi-code 在组装最终上下文时,有意识地将内容按「稳定性」从高到低排列:
上下文内容的稳定性排序(从高到低 / 从前到后): [最稳定 — 享受完整 Cache] [稳定 — 周期 Cache] [不稳定 — 不 Cache] 系统提示词 (System Prompt) → 注入内容 (Injections) → 对话历史 (Messages) ┌──────────────────────┐ ┌──────────────────────┐ ┌──────────────────────┐ │ • 基础 profile │ │ • 配置规则 │ │ • user/assistant/tool │ │ • 工具描述 │ │ • Goal 状态 │ │ 消息按时间排列 │ │ • 角色定义 │ │ • Plan 进度 │ │ • 最新消息在最末尾 │ │ • 行为约束 │ │ • Skill 提示 │ │ │ └──────────────────────┘ └──────────────────────┘ └──────────────────────┘
这种排序策略带来两个直接好处:
- 系统提示词完全缓存:基础 profile 和工具描述在一个 session 内很少变化,这部分 token 只计费一次
- 注入内容部分缓存:配置规则稳定不变;Goal 和 Plan 在同一 turn 内不变,跨 turn 才变化,因此至少在一个 turn 内的多次 LLM 调用间可以命中缓存
- 对话历史不缓存:新增的用户消息和助手回复位于末尾,不影响前缀缓存的命中
5.2 增量更新策略
当需要修改缓存友好的前缀内容时(如动态添加/移除工具描述),kimi-code 遵循以下策略:
- 尽量在其所在段落的末尾追加:而非在中部插入。前缀每增加一个 token 都会使缓存失效,而末尾追加则只影响新增部分
- 批量更新:如果一个 turn 内多个注入源产生变化,收集所有变更后一次性应用到上下文中,而非每个变更触发一次重建
- 缓存失效监控:记录每次缓存 hit/miss 的统计,用于评估优化效果
6. 系统提示词管理
系统提示词(System Prompt)是上下文中的「不变量」——它定义了 Agent 的身份、能力边界和行为准则。kimi-code 的系统提示词采用分层架构,由多个模块按优先级叠加组合而成。
6.1 分层结构
系统提示词的分层结构(从上到下 / 从底层到高层): ┌───────────────────────────────────────────────────────┐ │ Layer 4: 注入内容 (Injections) │ │ Goal 状态 / Plan 进度 / Swarm 协调信息 │ ├───────────────────────────────────────────────────────┤ │ Layer 3: 对话历史 (Conversation History) │ │ 用户消息 / Assistant 回复 / 工具调用结果 / 压缩摘要 │ ├───────────────────────────────────────────────────────┤ │ Layer 2: 工具描述 (Tool Descriptions) │ │ 动态生成:当前环境中可用的工具列表及其参数 schema │ ├───────────────────────────────────────────────────────┤ │ Layer 1: 基础 Profile (Base Profile) │ │ 身份定义 / 行为准则 / 输出格式 / 安全约束 │ └───────────────────────────────────────────────────────┘
6.2 Profile 的加载与合并
基础 profile 来自多个来源,按优先级合并:
// Profile 的合并优先级(从低到高,后者覆盖前者)
// 1. 内置系统 profile(框架硬编码的角色定义)
// 2. 工作空间 profile(MEMORY.md / CODEBUDDY.md)
// 3. 用户级 profile(~/.workbuddy/profile.md)
// 4. Session 级运行时注入(CLI 参数 / API 选项)
function buildBaseProfile(session: Session): string {
const profiles = [
BUILTIN_SYSTEM_PROFILE,
loadWorkspaceProfile(session.cwd), // MEMORY.md
loadUserProfile(), // ~/.workbuddy/profile.md
session.runtimeProfile, // 运行时参数
];
// 从底层向高层叠加
return profiles.filter(Boolean).join('\n\n---\n\n');
}
6.3 工具描述的动态生成
工具描述(Tool Descriptions)是系统提示词中最具动态性的部分。当 Agent 使用 select_tools 机制时,每次 LLM 调用前都会重新生成工具描述列表——只包含当前 turn 可能需要的那部分工具。这不仅减少了 token 消耗,也帮助模型聚焦于相关工具,减少「迷路」概率。
// 工具描述动态生成的简化流程
function generateToolDescriptions(
allTools: Tool[],
context: TurnContext
): string {
// 1. 过滤:只包含当前可用的工具
const availableTools = allTools.filter(t => t.isAvailable(context));
// 2. 排序:把最近使用过的工具放在前面(利用 cache 友好性)
const sorted = sortByRecency(availableTools, context.recentToolCalls);
// 3. 生成描述:每个工具包含名称、参数 schema、简要说明
const descriptions = sorted.map(tool => ({
name: tool.name,
description: tool.description,
parameters: JSON.stringify(tool.parameters),
}));
// 4. 格式化输出
return formatToolList(descriptions);
}
select_tools 对上下文的影响:当工具集变化时,系统提示词的工具描述部分也会变化。这会导致 Prompt Cache 该部分失效。因此 select_tools 的筛选逻辑应该尽量稳定——如果过滤条件在 session 中变化不频繁,缓存命中率会更高。
7. 记忆系统
上下文管理解决的是「当前 session 内的记忆」问题,但 Agent 的智能还需要跨 session 的持久记忆。kimi-code 的记忆系统由三个层次构成,从短暂到持久逐级增强。
7.1 Session 级别记忆
Session 记忆即 ContextMemory 中保存的当前对话历史。它的特征是全量、实时、但生命周期有限——session 结束即销毁(如果不保存 transcript)。这是 Agent 的「工作记忆」,用于当前任务的理解和推理。
7.2 用户 Profile 的持久化
用户 profile 是跨 session 的第一层持久化记忆。它保存在用户目录下(~/.workbuddy/profile.md),内容由用户手动维护或 Agent 在用户允许下更新。Profile 包含:
- 用户偏好的代码风格和命名规范
- 常用的工具链和项目结构偏好
- 技术栈偏好(语言、框架、数据库等)
- 自定义的行为规则和约束
Profile 在 Agent 启动时被加载并合并到系统提示词中,确保即使在新 session 中,Agent 也「了解」用户的偏好。
7.3 工作空间记忆(MEMORY.md)
MEMORY.md(也叫 CODEBUDDY.md)是保存在项目根目录下的项目级持久记忆文件。与用户 profile 不同,它是项目相关的、团队共享的。Agent 在 session 中可以将关键的项目理解写入这个文件,下次打开同一项目时自动加载。
// 工作空间记忆的读写流程
class WorkspaceMemory {
private filePath: string; // e.g., d:/code/my-project/CODEBUDDY.md
async load(): Promise<string | null> {
try {
return await fs.readFile(this.filePath, 'utf-8');
} catch {
return null; // 文件不存在,首次启动
}
}
async update(content: string): Promise<void> {
// 由 Agent 在完成任务后写入(需用户许可)
await fs.writeFile(this.filePath, content, 'utf-8');
}
}
7.4 三种记忆的对比
| 记忆类型 | 存储位置 | 生命周期 | 共享范围 | 典型用途 |
|---|---|---|---|---|
| Session 记忆 | 内存 (ContextMemory) | 单次 session | 当前对话 | 理解当前任务的上下文、跟踪执行进度 |
| 用户 Profile | 磁盘 (~/.workbuddy/) | 持久 | 该用户的所有项目 | 代码风格偏好、技术栈选择、行为约束 |
| 工作空间记忆 | 磁盘 (项目根目录 CODEBUDDY.md) | 持久 | 该项目团队成员 | 项目架构决策、关键约定、依赖说明 |
设计哲学:kimi-code 的记忆系统遵循「最近记忆在内存,关键记忆落磁盘」的原则。Session 记忆提供实时推理所需的上下文;Profile 和 MEMORY.md 则确保 Agent 在跨 session 时不会从零开始——它至少了解用户是谁、项目是什么、之前达成了哪些共识。
总结
kimi-code 的上下文管理系统是一套从容量约束到记忆持久化的完整解决方案。它以 ContextMemory 为核心,通过消息优先级机制和两级压缩策略实现上下文的动态管理,通过 InjectionManager 在关键节点注入运行时状态,通过 Prompt Cache 友好的字段排序降低运行成本,并通过分层的系统提示词和三级记忆系统确保 Agent 既不会遗忘当前任务,也不会在跨 session 时丢失长期知识。
理解上下文管理,是理解 Agent 如何「思考」和「记忆」的根本。它不是辅助子系统,而是 Agent 的认知基础设施——压缩算法决定了 Agent 能走多远,注入系统决定了 Agent 知道什么,记忆系统则决定了 Agent 是否能持续成长。
关键洞察:上下文管理的本质是信息经济学——用有限的 token 预算实现信息的最大效用。优先级、压缩、缓存、注入,每一个机制都在回答同一个问题:「在给定的容量约束下,当前最值得让模型看到的信息是什么?」
浙公网安备 33010602011771号