pi × tau / agent 教程
交互式教程 · 对比学习 Agent 开发

一个循环,两种实现
τ = 2π:tau 是 pi 的 Python 教学复刻

Coding agent 的核心只是十行循环:问模型 → 执行工具 → 结果回填 → 重复。这两个真实开源项目共享同一张架构蓝图——先在 tau 的 1,351 行核心里看懂它,再到 pi 的 11 万行里看它的生产形态。

▶ 先玩循环模拟器 直接看学习路径
111.7k
pi 源码行数(TS)
24.6k
tau 源码行数(Py)
4
默认工具(两者相同)
<1k
pi 的 harness token 开销
pi TypeScript · v0.80.6 · Mario Zechner (badlogic)

生产级极简 harness。npm 五件套:pi-ai(统一 1,057 个模型)/ pi-agent-core / pi-coding-agent / pi-tui。运行时扩展系统 + 自我扩展能力。Terminal-Bench 2.0 上与 Codex/Cursor 同级。

tau Python · v0.1.5 · alejandro-ao

"为阅读而生"的教学复刻:tau_ai / tau_agent / tau_coding 三层,核心循环 276 行。40 篇 dev-notes 逐阶段记录"这对应 pi 的什么设计"。也是能真用的终端 agent(PyPI:tau-ai)。

学习策略 本教程的用法

① 玩下面的模拟器建立直觉 → ② 按三层架构图定位代码 → ③ 逐机制对比读两边实现 → ④ 对照业界最佳实践 → ⑤ 做 12 个动手实验。配套详细文档在 agent-study/pi-vs-tau-架构对比学习指南.md

第 1 站 · 亲手转一圈

Agent 循环模拟器

场景:让 agent 修一个失败的测试。点「下一步」逐步执行,左边看循环走到哪一步,中间看对话如何生长,右边看事件流与上下文占用——这三样东西就是一个 harness 的全部可观察面。试试在它干活时点「插话 steer」。

step 0 / 15
准备就绪。harness 已装载:极小系统提示词(身份 + 4 个工具的一行描述 + AGENTS.md + skills 索引)。点「下一步」发出第一条用户消息。

循环 loop

会话 transcript

事件流 events

// AgentEvent 会出现在这里
上下文占用~1.0k tokens
图示范围 0–32k · 压缩触发 = 窗口−16,384(两者同参)

消息队列

当前阶段对应的真实源码(节选/简化)
packages/agent/src/agent-loop.ts
第 2 站 · 地图

三层架构:同一张蓝图

tau 从 pi 原样继承的口号:AgentHarness = 可复用大脑 · CodingSession = 编码环境 · TUI = 一种前端。依赖严格单向(自上而下),大脑层不知道终端的存在,前端只消费事件流。点开每一层看两边的对应实现。

产品层 · coding agent 本体
CLI / TUI / 内置工具 / 系统提示词 / 会话落盘 / 压缩 / skills / 配置凭据
pi-coding-agent
52,660 行 · TUI/print/JSON/RPC 四模式
tau_coding
19,832 行 · TUI/print 两模式
pi
  • 中枢 AgentSession(3,246 行):持久化 + 扩展 + 自动压缩 + 自动重试 + 模型切换
  • 7 个工具实现,默认启用 4 个;grep 走 ripgrep、find 走 fd(自动下载二进制)
  • RPC 模式:30+ 命令经 stdin/stdout 驱动外部前端
  • 扩展 / skills / prompt 模板 / 主题 / packages 五级定制
tau
  • 中枢 CodingSession(2,274 行):同职责减去扩展系统
  • 恰好 4 个工具;搜索靠 bash 里的 grep
  • Textual TUI(4,384 行)隔在 100 行 adapter.py 后面(ADR 0001)
  • skills + prompt 模板;extensions 明确推迟(Phase 21)
