打开十万行 Agent 源码,到底从哪儿下手?
先建地图,再读代码

你听过太多 Agent 框架的名字,却始终说不清它们到底差在哪。这篇文章想给你一把“解牛刀”:不是逐行硬啃,而是先在脑子里画好一张“Agent 系统该长什么样”的地图,再带着它去源码里对位验证。文中拆解的 8 个框架全部真实存在,关键结论均可在官方文档、源码与论文中查到。
前言 读源码最大的误区,是“从第一行顺着读”。高效的做法恰恰相反:先有预期,再做验证。没有预期,读源码是信马由缰;有了预期,才能按图索骥。 |
一那个让人发懵的瞬间
你把一个很火的 Agent 框架 clone 下来,打开一看——几百个文件、几十个目录,README 写得漂亮,可盯着屏幕看了半小时,还是说不清这套系统是怎么转起来的。
问题不在于你不够聪明,而在于你少了一样东西:一张预期中的地图。这篇文章就讲怎么画这张地图,以及怎么用它。方法本身不复杂,难的是克制——克制住“看到一个文件就想读懂”的冲动。
二为什么“硬读”几乎一定会失败
在给方法之前,先看三个最常见的坑。认出它们,你就赢了一半。
【常见的三个坑】 •被 README 带偏。它告诉你项目“能做什么”,几乎从不告诉你“为什么这么做”。你看到的是一张功能清单,不是系统骨架。 •grep 漫游。一上来就搜 agent、tool、memory,跳出几百个文件,每个看两眼都像重点。一圈下来脑子里只剩碎片,其实只是在“源码景点”打卡。 •从 main() 一路钻到底。大型项目里真正决定 Agent 行为的代码往往只是一小部分,剩下大量篇幅是配置、日志、类型定义、序列化、适配器、UI 胶水、兼容分支。顺着调用栈往下钻,很容易钻进一条又长又不关键的支路。 |
三个坑的共同病根只有一个:没有预期框架。
三先搭一张地图:任何 Agent 框架都绕不开的五个地基
不管框架叫什么名字,只要它是个能干活的 Agent,就一定有这五块地基:
【五个地基】 •主循环——系统的心脏。把“接收输入 → 拼装上下文 → 调用模型 → 解析返回 → 派发工具 → 收集结果 → 更新状态 → 决定下一步”串成一个不断重复的圈。 •上下文管理——决定“模型这一轮能看到什么”。没有它,token 窗口很快失控。 •工具注册与调度——决定“模型能做什么”。哪些工具可用、怎么用、什么时候用,都在这里登记和约束。 •状态 / 事件账本——决定“出了事能不能复盘”。长任务能否恢复、错误能否回放和审计,全看这本账。 •治理边界——决定“模型被允许做到哪一步”。权限、沙箱、二次确认、日志……哪怕很弱,也一定以某种形式存在。 |
【可查的佐证】 “Harness 是把模型变成 Agent 的关键”不是空话。Anthropic 官方文档对 Claude Code 的定义就是一句:它是“围绕 Claude 的 agentic harness”,提供让语言模型变成能干活的编码 Agent 所需的工具、上下文管理与执行环境(来源:code.claude.com)。 |
记住这五个,你的阅读目标就从“这个项目有多少功能”,变成了一个更锋利的问题:它把模型放进了一个怎样的运行时?
四把地图用起来的五步法
第一步 Detect:先找主循环
所有 Agent 框架都有一颗心脏,藏在一段不断重复的循环里。它未必是 README 里最显眼的概念。找它,只要回答三个问题:用户输入从哪儿进来?模型调用在哪儿发生?工具执行的结果怎么回到下一轮?
【动手:先搜这几类词】 •循环相关:while、loop、step、run、turn、session •模型调用:messages、model、completion、response •工具相关:tool_call、function_call、ToolCall、Action、Observation 真正的主循环,通常会同时碰到三件事:消息、模型调用、工具派发。只处理 UI 或配置的文件先排除。产物不必精细——画一张不超过 10 个框的草图就够了。 |
第二步 Classify:给组件“对号入座”
找到主循环后,先别急着往下钻——一钻到底,就容易掉进某个序列化函数里出不来。正确做法是停一下,用一套更细的镜头给组件归类。这套镜头有七个格子,可以理解为“Agent 在帮自己管哪一类资源”:
•决定看见什么 → 感知(Perception)
•决定记住什么 → 记忆(Memory)
•决定怎么想 → 推理(Reasoning)
•决定能做什么 → 行动(Action)
•决定怎么纠错 → 反思(Reflection)
•决定谁来做 → 协作(Collaboration)
•决定被允许做到哪 → 治理(Governance)
【最容易绕晕的一点】 前面的“五个地基”和这里的“七个格子”是什么关系?其实是同一套东西的两个视角:五个地基从“系统有没有这些部件”出发,是粗筛;七个格子从“Agent 在做什么”出发,是细分。一个偏工程师视角,一个偏拟人视角,配合着用就好,不必纠结哪个更“正确”。 归类的关键提醒:别只看组件的名字,要看它在系统里真正做什么。比如一个叫 “repo map”(仓库地图)的东西,名字像索引,实际却决定了“哪些代码结构能进入模型的上下文”——所以它首先是“感知”。一个组件可以横跨几脉,第一遍只找准“主脉”即可。 |
第三步 Filter:敢于丢掉大部分代码
读大型工程最反直觉的能力,是敢于不读。判断标准只有一句话:这个文件会不会改变 Agent 的决策、上下文、状态、行动或权限?不会,就先标成“样板代码”,放一边。CLI 参数解析、UI 布局、错误文案、监控上报、类型定义、SDK 包装、测试桩、平台兼容分支……都有价值,但第一轮不看。
做好这一步,你的阅读对象会从“源码本身”转向“控制面”——你开始只关心:这个系统到底在哪里控制上下文、控制行动、控制状态、控制权限。速度会突然快很多。
第四步 Map:把组件放进“可比较”的矩阵
第四步,是把组件落进一张矩阵——纵轴是上面的“七脉认知功能”,横轴是执行拓扑,也就是“数据和控制怎么流动”:一条链顺着走(Chain)、按条件分发(Route)、上级派给下级(Hierarchy)、几路并行(Parallel)、反复重试(Loop)、只追加不覆盖(append-only)……同一个功能,可以用不同的“流”来实现,每种流各有优劣。
Map 最容易退化成“贴标签”。真正的 Map,是逼自己把一句话说完整:这个功能解决的是哪个认知问题?用的是哪种拓扑?它会带来什么失败模式?
【真实案例:一套“事件日志”落进矩阵】 OpenHands(前身 OpenDevin,论文发表于 ICLR 2025)用一条事件流作为系统主干。把它落进矩阵,一个事实就变成了三个工程判断: •解决记忆问题——系统状态来自一串事件,而非散落在各对象的内存里;据其论文,重放这条日志即可还原整段会话。 •解决治理问题——事件可审计、可回放,等于给软件 Agent 装了“黑匣子”。 •采用 append-only 拓扑——好处是错误不会被悄悄覆盖;代价是日志会膨胀、回放有成本。其沙箱还能从本地进程一键换成 Docker 隔离。 |
第五步 Verify:每个判断都要能回到证据
没有 Verify,逆向工程就很容易变成“讲故事”。你说这个框架重治理、那个重记忆,听着都有理,但只要回不到代码,就只是解释,不是论证。证据分三层,强度递减:
•源码(最强):权限模块、沙箱管理、事件存储、工具派发器的实现,直接证明系统怎么工作。
•测试(很强):很多时候测试比实现更清楚地暴露设计边界——“最多能派几个子 Agent”“沙箱怎么限制动作”往往在测试里写得最明确。
•官方文档(辅助):用来确认产品语义和公开承诺。
产品解读可以停在概念层,工程论证必须回到代码层。这就是两者的区别。
五把方法用在真东西上:8 个框架的“工程性格”
用这把刀横切 8 个真实框架,每个只问两件事:它一句话的“工程性格”是什么?哪个关键事实可以查证?下表的每一条结论都能在官方文档、源码或论文里找到(来源见文末)。
框架 | 一句话工程性格 | 可验证的关键事实(来源) |
Claude Code | Harness 是模型的“整车” | Anthropic 官方文档直接把它定义为“围绕 Claude 的 agentic harness”;刻意保持极薄,每出一代新模型就删掉一批脚手架(code.claude.com) |
Codex CLI | 一套协议,跨端复用同一个 Agent | App Server 用 JSON-RPC 协议,让终端、VS Code、JetBrains、桌面、云端共用同一个 harness(OpenAI 工程博客) |
Aider | Git 就是最小可靠账本 | 每次改动自动 git commit、可用 /undo 回退;据官方 FAQ,它约 70% 的新代码由自己写成(aider.chat) |
OpenCode | 把 LSP 接进“感知” | 集成语言服务器,让 Agent 拿到诊断、符号、定义跳转——从“字符串在哪”升级到“符号指向哪”(opencode.ai) |
OpenClaw | 个人助手的核心是统一控制面 | 单个 Gateway 作为控制面,统一 WhatsApp / Telegram / Slack / iMessage 等多渠道,并为每个 agent 隔离会话(github.com/openclaw) |
Hermes | 会成长,靠“程序性记忆” | 把“怎么做事”沉淀成 SKILL.md:完成复杂任务后自动写技能、还能自我修订(MIT 开源;记忆学界称之为 procedural memory) |
DeerFlow | 多 Agent 的难点是边界 | 字节开源,基于 LangGraph 的 supervisor + 子 Agent;在“出计划”和“动工具”两处都设了人工审批关卡(github.com/bytedance) |
OpenHands | 事件流是软件 Agent 的黑匣子 | append-only 事件日志是唯一真相、重放即可还原整段会话;沙箱可从本地一键换成 Docker(ICLR 2025 论文) |
把这 8 行连起来看,会浮现三种“工程性格”:开发者工具型(Claude Code / Codex / Aider / OpenCode,重感知、行动、治理);个人助手型(OpenClaw,重记忆、行动,外加一个统一控制面);重执行 / 多 Agent 型(DeerFlow / OpenHands,重协作、可观测、治理,Hermes 则在“记忆”一脉上走得最远)。没有万能架构,所有设计都是面向具体场景的取舍。
六一个微型演练:用 Aider 走一遍五步
把五步连起来,落到一个真实框架。Aider 是个终端里的 AI 结对编程工具,它的设计恰好把五步法照得清清楚楚:
【五步拆解 Aider】 •Detect:搜 run / messages / tool,定位反复调用模型、派发工具的循环,画出 5 个框的草图。 •Classify:它有“仓库地图(repo map)”——归感知;有“diff / commit”流程——归行动 + 治理;有重试逻辑——归反思。 •Filter:几十个 prompt 模板、CLI 参数、UI 文件,全部标记为“样板”,先不看。 •Map:把“diff / commit”落进矩阵——它解决“行动留痕”问题,用的是链式拓扑(改 → diff → 提交 → 可回退),失败模式是“没及时提交,中间状态会丢”。 •Verify:打开实现确认它确实走 Git——官方文档写明:每次改动自动 git commit、可用 /undo 回退;据其 FAQ,Aider 约 70% 的新代码由它自己写成(git blame 可统计)。 |
你会发现,这套流程几乎对所有代码 Agent 都成立——区别只在于那个“关键不变量”:有的把 Git 当行动账本(Aider),有的把语言服务器 LSP 接进感知(OpenCode,于是它知道符号真正指向哪,而不只是字符串在哪),有的把事件流当黑匣子(OpenHands)。抓住这个不变量,你就抓住了一个框架的灵魂。
七一份可以直接抄走的清单
下次打开一个 Agent 框架,按这张表走一遍,顺便也是一份很好的选型清单:
【阅读 / 选型双用清单】 •□主循环在哪?能不能用一张 ≤10 个框的图画出来? •□上下文是显式机制装配的,还是靠 prompt 硬撑? •□工具调用有没有 schema、权限和失败处理? •□状态是否可恢复、可回放、可审计?账本在哪? •□高风险动作的边界在哪?谁来确认? |
如果一个框架对这五个问题都答不上来,那它大概率还不具备进生产系统的条件。
八在 AI 时代,“做难事”才长本事
这套五步法,做起来确实比“丢给 AI 让它分析一下”要繁琐得多。但也正因为繁琐,它才有价值——它逼着你的思维和真实系统产生摩擦。
【一个值得记住的数据】 2025 年 7 月,研究机构 METR 的一项对照实验发现:让有经验的开源开发者用上 AI 编程工具后,他们完成任务实际上慢了约 19%,却普遍以为自己快了约 20%。“感觉变快”和“真的变强”是两回事——亲手把难事做一遍,才不会被错觉骗过去。 |
读懂几十万行源码的捷径,从来不是逐行硬啃,而是先建立一套“看系统”的方法。框架会过期,版本会变,目录结构也会变;但只要 Agent 还需要感知、记忆、推理、行动、反思、协作和治理,这套地图就一直好用。
夜雨聆风