Skip to content
Ziwen
Go back

Pi 与 Kimi code Hanress 分析

目录

分析范围:Kimi code 仅基于 packages/agent-core-v2;Pi 基于 packages/agentpackages/coding-agent 的主执行链路。

祝贺 Kimi K3 发布,让中国开源模型走向下一个阶段。

1. 引言与术语

Pi 和 Kimi code 都提供模型、工具、上下文、调度、持久化和交互能力,却选择了不同的组织方式:Pi 是容易嵌入的状态机,Kimi code 是分作用域、可恢复的调度内核。

两套代码对 Turn 的定义不同。本文使用三个中性术语进行比较:

中性概念PiKimi code
Conversation:长期对话与工作历史Session / Agent transcriptSession / Context Memory
Job:一项需要独立处理的任务通常是一次 Agent runTurn
Model round:一次 LLM 请求及工具处理TurnStep

Pi 的 Turn 是一次 Assistant 响应及其工具调用;Kimi 的 Turn 可以包含多个 Step,更接近完整任务。

2. 两套 Harness 全景

2.1 Pi:状态机外包一层产品编排

Pi Harness 架构全景

Pi 分为三层:runLoop() 执行模型与工具循环;Agent 保存 transcript、消息队列和运行状态;AgentSession 增加 Extension、持久化、重试和压缩。

调用链是 AgentSession → Agent → runLoop()。中间的 Agent 不是另一个循环,而是连接内外两层的状态容器:内层 runLoop() 处理正常执行,外层 AgentSession 在一次 run 结束后决定是否调用 agent.continue()

2.2 Kimi code:分 Scope 的调度内核

Kimi code Harness 架构全景

Kimi code 将生命周期分为 App、Session 和 Agent Scope。每个 Agent 拥有 Loop、Context、Tool、Wire 和 EventBus。Prompt、Goal、后台 Task、重试和压缩等模块生成 StepRequest,再由 Loop 统一调度。

两套设计的核心差异由此出现:Pi 用控制流组织 Agent,Kimi code 用工作请求组织 Agent。

3. 控制模型:控制流与 StepRequest

3.1 Pi:下一步写在循环条件中

Pi 的主循环直接理解业务含义:

模型调用工具 → 执行工具 → 再请求模型
出现 steering → 下一轮前注入 → 再请求模型
准备停止但有 follow-up → 注入消息 → 再请求模型

工具调用、steering queue、follow-up queue 和停止回调共同决定循环是否继续。正常路径集中在一个函数里,控制流直观,但 Loop 需要理解每种续跑原因。

3.2 Kimi:下一步成为工作请求

Kimi 将续跑原因转换成统一的 StepRequest

原因表达方式
用户开始任务PromptStepRequest
工具执行完毕ContinuationStepRequest
用户修正当前任务SteerStepRequest
瞬时错误失败请求重新入队
Context overflow压缩后重新入队
Goal 或 Hook 要求继续相应的 continuation request

这里的“续跑”是指当前 Model round 结束后,因为工具结果、错误恢复或用户补充而再次调用 LLM。Loop 只负责排空队列,“为什么继续”由请求生产者决定。

Pi 新增续跑原因,通常需要增加控制分支或外层处理;Kimi 新增续跑原因,通常只需增加一种 StepRequest 生产者。前者降低了理解成本,后者降低了扩展调度策略的成本。

4. 任务边界与并发输入

4.1 Pi:围绕一个 active run 排队

Pi 同时只允许一个 active run。运行期间再次调用 prompt() 会报错,调用方必须选择:

  • steer():当前工具 batch 完成后,尽快修正正在执行的任务。
  • followUp():当前任务原本准备停止时,再处理这条消息。

Pi 没有 pending run,也不会为后续消息预留独立 ID、取消信号和结果 Promise。两类消息都围绕当前 run 运转。

4.2 Kimi:先确定工作属于哪个 Turn

Kimi 将 Job 建模为 Turn。每个 Turn 创建时就获得 ID、状态、取消通道、结果 Promise 和独立队列。一个 Agent 只有一个 active Turn,但可以有多个 pending Turn。

StepRequest 通过 admission 声明归属:

admission语义
newTurn创建独立 Turn
activeOrNewTurn加入当前 Turn;空闲时创建 Turn
activeOrNextTurn加入当前 Turn;空闲时等待下一个 Turn
activeTurnOnly只能加入正在执行的 Turn

例如,用户在 Agent 工作时输入“不要修改公开 API”,它可以作为 steer 加入当前 Turn;“完成后再补测试”通常先成为 pending Prompt,之后创建新 Turn。