↓ 依赖方向(产品层 import 大脑层)
大脑层 · 可移植 agent 运行时
循环 / 事件 / 消息模型 / 工具接口 / steering 队列 / 会话数据结构
pi-agent-core
8,244 行 · 纯函数 loop + Agent 类 + harness
tau_agent
1,351 行 · loop.py 276 行一次读完
pi
  • agentLoop() 纯函数返回 EventStream<AgentEvent>;10 种事件
  • 工具默认并行执行;beforeToolCall / afterToolCall / prepareNextTurn 钩子
  • 截断守卫:stopReason=length 时全部工具调用拒绝执行
  • 运行中注册新工具(addedToolNames 延迟加载)
tau
  • run_agent_loop() 纯 async generator;14 种事件(pydantic)
  • 工具严格串行;异常在工具边界捕获转 ok=False
  • 取消后自动补"Tool call interrupted"合成结果,保 transcript 合法
  • 会话 = 追加式条目树 + SessionState.from_entries() reducer
↓ 依赖方向(大脑层调用 provider 层)
Provider 层 · 统一 LLM 流式 API
把各厂商私有协议翻译成中立事件流;认证 / 重试 / thinking 映射 / 模型目录
pi-ai
36,702 行 · 9 种 wire API · 1,057 模型
tau_ai
3,404 行 · 5 个适配器 · 手写 SSE
pi
  • 硬契约:stream 永不 throw,一切失败编码为流内 error 事件
  • 兼容性长尾:10 种 thinking 方言、24 条溢出错误正则、工具 ID 归一化 → 会话可中途换厂商
  • 真实 usage/成本核算 + 自动 cache_control 断点
  • OAuth:Claude Pro/Max、ChatGPT、GitHub Copilot
tau
  • ModelProvider 是 Protocol(结构化类型,无基类)
  • 零厂商 SDK:httpx + 手写 SSE 解析(教学价值高)
  • 7 种 ProviderEvent;工具调用整体交付不流增量
  • 刻意空白:无 usage/成本核算(chars/4 估算)——现成的练手 PR 选题
第 3 站 · 逐机制拆解

八大核心机制对比

每个机制:pi 怎么做 / tau 怎么做 / 业界最佳实践怎么说。展开即读;完整版(含 file:line 出处)见配套文档第 4 章。

工具系统read·write·edit·bash
pi
  • edit 有模糊匹配管线(NFKC/智能引号/异形空格),精确失败才启用
  • 并行批次 + 按 realpath 的文件互斥队列
  • grep/find/ls 可选启用
tau
  • edit 只做行尾归一化的精确匹配
  • 串行执行 + asyncio.Lock 文件锁
  • 没有搜索工具:让模型 bash 里跑 grep
共同设计即最佳实践:oldText 必须唯一(poka-yoke)、截断 footer 引导续读、错误消息可直接行动、prepareArguments 容忍模型笔误——全部对应 Anthropic《Writing effective tools》的建议。
循环与队列steer / follow-up
pi
  • steering 每轮开始+结束两次轮询注入
  • follow-up 在 agent 将停时注入(外层循环)
  • prepareNextTurn 可换模型/上下文
tau
  • 同款双队列(deque),默认 one-at-a-time
  • TUI:运行中 Enter=steer,Alt+Enter=follow-up
  • 用户消息也走事件流回显——前端只有一个数据源
关键约束:运行中调用 prompt() 直接抛错,插话必须走队列——保证 transcript 在任何时刻对 provider 合法。
系统提示词<1000 tokens
pi
  • ~25 行机械拼装;工具自带一行 promptSnippet
  • 指向自带文档的绝对路径——"agent 能解释自己"
tau
  • 同款拼装逻辑,注释直接写 "Pi-style"
  • skills 区块只在 read 工具存在时渲染
渐进式披露:skills 只放"名字+描述+路径"索引,模型需要时自己 read。对照 Claude Code 10k+ tokens 的提示词,pi 全套 <1k——Terminal-Bench 证明不吃亏。
会话持久化JSONL 条目树
pi
  • ~/.pi/agent/sessions/ 下 uuidv7 命名
  • /tree 分支、/fork、/clone、/share(gist)、HTML 导出
  • v1→v3 版本迁移
