跳转至

实践一:不用模型,复原一条源码调用链

返回课程总目录 · 下一项:运行最小 Agent Loop

这项实践只练习怎样读源码,你可以先从六条课程中选定一个足够具体的源码站点,不必运行产品,也不会让环境准备和模型凭据干扰这轮核对。你要顺着真实的调用关系,逐项检查这段代码为什么存在、谁调用它、输入从哪里来、它改了什么状态、结果返回到哪里,还要找出至少一个失败分支。把这些站点连起来以后,你才能看清单个函数在整条任务链里起什么作用。整个过程都以锁定提交为准,所以其他读者也能回到同一份源码复核你的结论。

先选择一个足够小的问题

你必须把问题收得足够窄,因为一旦从「这个项目架构是什么」之类的宽泛问题出发,调用关系很快就会淹没在目录和类型名称里。最好选一个能沿调用链回答的小问题,让每次搜索都进一步缩小阅读范围,而且问题还得落到可观察的状态或输出上。否则你很容易只解释了几个名字,却无法判断这套机制是否真按文章所说运行。例如:

  • Codex 的并发工具完成后,历史怎样保持调用顺序;
  • Gemini CLI 的 Scheduler 在哪里等待 Confirmation;
  • Claude Python Agent SDK 怎样把 can_use_tool 回调接入控制请求;
  • pi 的 Follow-up 为什么在外层循环消费;
  • OpenCode 的 Permission 为什么由最后一条匹配规则决定;
  • DeepSeek Harness 的 Tool Result 怎样重新进入 Agent Loop。

问题越具体,你就越容易找到真正的调用者和对应测试,也越容易看出文章漏掉了哪个关键分支。

七步阅读法

  1. 打开课程给出的 40 位提交永久链接,确认文件与符号存在。
  2. 先读函数签名和相邻类型,写下它解决的问题。
  3. 向上搜索调用者,直到 Session、Turn、Agent 或产品入口。
  4. 向下追返回值,直到状态持久化、事件发布或下一次模型请求。
  5. 找到一个正常分支、一个错误分支和一个取消或清理分支。
  6. 找到上游测试,确认它真的制造了文章描述的边界。
  7. 写出测试没有覆盖什么,避免把局部断言扩大成产品结论。

交付模板

project: codex
commit: c9b19deb09c1841ce7acc33ddb96276030936a29
question: 多个工具并发完成后怎样保持结果顺序
why: 模型声明顺序和实际完成顺序可能不同,历史必须可重放
entry: codex-rs/core/src/session/turn.rs
caller: 本次 Turn 的工具批次处理
input: 按模型输出顺序建立的 Tool Futures
state_change: 结果按调用身份写入 Conversation Items
return: 下一次模型请求使用的 Function Outputs
next: Session 继续构造下一轮输入
error_path: 单个 Tool Error 仍与原 Call ID 关联
cancellation_path: Turn Cancellation Token 传播到在途调用
test: codex-rs/core/tests/suite/tool_parallelism.rs
tradeoff: 保持确定性提交会等待较慢的前序调用
limits: 测试不证明所有真实工具都适合并行

这份模板只是帮你整理阅读结果,不要求公开文章照搬这些固定标题,因为真正要保持稳定的是各项证据能否彼此对应。如果当前来源里找不到某一项,就明确写出「当前来源不可核对」,别拿其他项目的常见做法补上空白。缺口可以先留着。这样既不会把推测冒充源码事实,后来找到新来源时也知道该补在哪里。只有当调用者、状态变化和验证证据都能互相对上,你才有理由从局部观察归纳出机制怎样运作。

自己核对答案的标准

  • 入口、调用者和消费者来自 Runtime 源码,不只来自 README;
  • 解释了这段代码为什么存在,而不只是复述变量名;
  • 区分了内存状态、持久记录与外部副作用;
  • 错误分支说明副作用是否可能已经发生;
  • 测试的输入确实触发目标边界;
  • 对设计取舍至少写出一个好处和一个代价;
  • 所有上游链接固定到同一提交。

进阶:画一张局部图

图里只留 5 至 8 个节点,把当前问题真正涉及的对象放进去,再用中文说明每个节点做什么,并把真实类型或函数名写在括号里。节点少一些,次要对象才不会冲淡箭头的含义,读者也能按正文的顺序检查调用链。画完再讲一遍。你可以从入口出发,沿着箭头复述任务。如果中途必须跳过某个节点,说明图里的关系多半还没理顺。每条箭头都应该对应源码里的调用、事件或数据转换。某段关系如果只能靠推断,就改用虚线,并在图注里交代依据和边界。

下一项:运行一个不需要模型的最小 Agent Loop