04 代理循环与上下文工程
2026-10-06 07:31
04 代理循环与上下文工程
这是整套文档的地基。Pi 的其余所有能力(会话树、压缩、扩展、SDK)都是围绕这个循环和它的上下文组装规则长出来的。
1. 三个基本概念
- session(会话):Pi 对一段对话的完整记录,包含消息、工具调用与结果、模型切换、压缩等事件。
- tree(树):会话里的消息与事件构成一棵树;根到叶的每条路径叫分支(branch)。
- active branch(活动分支):以当前 entry(leaf)结尾的那条分支,它提供下一次模型请求的历史。
重要区别:会话文件保存整棵树,模型只看到活动分支。这是 Pi “探索另一条路而不丢历史” 的结构基础。
2. Agent loop(代理循环)
一次 run 的完整流程:
- 提交的消息被追加到活动分支;
- Pi 用 system prompt + 活动分支 + 可用工具 + 模型设置 组装请求,经选定的 provider 发出;
- provider 流式返回 assistant 响应,响应里可以同时有文本和 tool call;
- Pi 记录该响应,逐个执行每个 tool call,并记录结果——到此算一个 turn;
- 如果工具结果或排队消息还需要再一次模型请求,就开始下一个 turn;否则 run 结束。
user message
↓ (追加到活动分支)
组装请求 → provider 流式响应
↓
记录 assistant 响应
↓
逐个执行 tool call → 记录 tool result ← 一个 turn
↓
还有待办?── 是 ──→ 下一个 turn
│
否
↓
run 结束
排队消息的插入时机
| 消息 | 插入时机 |
|---|---|
steering(Enter) | 当前 assistant turn 之后,用于引导下一次响应 |
follow-up(Alt+Enter) | agent 完成所有待办工作之后 |
abort(Escape) | 停止当前 run,把排队消息退回编辑器 |
注意 abort 的行为:排队消息不会丢,而是回到编辑器由你决定是否重发。这是一个典型的“不替用户做决定”的设计。
3. 上下文是怎么拼出来的
一次模型请求由四类输入拼成:
| 输入 | 来源 |
|---|---|
| system prompt | Pi 的基础指令 + 发现的 context files(AGENTS.md / CLAUDE.md 等) |
| 对话历史 | 活动分支的 session entries,转换成模型兼容的 user / assistant / tool-result 消息 |
| 工具定义 | 当前启用的工具声明 |
| skill 描述 | 已发现 skill 的描述(全文按需加载) |
关键设计:
- Skill 是渐进披露的:常驻上下文里只有描述,完整指令在按需加载时才进入。
- Extension 可以加指令,也可以直接转换上下文。
- Prompt template 在“编辑器输入 → user message”这一步之前展开。
- 选中的文件、图片、粘贴的文本、shell 输出都可以成为消息内容。
4. 会话的持久化与分支
- 持久会话是 JSONL 文件;每个树节点有
id,并指向parentId;当前 entry 标识活动分支。 - 从较早的 entry 继续,就是在同一个文件里再开一条分支。
- fork / clone 会把选中的历史复制到新的会话文件。
- 模型上下文是从活动分支重建的,而不是从文件顺序读的。
- compaction 插入一条 summary entry,在后续模型请求里替换掉更旧的消息;原始 entry 仍保留在会话树里。
这是理解 Pi 数据安全的关键点:压缩是“改变模型可见视图”,不是“删数据”。
5. 接口层
| 模式 | 行为 |
|---|---|
| interactive | 在终端渲染会话与 agent 事件 |
| 跑一个 prompt 并输出最终回复 | |
| json | 把 agent 事件写成 JSONL |
| rpc | stdin 读 JSONL 命令,stdout 写响应与事件 |
| SDK | 在进程内创建并控制 agent session |
所有接口共用同一套 agent 与 session 机制——不是五份实现。这是阅读 Pi 源码时最应该先确认的一条架构事实。
6. 扩展与资源
- Extension 是加载进 Pi 进程的 TypeScript 模块。其 factory 函数向 Pi 注册:tools、commands、shortcuts、providers、event handlers、renderers、terminal UI。
- Skill 提供按需指令与附属文件。
- Prompt template 提供可复用的消息文本。
- Theme 提供终端颜色。
- Pi package 通过 npm 或 git 分发上述资源。
7. 信任与权限(先建立正确预期)
执行顺序是:先解析 project trust → 再加载 project settings 与项目资源 → 最后加载 context files。
两句必须记住的话:
- 启用的工具使用 Pi 进程的操作系统权限;
- Extension 就在该进程内执行。
所以 project trust 只解决“要不要加载这个目录提供的可执行资源”,它不是沙箱,也不限制工具能访问什么。真正的隔离要靠容器/虚拟机/专用账号。详见 07 工具系统与安全边界。
8. 一张图记住全局
┌─────────────────────── Pi 进程 ───────────────────────┐
│ │
session │ ┌─ agent loop ─┐ ┌──── 资源与扩展 ────┐ │
(JSONL │ │ 组装请求 │ │ extensions (TS) │ │
tree) ───┼──▶│ provider 流式 │◀───────│ skills / prompts │ │
│ │ 执行工具 │ │ themes / packages │ │
│ │ 记录结果 │ └─────────────────────┘ │
│ └──────────────┘ │
└───────┬─────────────────┬──────────────┬─────────────────┘
│ │ │
interactive print/json rpc / SDK
溯源
- 官方
docs/how-pi-works.md、docs/index.md、docs/sessions.md、docs/security.md