tau
  • 同款条目树 + leaf 指针;根目录有真实样本 session-temp.jsonl
  • 自动会话命名(对 pi 的有意分歧)
  • HTML/JSONL 导出
树而非数组,追加而不改写:分支=移动 leaf 指针;历史永不丢失;from_entries() 就是 12-Factor 说的"无状态 reducer"。每条 message_end 即落盘。
上下文压缩reserve 16,384
pi
  • 真实 usage 计数,chars/4 兜底
  • 切中 turn 时生成两段式摘要
  • 累计维护 read/modified 文件清单
tau
  • 纯 chars/4 估算(+每消息开销常数)
  • 同款结构化摘要提示词(Goal/Progress/Decisions/Next)
  • 同款溢出恢复:压缩一次 → 重试一次 → 放弃
切点永不落在 tool_call 与 tool_result 之间(否则 transcript 非法);溢出不走普通重试通道。context rot 是实测现象——badlogic 经验值:100k 后质量下滑。
扩展系统pi 的灵魂
pi
  • TS 扩展 jiti 热加载:33 个事件,可拦截 input/tool_call/context/provider 请求
  • 运行中 registerTool 立即可用 + /reload 闭环 → agent 自己扩展自己
  • skills / 模板 / 主题 / packages
tau
  • 只有 skills(严格 Agent Skills 规范,ADR 0003)+ prompt 模板
  • extensions 推迟到 Phase 21
  • custom 会话条目留了钩子
极简核心成立的另一半:pi 拒绝内置 MCP/权限/计划模式的每一条,都跟着"用扩展自己装一个"。ExtensionAPI 类型定义就是一份"harness 有哪些可拦截点"的清单。
安全与权限最有争议
pi
  • 无权限弹窗:“能写代码并执行的 agent,弹窗是安全剧场”
  • 要安全 → 容器 + 掐网络(3 种模式文档)
  • project trust:加载项目内扩展前须信任决策(是输入守卫,不是沙箱)
tau
  • 同立场,连确认弹窗都没有
  • 防御面:目录不可被克隆仓库覆盖、凭据 0600、bash 不 source rc
对照另一极:Claude Code 弹窗→沙箱(bubblewrap+网络代理)→auto mode 分类器。有趣的收敛:Anthropic 沙箱文章实质承认"真边界胜过弹窗"。权限的价值取决于信任上下文(个人工作站 vs 企业 SRE)。
TUI自研 vs 借力
pi
  • 自研 pi-tui:差分渲染只重画变化行、同步输出防闪烁、内联图片协议
  • 用 @xterm/headless 仿真终端做测试
tau
  • Textual + Rich,隔在 adapter 后(可整体换 UI 框架)
  • run_id 递增丢弃取消后迟到事件——异步 UI 竞态的经典解法
取舍范式:产品差异化在终端体验 → 自研;否则借力生态。做自己的项目时默认学 tau。
第 4 站 · 用数字看差距

规模与开销

"教学版 vs 生产版"的差距不在核心设计(两边循环几乎同构),而在兼容性长尾与测试覆盖。悬停条形可看明细。

各层源码行数对比

单位:千行(k LOC)· 不含测试 · pi v0.80.6 / tau v0.1.5

pi (TypeScript)tau (Python)
表格视图
pi 包pi 行数tau 包tau 行数
Provider 层pi-ai36,702tau_ai3,404
大脑层pi-agent-core8,244tau_agent1,351
产品层pi-coding-agent52,660tau_coding19,832
TUIpi-tui12,144(用 Textual)
测试全仓≈83,000tests/≈19,156

harness 注入模型上下文的固定开销(系统提示词 + 工具定义)

近似值 · 来源:badlogic 的 pi 宣言(pi <1k;Claude Code 10k+);tau 同构于 pi