Pi 主要决定消息何时进入当前控制流;Kimi 还要决定工作由哪个可结算 Job 所有。

5. 错误恢复:Loop 外与 Loop 内

5.1 Pi:结束 run 后恢复

Pi 通常将请求失败编码为 stopReason: "error" 的 Assistant message,随后结束低层 run。AgentSession 再检查结果:

可重试错误 → 退避 → agent.continue()
Context overflow → 压缩 → agent.continue()
agent_end 后出现新消息 → agent.continue()

一次产品任务因此可能跨越多个 Agent run。低层 Loop 保持简单,但完整控制流分布在 runLoop()AgentSession 两层。

5.2 Kimi:在当前 Turn 内恢复

Kimi 将 Step 错误交给恢复模块。重试模块经过退避后把失败请求放回队首;压缩模块缩减 Context 后重新入队。恢复成功时,调用方看到的仍是同一个 Turn。

Kimi 用同一套队列处理正常续跑和异常恢复,但恢复模块必须在认领错误后安排下一 Step。

6. 状态、事件与持久化

6.1 Pi:统一的 awaited event stream

Pi 用一条 AgentEvent 流描述 Agent、Turn、Message 和 Tool 的生命周期。Agent 先根据事件更新内存状态,再依次等待 listener;AgentSession 通过 listener 转发 Extension 事件、持久化消息并通知 UI。

持久化属于宿主层:低层 Agent 先产生消息,AgentSession 再将 message_end 写入 SessionManager。这个模型容易嵌入,也保证事件与状态顺序一致;代价是慢 listener 会直接阻塞执行。

6.2 Kimi:三种机制分担职责

机制职责
Wire状态操作、Reducer、JSONL journal、恢复与迁移
EventBus向 UI、transport 和遥测广播事实
Ordered Hook有序介入 Step 生命周期,修改控制决策

Kimi 通过 Wire Op 更新内存模型并追加 journal,需要时再派生 EventBus 事件。必须影响下一 Step 的逻辑使用 Ordered Hook,而不是普通事件订阅。

因此,Pi 是“Agent 先运行,宿主记录结果”;Kimi 是“Agent 通过可记录的状态操作运行”。前者更轻,后者更适合恢复、迁移和多客户端同步。

7. 工具与 Context

7.1 工具执行

Pi 将工具执行和续跑放在同一个低层 Loop。一次 Assistant message 的工具组成一个 batch,执行结果写入 Context 后,Loop 直接判断是否再请求模型。

Kimi 将两项职责分开:ToolExecutor 执行工具,LoopContinuationService 在 after-step Hook 中决定是否提交 ContinuationStepRequest。Pi 的工具链更内聚,Kimi 的执行与调度边界更清晰。

7.2 Context 管理

Pi 在每次请求前通过 transformContext() 生成临时视图,再由 convertToLlm() 转换为供应商消息。持久压缩主要由 AgentSession 在 run 结束后完成。

Kimi 的 StepRequest 在真正出队时才把消息写入 Context,取消的排队请求不会污染历史。压缩既可以在 Step 前主动进行,也可以在 overflow 后恢复失败请求。

两者都区分请求视图和长期历史;Kimi 进一步将 Context 写入纳入调度过程:排队不等于提交,消费请求时才改变历史。

8. 架构取舍与结论

Pi 优先降低概念数量和嵌入成本,适合本地 CLI、单 active Agent,以及以工具和消息扩展为主的场景。它的复杂性主要留在宿主层:产品能力增多时,AgentSession 会逐渐承担第二套编排逻辑。

Kimi 优先处理运行时治理,适合多入口、多输入来源、长期任务和可恢复状态。它通过 Turn、StepRequest、Wire 和 Scope 统一编排,但也增加了 admission、队列和跨模块 Hook 的认知成本。

两条路线可以概括为:

Pi:简单内核 → 宿主逐层增强
Kimi:通用内核 → 业务模块按协议组合

两者的区别不在于是否支持工具调用,而在于如何表示尚未完成的工作:Pi 将它保留在运行状态中,有工具或消息就继续;Kimi 将它放入显式队列,每个继续原因都成为工作请求。

因此,Pi 更像一台透明、紧凑的 Agent 状态机;Kimi code 更像一个可调度、可恢复的 Agent 运行时内核。选择哪种设计,取决于系统的主要复杂性来自单个 Agent 的推理链,还是来自多个输入、生命周期和恢复策略之间的协调。


Share this post:

Previous Post
动态工具加载:四种 Agent Harness 的协议与实现