这就是"薄 harness"论点的核心数字:Terminal-Bench 2.0 上 <1k 开销的 pi 与 10k+ 开销的大型 harness 成绩同级——省下来的都是任务可用的注意力预算。

第 5 站 · 对照业界共识

最佳实践对照

用 12-Factor Agents(生产 agent 的事实标准清单)逐条打分,再看两个项目"有意不做"的四件事——每张卡片可翻开看反方观点。

12-Factor 条目pi / tau实现方式
F2 拥有自己的提示词✓ 满分机械拼装,全部可见,无隐藏注入
F3 拥有上下文窗口✓ 满分transformContext / 压缩 / 溢出恢复全部自持
F4 工具只是结构化输出TypeBox / 手写 JSON Schema,无魔法装饰器
F6 启动/暂停/恢复 APIprompt / steer / follow_up / abort + JSONL resume
F8 拥有控制流循环就是自己的一个函数(276 行读完)
F9 错误压入上下文异常 → ok=false 工具结果;模型看见失败才会修
F12 无状态 reducerSessionState.from_entries() 字面实现
F7 用工具调用联系人类(HITL)✗ 无内置pi 的答案:"用扩展自己装"(tool_call 钩子可拦截)
F11 随处可触发◐ 部分pi 有 RPC/SDK/print;tau 只有 CLI
(补)系统化工具评测 evals✗ 两边都缺Anthropic 工具文章的第一条建议——自己做 agent 时补上

有意不做的四件事(点开看反方)

不做 MCP
"MCP server 动辄吃掉 7-9% 上下文窗口。CLI 工具 + README 更省。"
▸ 点开看反方与收敛点
反方:MCP 已捐入 Linux 基金会,OpenAI/Google 全采用,生态价值真实。
收敛点:Anthropic 自己也在推"代码执行式 MCP"把工具 schema 挪出提示词——双方都同意:工具目录不该全量常驻上下文。pi 生态用扩展外挂 MCP(OpenClaw/mcporter)。
不做内置子代理
"bash 里再开一个 pi 实例,全程可观察。"
▸ 点开看反方与收敛点
反方:Anthropic 多 agent 研究系统在研究类任务上 +90%(token 15 倍)。
收敛点:那篇文章明说 coding 不适合多 agent(上下文难共享、可并行度低)。pi 的立场对 coding 场景基本成立;做研究类产品时再引入编排。
不做权限弹窗
"能写代码并执行的 agent,弹窗是安全剧场。要安全→容器+掐网络。"
▸ 点开看反方与收敛点
反方:企业/SRE 场景需要审计、分级授权、HITL。用户数据也支持弹窗疲劳论(Claude Code 用户批准 93% 的弹窗)。
收敛点:Anthropic 沙箱方案(文件系统+网络双隔离)实质承认"真边界胜过弹窗";auto mode 用分类器替弹窗。权限的价值取决于信任上下文。
不做计划模式 / TODO 工具
"它们让模型困惑。用 TODO.md——文件更好且可观察。"
▸ 点开看反方与收敛点
反方:结构化任务利于 UI 呈现与多会话协作(Claude Code 的任务列表派)。
收敛点:Manus 的"复述 todo.md 对抗 lost-in-the-middle"支持文件派;本质是品味分歧,两条路都有大厂实践。
第 6 站 · 放进大地图

框架生态光谱

按抽象层级从"裸金属"到"全托管"排列。点击节点看定位与选型建议。pi/tau 证明了"薄 harness"档位的存在价值:比裸循环多了你一定会需要的四件套(多 provider、会话、压缩、中断插话),又不引入任何隐藏提示词。与 LangGraph 等框架的范式级深度对比(三种控制流范式、同一个 agent 的四种写法、概念对照表、决策清单)见文档第 11 章。

← 完全控制 · 更多自己写更多现成能力 · 更少控制 →
点击上方任一节点查看详情。
第 7 站 · 开始动手

学习路径与实验清单

核心策略:先 tau 后 pi——先用一个下午在 tau 里建立完整心智模型,再带着地图去 pi 里看生产形态。实验进度保存在本地浏览器。

第一周 · tau:建立心智模型

每一步都是一次可完成的阅读
  1. README + 官网 internals/architecturedesign-principles(背下 7 条原则)
  2. 数据模型:tau_agent/messages.py(47 行)→ tools.pyevents.py
  3. 核心:loop.py(276 行),对照官网 agent-loop 页逐步读
  4. harness.py:双队列、取消、transcript 修复
  5. session/:entries → tree → memory(reducer!)+ 根目录 JSONL 样本
  6. tau_ai/provider.py + anthropic.py:手写 SSE 长什么样
  7. 产品层择要:tools.py 四工具全文 → system_prompt.pysession.py
  8. 泛读 dev-notes/:roadmap、04-sessions、ADR 0003

第二周 · pi:看生产形态

带着 tau 的地图找差异
  1. coding-agent/README Philosophy 段 + docs/security.md(无权限论证全文)
  2. agent-loop.ts 对照 loop.py:steering 注入 / 截断守卫 / 并行执行 / prepareNextTurn
  3. agent.ts(订阅者顺序结算)+ types.ts(AgentTool 接口)
  4. core/tools/edit-diff.ts:模糊匹配管线精读
  5. system-prompt.ts / compaction.ts / docs/session-format.md
  6. pi-ai/types.ts(9 种 API、compat 开关)+ overflow.ts(感受长尾)
  7. 扩展系统:extensions/types.ts + examples/extensions/ 逐个跑
  8. 外围:badlogic 宣言、Armin Ronacher 评测、Terminal-Bench

进阶:从零复刻一个自己的 mini-harness

主文档第 9 章「从零复刻」· M0–M10 共 11 个里程碑

读完看懂 ≠ 会造。施工图从空目录出发:M0 骨架与依赖守卫 → M1 核心类型 → M2 FakeProvider+真适配器 → M3 循环(四大守卫)→ M4 四工具 → M5 队列 → M6 提示词 → M7 JSONL 会话 → M8 print 模式(用它修一个真 bug)→ M9 压缩 → M10 选做。每个里程碑都带验收测试与 pi/tau 对照文件,附「十大典型翻车」预防清单。见 pi-vs-tau-架构对比学习指南.md 第 9 章。起步工程已搭好:agent-study/mini/——M0/M1 完成、开箱全绿(mypy strict + 依赖方向守卫测试),M2/M3 是带规格测试的练习(5 条循环契约已验证可通关),参考答案在 solutions/。

深度对比:pi/tau vs LangGraph 等框架

主文档第 11 章 · 范式 / 代码对照 / 决策清单

核心区别一句话:pi/tau 是"你拥有循环的库",LangGraph 是"框架拥有执行、你填空"的图运行时——控制反转方向相反。章节含:三种控制流范式(模型驱动循环 / 显式图 / 代理交接)、同一个 agent 的四种写法代码对照、逐维度硬对比表与概念对照表(steering ↔ interrupt、JSONL 树 ↔ checkpointer)、两边挨的批评各该听哪一半、图与循环各自的真实胜场、"外层编排 + 内层薄 harness"混合策略与 7 问决策清单。

模型接入:什么 API 都能接吗?本地模型呢?

主文档第 10 章「模型接入指南」· 格式要求 / 统一层 / 本地模型

两条硬性要求:必须支持工具调用(不可妥协)、最好支持流式。市面上没有统一格式,只有事实标准——OpenAI Chat Completions(一个适配器吃遍 90% 模型,含"同一件事的四种写法"对照表)。最佳实践是内部中立层 + 适配器 + 逃生舱,警惕最小公分母陷阱。Ollama / vLLM / LM Studio 可直接接入:mini 三行配置、tau 用 ~/.tau/catalog.toml、pi 用 ~/.pi/agent/models.json——文档给出核对自官方的可用示例与四个本地模型专属坑。

12 个动手实验

由浅入深 · 勾选保存进度
0 / 12