从零理解 Agent 架构:以 Swarm 项目为例
面向读者:刚开始学习 LLM Agent 的开发者。本文不假设你熟悉 LangChain、LangGraph 或复杂多智能体框架,而是用本项目
swarm的实际实现来解释:一个能读文件、写代码、跑命令、并留下可审计证据的 Agent 应该如何设计。项目快照:基于 2026-07-05 当前工作区代码与文档整理。
0. 一句话概括本项目
swarm 是一个高并发、工具驱动、证据优先的研究/编码 Agent 原型。它的核心不是“让模型自由发挥”,而是把职责分清:
- 模型负责判断下一步该读什么、查什么、写什么、运行什么、什么时候收束;
- 程序 harness负责执行工具、记录证据、限制风险、压缩上下文、恢复状态、验证最终声明;
- 工作区保存问题、产物、日志、报告、可复现实验和补丁。
这就是本项目最重要的设计哲学:
让 LLM 做判断,让确定性程序做约束。
如果你是 Agent 初学者,可以把这个项目看成“怎样把 ChatGPT 变成可靠工作流”的一份工程范例。
1. 初学者先理解:什么是 Agent?
普通 LLM 调用大致是:
用户问题 -> 模型回答Agent 则多了一个循环:
用户目标
-> 模型决定下一步动作
-> 程序执行动作(搜索、读文件、写文件、跑命令)
-> 观察真实结果
-> 模型基于结果再决定下一步
-> ...
-> 最终答案/产物所以,一个实用 Agent 至少包含五件东西:
| 层次 | 作用 | 本项目中的对应实现 |
|---|---|---|
| 模型接口 | 调用一个或多个 LLM | swarm.llm.ChatClient |
| 控制循环 | 决定下一步、处理模型输出 | swarm.research.ResearchSwarm、swarm.director.ResearchDirector |
| 工具系统 | 把模型动作变成真实操作 | swarm.tools.ToolRegistry |
| 记忆/状态 | 保存过程、证据、断点 | swarm.memory.Memory、director_state.json、heartbeat.json |
| 验证与评估 | 防止幻觉和未验证结论 | swarm.verify、SWARM_VERIFICATION_JSON、swarm.build_policy、swarm.benchmarks |
很多 Agent 项目失败,是因为只关注“模型会不会推理”,忽略了后四层。本项目的精华正是把后四层做成了可观察、可恢复、可验证的工程内核。
2. 项目整体架构鸟瞰
当前代码主要分为四条工作流:
swarm run:固定流程的并发研究 Swarm。swarm loop:多轮可恢复自治循环。swarm director:强模型主导的“研究导演”模式。swarm solve/build/research/agent:面向普通任务的独立工作区模式。
其中最值得学习的是两种架构:
- 固定流水线式 Swarm:规划多个角度,并发 worker 搜索/验证,再由 critic 和 synthesizer 汇总。
- Director 自主循环:每一步由强模型选择
tool、fanout、checkpoint或final,但所有动作必须通过 harness。
2.1 固定流水线式 Swarm
flowchart TD Q[用户问题] --> P[Planner 规划多个角度] P --> W1[Worker 1] P --> W2[Worker 2] P --> WN[Worker N] W1 --> E[证据与 WorkerReport] W2 --> E WN --> E E --> C[Critics 批评与风险检查] E --> S[Synthesizer 中文报告] C --> S S --> V[RunVerifier 证据验证] V --> R[report.md / verification.json / summary.json]
对应代码入口:
swarm.research.ResearchSwarm.run():主流程;plan_angles():规划并发角度;run_worker():worker 工具循环;run_critics():并发批评;synthesize():汇总为报告;RunVerifier.verify():最终证据约束。
这种方式的优点是简单、可预测、容易调试;缺点是像流水线,策略不够灵活。
2.2 Director 自主循环
flowchart TD Start[目标 + 目标工作区] --> Overview[确定性 workspace_overview] Overview --> Preflight[命名文件/强制命令预检] Preflight --> State[写 director_state.json + heartbeat] State --> LLM[Director 模型选择下一步] LLM --> Parse[解析/归一化 JSON move] Parse -->|tool| Tool[ToolRegistry 执行] Parse -->|fanout| Fanout[启动 bounded ResearchSwarm] Parse -->|checkpoint| Checkpoint[写 checkpoint.md] Parse -->|final| Verify[验证 final claims] Tool --> Evidence[director_evidence d-e0/d-e1/...] Fanout --> FanoutReport[fanout report excerpt] Evidence --> Guards[反循环/强制验证/构建策略 guard] FanoutReport --> Guards Checkpoint --> Guards Guards --> State Verify -->|通过| Report[report.md + director_summary.json] Verify -->|失败| State
对应代码入口:
swarm.director.ResearchDirector.run():主循环;parse_director_move():解析模型 JSON;_initial_transcript():系统提示和动作协议;_run_fanout():把子问题交给并发 worker;verify_director_final():检查最终声明是否有证据;_write_state()/_write_heartbeat():可恢复状态;_finish():写报告、summary、verification。
Director 模式是本项目的“架构精华”:强模型像人类研究负责人一样选择下一步,但不能跳过工具、证据和验证。
3. 本项目的核心设计精华
精华 1:不用依赖原生 tool calling,而是使用文本 JSON 协议
本项目没有把可靠性寄托在某个供应商的原生工具调用格式上,而是让模型输出普通 JSON:
{"action":"tool","tool":"workspace_read","args":{"path":"README.md","start_line":1,"max_lines":80}}或者:
{
"action": "final",
"content": "最终结论...",
"claims": [
{
"id": "c1",
"kind": "fact",
"text": "某检查已通过",
"evidence_ids": ["d-e3"],
"obligation_ids": ["coverage"]
}
]
}好处:
- 可以兼容任意 OpenAI-compatible Chat Completions endpoint;
- 不受
/responses、原生 tool call、JSON mode 支持差异影响; - 解析失败可以用确定性代码修复或追问;
- 所有模型都遵守同一套 harness 规则。
对应实现:
swarm.ir.JSON_COMMAND_PROTOCOL定义 worker 协议;swarm.ir.parse_command()解析 worker 输出;swarm.director.parse_director_move()解析 director 输出,并兼容很多模型常见变体,例如把action写成工具名、把shell写成run_command等。
初学者可学到的原则:
先设计你自己的稳定中间协议,再让模型适配协议;不要让项目被某个模型厂商的输出格式绑死。
精华 2:Provider 和角色解耦
swarm.config 把“模型供应商”和“Agent 角色”分开:
[providers.codex]
base_url = "..."
model = "..."
max_concurrency = 1
safe_context_chars = 90000
[providers.gemini]
base_url = "..."
model = "..."
max_concurrency = 8
safe_context_chars = 35000
[roles]
director = "codex"
search_worker = "gemini"
critic = "codex"
synthesizer = "codex"这表达了一个重要架构思想:
- 角色是工作职责:planner、worker、critic、synthesizer、director;
- provider是资源实现:某个 endpoint、模型、key、并发、上下文大小;
- 同一角色可以换模型,同一模型也可以承担多个角色。
对应代码:
ProviderConfig:base_url、model、api_key_env、max_concurrency、safe_context_chars;RuntimeConfig:请求超时、重试、stream 设置;SwarmConfig.provider_for_role(role):把角色映射到 provider。
初学者可学到的原则:
Agent 架构里不要写死“哪个模型做什么”。应该写“哪个角色需要什么能力”,再由配置决定模型实现。
精华 3:工具不是函数列表,而是安全边界
ToolRegistry 提供的工具大致分为四类:
| 工具类别 | 例子 | 是否能作为事实证据 |
|---|---|---|
| 外部/资料检索 | web_search、web_content | 可以 |
| 工作区观察 | workspace_list、workspace_read、workspace_search、workspace_file_info、workspace_git_diff | 可以 |
| 执行验证 | run_command | 可以,而且最强 |
| 状态变更 | workspace_write、workspace_edit、write_note | 通常不能直接证明事实 |
这个区分非常关键。写了一个文件,并不能证明这个文件是对的;只有读到的内容、搜索结果、命令输出、哈希信息、测试结果等,才可以作为事实声明的证据。
工具层还做了安全约束:
- 所有 workspace path 必须相对目标工作区,阻止绝对路径和
..逃逸; - 写入
.git等 VCS 元数据会被拒绝; run_command有危险命令 denylist,例如rm、sudo、dd、mkfs、curl | sh;workspace_edit使用精确 old/new 片段,Python 文件编辑后还会做语法检查;run_command记录执行目录、命令、返回码、耗时、引用文件哈希、工作区副作用。
初学者可学到的原则:
工具系统不仅是“给模型能力”,更是“定义模型不能越过的边界”。
精华 4:证据 ID 是抗幻觉核心
每个工具结果都会被包装成 evidence item,例如 worker 的 w0-e0,director 的 d-e0。
EvidenceItem 记录:
id:唯一证据编号;tool:来自哪个工具;ok:是否成功;source_type:web、workspace、execution、local_note、workspace_write 等;excerpt:短摘录;metadata:结构化元数据,比如 SHA-256、structured verification、命令返回码。
最终声明必须引用证据 ID。比如:
{
"kind": "fact",
"text": "有限覆盖检查通过",
"evidence_ids": ["d-e4"],
"obligation_ids": ["coverage", "uniqueness"]
}验证器会检查:
- factual claim 是否有
evidence_ids; - 引用的 evidence id 是否存在;
- 是否错误引用了
workspace_write或write_note这类 non-grounding evidence; - 如果声明“验证了覆盖/唯一性/证书/不变量”,是否引用了带
SWARM_VERIFICATION_JSON的run_command; obligation_ids是否真的在对应命令中通过。
对应代码:
swarm.schema.EvidenceItem;swarm.schema.Claim;swarm.verify.RunVerifier;swarm.director.verify_director_final()。
初学者可学到的原则:
不要问模型“你确定吗”;要让模型说“我依据哪条证据确定”。
精华 5:计算结果必须机器可读
本项目对 run_command 做了一个很实用的增强:脚本可以输出一行 SWARM_VERIFICATION_JSON。
例如:
import json
payload = {
"verdict": "pass",
"summary": "all finite cases checked",
"obligations": [
{"id": "coverage", "status": "pass", "description": "all cases covered"},
{"id": "uniqueness", "status": "pass", "description": "no duplicated owner"},
],
}
print("SWARM_VERIFICATION_JSON: " + json.dumps(payload, sort_keys=True))run_command 会解析这行 JSON,并把它放进 evidence metadata。如果任何 obligation 失败,就算进程退出码是 0,这个 tool result 也会被标记为失败。
这区分了两件事:
- “脚本运行了”;
- “脚本检查的命题通过了”。
对于研究型 Agent,这一点非常重要。因为很多错误不是命令崩溃,而是脚本逻辑发现反例、覆盖不全、证书不合法。
对应实现:
swarm.tools._extract_structured_verification();swarm.tools._normalize_structured_verification();swarm.verify.structured_verification_passes();- director 的 final guard 会要求相关 obligation 通过后才能最终回答。
初学者可学到的原则:
如果 Agent 要做计算验证,就给它一个机器可读的验收协议,而不是只让它读自然语言 stdout。
精华 6:上下文不是记忆,记忆也不是全文塞回 prompt
LLM 上下文窗口有限,而且长上下文并不总可靠。本项目采用:
- 工具完整结果写入 JSONL memory;
- 当前 prompt 只携带必要摘要、证据 ID 和最近交互;
- 超预算时用确定性 compaction,而不是再找一个模型总结。
compact_worker_transcript() 和 compact_director_transcript() 的策略是:
- 保留 system contract;
- 保留初始目标的截断版;
- 插入 evidence summary;
- 保留最近若干条消息;
- 删除旧的完整 tool output;
- 记录
context_compacted事件。
这背后的原则是:
旧 stdout 可以忘,证据 ID 不能忘;旧全文可以重读,来源和哈希不能丢。
对应实现:
swarm.memory.Memory:append-only JSONL;swarm.context.compact_worker_transcript();swarm.context.compact_director_transcript();swarm.audit.audit_workspace():事后统计 compaction、tool call、evidence 分布。
初学者可学到的原则:
可靠 Agent 的记忆应该是外部持久状态,prompt 只是当前工作集。
精华 7:可恢复是长任务 Agent 的基本能力
Director run 会持续写:
director_state.json:权威可恢复状态;heartbeat.json:轻量实时监控;checkpoint.md:人类可读 checkpoint;report.md、director_summary.json、verification.json:最终产物。
写状态时使用同目录临时文件加 os.replace,避免进程中断留下半截 JSON。
这让长任务具备三个能力:
- 运行中可以观察进度;
- 中断后可以从 evidence、steps、fanouts、checkpoints 继续;
- 完成后可以审计每一步。
对应实现:
ResearchDirector._write_state();ResearchDirector._write_heartbeat();_atomic_write_text();ResearchDirector._resume_context()。
初学者可学到的原则:
只要任务可能超过几分钟,就不要把状态只放在内存和 prompt 里。
精华 8:反循环 guard 比“更强模型”更重要
Agent 常见失败模式包括:
- 反复读同一个文件;
- 反复跑同一个失败命令;
- 写一点、失败、再写一点、仍然同样失败;
- 快到步数上限时还在搜索;
- 明明工具能访问工作区,却声称无法访问。
本项目通过 harness 做了很多 guard:
- read-only tool cache:重复工具调用不重跑,返回旧 evidence id;
- identical failing
run_command不重复运行,除非发生 workspace write/edit; - successful structured run 也不重复运行,提示模型 final 或换一个检查;
- stagnation detector:连续非进展 move 会停止并 checkpoint;
- repair-thrash guard:连续同签名失败后的重复写入会被拒绝;
- late computation guard:快到预算末尾且目标要求计算时,强制模型跑命令或明确说明无需计算;
- inaccessible-workspace guard:如果已有成功 workspace evidence,就拒绝“无法访问工作区”的 final/checkpoint。
初学者可学到的原则:
Agent 的可靠性往往来自“不允许它浪费下一步”,而不是来自“提示它认真一点”。
精华 9:目标工作区隔离与补丁回放
当 Agent 会修改真实项目时,风险很高。本项目提供三种 target isolation:
| 模式 | 行为 | 适合场景 |
|---|---|---|
direct | 直接操作原工作区 | 短小、可控、你愿意立即修改 |
copy | 复制目标到 run workspace | 保留未提交变更,不要求 git,但可能占空间 |
git-worktree | 创建 detached worktree | 长任务、较安全、便于 patch review |
完成后可以:
target-diff导出 patch;- 人类 review;
target-apply --check检查;target-apply --yes应用。
对应实现:
swarm.target.prepare_target_workspace();swarm.target.export_target_patch();swarm.target.check_or_apply_target_patch()。
初学者可学到的原则:
让 Agent 能写文件之前,先设计“如何撤销、审查、合并它写的东西”。
精华 10:构建类任务需要“完成策略”,不是只要 final 报告
在 build 模式中,Agent 不能只写 ANSWER.md 或 FINAL_REPORT.md 就算完成。build_policy 会检查:
- 是否有非报告、非生成缓存的 deliverable;
- 最新 deliverable edit 后是否有成功
run_command; - 如果用户要求测试,是否有新鲜的成功测试命令;
- 如果用户要求启动服务,是否有 HTTP 验证;
- 如果要求记录 PID/port,是否存在符合格式的
SERVER.md。
对应实现:
swarm.build_policy.evaluate_build_completion_policy();cmd_solve()在写solve_summary.json时加入artifact_status.build_policy。
初学者可学到的原则:
对编码 Agent 来说,“产物存在 + 运行过检查”比“模型说完成了”重要得多。
4. 代码模块导读:初学者应该按什么顺序读?
建议按以下路线阅读,而不是一上来读最长的 director.py。
第 1 步:读配置层 swarm/config.py
你会学到:
- 如何用 dataclass 表示 provider;
- 如何从 TOML 加载配置;
- 如何用
roles把 Agent 职责映射到模型; - 如何隐藏 API key,只在
redacted_dict()里显示是否存在。
这一层是 Agent 的“资源声明”。
第 2 步:读模型客户端 swarm/llm.py
重点看:
ChatClient.complete();- 有界并发
BoundedSemaphore; - 失败重试;
- streaming / non-stream fallback;
- 空响应和 ResponseBodyError 的处理;
ChatResult如何记录 status、duration、usage、first token 等。
这一层是 Agent 的“模型 IO”。
第 3 步:读协议解析 swarm/ir.py
重点看:
JSON_COMMAND_PROTOCOL;json_candidates()如何从模型混乱输出中找 JSON;parse_command()如何归一化 action alias;- 为什么允许
tool_call、call_tool、answer等别名。
这一层是 Agent 的“语言到动作”的边界。
第 4 步:读工具层 swarm/tools.py
先看 ToolRegistry.call(),理解所有工具的统一入口;再重点看:
- path containment;
workspace_read/search/retrieve;workspace_write/edit;run_command;- structured verification parser;
- referenced file hashes;
- side-effect detection。
这一层是 Agent 的“手和眼睛”。
第 5 步:读证据 schema swarm/schema.py
重点理解:
EvidenceItem.can_ground_claim;Claim.is_factual;WorkerReport;- 为什么
write_note、workspace_write不是 grounding evidence。
这一层是 Agent 的“事实账本”。
第 6 步:读验证器 swarm/verify.py
重点理解:
- factual claim 必须有 evidence;
- obligation claim 必须引用 run_command;
- structured obligations 必须 pass;
- 验证器不是数学证明器,而是 provenance checker。
这一层是 Agent 的“审稿人”。
第 7 步:读固定 Swarm swarm/research.py
重点看:
ResearchSwarm.run()的 planner → workers → critics → synthesizer;run_worker()中模型如何一步步调用工具;- worker final 为什么会被拒绝;
- named file preflight;
- context compaction。
这一层是 Agent 的“并发流水线”。
第 8 步:读 Director swarm/director.py
这是最复杂但也最有价值的部分。建议分块读:
DirectorOptions:先看有哪些控制参数;_initial_transcript():理解 director 可以做哪些 move;run()前半段:resume、preflight、initial fanout;run()主循环:parse、guard、tool/fanout/checkpoint/final;- final guard:为什么最终声明会被拒绝;
_write_state()/_finish():如何持久化。
这一层是 Agent 的“自主驾驶系统”。
第 9 步:读 target / benchmark / audit
swarm.target:隔离与补丁;swarm.benchmarks:如何评测 harness 行为;swarm.audit:如何事后观察 Agent 真实行为;swarm.build_policy:如何定义 coding task 完成标准。
这一层是 Agent 的“工程化闭环”。
5. 一次 swarm solve 从开始到结束发生了什么?
swarm solve 是最贴近普通用户的入口。它的生命周期大致如下:
sequenceDiagram participant U as User participant CLI as swarm.cli participant D as ResearchDirector participant T as ToolRegistry participant FS as Solve Workspace participant V as Verifier/Policy U->>CLI: swarm build/research/agent problem.md CLI->>FS: 创建 PROBLEM.md, README.md, experiments/, notes/ CLI->>D: DirectorOptions(objective, workspace, target_workspace) D->>FS: 写 director_state.json/heartbeat.json D->>D: 模型选择 move D->>T: 执行 workspace_read/run_command/... T->>FS: 读写文件或运行命令 T-->>D: ToolResult D->>FS: 记录 director_evidence D->>D: guard 检查是否继续/拒绝/final D->>V: verify_director_final V-->>D: pass/warn/fail D->>FS: report.md, summary.json, verification.json CLI->>FS: 复制 FINAL_REPORT.md/ANSWER.md, 写 solve_summary.json
输出工作区通常包含:
PROBLEM.md # 权威问题描述
ANSWER.md # 最终答案副本
FINAL_REPORT.md # 最终报告副本
experiments/ # Agent 可写验证脚本/实验
notes/ # Agent 可写笔记
.swarm/run/ # 内部日志、状态、证据、模型健康、checkpoint
director_state.json
heartbeat.json
report.md
director_summary.json
verification.json
memory/*.jsonl
model_health.jsonl这个结构体现了一个重要经验:
用户可读产物和内部审计产物应该分离,但必须能互相追溯。
6. 如何用本项目理解“多 Agent”?
很多人一听“多 Agent”就想到多个聊天机器人互相对话。但本项目更务实:多 Agent 是为了并行采样不同视角,不是为了模拟组织架构。
在 ResearchSwarm 中:
- planner 产出多个角度;
- worker 并发探索;
- critic 独立挑错;
- synthesizer 汇总。
在 ResearchDirector 中:
- director 是主决策者;
- fanout worker 是临时并发顾问;
- fanout 默认禁用写工具和
run_command,避免多个 worker 同时乱改; - fanout 输出不是最终权威,director 仍需自己用 evidence 验证关键结论。
这是一种成熟的多 Agent 设计观:
| 错误理解 | 更好的理解 |
|---|---|
| 多 Agent = 越多越聪明 | 多 Agent = 用并发换视角多样性 |
| 子 Agent 可以直接决定结论 | 子 Agent 只提供候选证据/假设 |
| 所有 Agent 权限一样 | 不同角色应该有不同工具权限 |
| 多 Agent 互聊就会收敛 | 必须有 deterministic verifier 和最终负责人 |
本项目选择让 Codex-like director 做最终负责人,让 Gemini-like workers 做高并发探索。这很符合工程直觉:
- 强模型用于策略、整合、最终判断;
- 快/便宜/并发模型用于搜索、枚举、头脑风暴;
- 程序验证用于裁决可机器检查的事实。
7. 本项目的“可靠性公式”
可以把本项目的可靠性总结为:
可靠 Agent
= 明确协议
+ 有边界工具
+ 持久证据
+ 机器可读验证
+ 上下文压缩
+ 可恢复状态
+ 反循环 guard
+ 评测基准下面逐项解释。
7.1 明确协议
模型每一步只能返回一个 JSON move。这样 harness 可以明确知道:
- 这是工具调用、fanout、checkpoint 还是 final;
- 参数是什么;
- final claims 是哪些;
- confidence 和 obligation ids 是否存在。
7.2 有边界工具
工具有路径限制、命令限制、写入限制和元数据记录。模型不能直接接触宿主机任意文件,也不能用自然语言声称自己“已经运行了测试”。
7.3 持久证据
所有 evidence 写入 JSONL memory。即使 prompt 被压缩,审计记录还在。
7.4 机器可读验证
SWARM_VERIFICATION_JSON 把“脚本检查了什么”显式化,使 final claim 可以引用 obligation id。
7.5 上下文压缩
旧 tool output 不无限堆进 prompt;只保留 evidence ids、摘录、structured verification 摘要和最近交互。
7.6 可恢复状态
director_state.json、heartbeat.json、checkpoint 让长任务能恢复和观察。
7.7 反循环 guard
重复失败命令、重复读取、修复抖动、预算末尾不计算等都由 harness 处理。
7.8 评测基准
swarm.benchmarks 不只评估答对没答对,还评估是否:
- 找到指定文件;
- 写了预期脚本;
- 跑了命令;
- 输出 structured obligations;
- 引用了正确 evidence;
- 没改不该改的文件;
- interrupted suite 能保留 partial results。
8. 适合初学者复用的 Agent 架构模板
如果你想从零写一个自己的 Agent,可以照这个最小模板开始。
8.1 数据结构
@dataclass
class ToolResult:
ok: bool
content: str
metadata: dict[str, Any]
@dataclass
class Evidence:
id: str
tool: str
ok: bool
source_type: str
excerpt: str
metadata: dict[str, Any]
@dataclass
class Claim:
id: str
kind: str # fact | inference | recommendation | uncertain
text: str
evidence_ids: list[str]8.2 模型协议
你必须只输出一个 JSON:
- {"action":"tool", "tool":"...", "args":{...}}
- {"action":"final", "content":"...", "claims":[...]}8.3 控制循环
for step in range(max_steps):
messages = compact_if_needed(transcript, evidence)
raw = llm(messages)
move = parse_json_move(raw)
if move.action == "tool":
result = tools.call(move.tool, move.args)
ev = record_evidence(result)
transcript.append(tool_result_message(ev, result))
continue
if move.action == "final":
verification = verify_claims(move.claims, evidence)
if verification.ok:
return write_report(move.content, verification)
transcript.append(repair_instruction(verification))
continue
return fallback_report(evidence)8.4 必备 guard
至少实现这些:
- parse error repair;
- no-evidence final rejection;
- factual claim evidence check;
- repeated identical tool call cache;
- repeated failing command guard;
- write 后必须 run/check;
- path containment;
- state checkpoint。
9. 本项目相对成熟框架的位置
README 和 docs 中多次强调:本项目不是要重造完整 Agent 框架,而是一个小而清晰的 control kernel。未来可以迁移到成熟组件:
| 层 | 当前实现 | 未来可替换/增强 |
|---|---|---|
| 模型调用 | 自写 OpenAI-compatible urllib client | provider router、LiteLLM 等 |
| Durable orchestration | 自写 director state loop | LangGraph |
| Typed worker | 自写 JSON protocol + dataclass | PydanticAI |
| Retrieval | 本地 lexical search + web CLI | LlamaIndex |
| Benchmark | 自写 staged benchmark | 更系统的数据集/评测平台 |
这个取舍对初学者非常有启发:
先用小内核把 Agent 的不变量跑通,再考虑框架化;不要一开始就把错误藏进复杂框架里。
10. 设计反模式:本项目刻意避免了什么?
反模式 1:把模型回答当事实
错误做法:模型说“测试通过了”,就信。
本项目做法:必须有 run_command evidence;强命题必须有 structured obligation。
反模式 2:把 prompt 当数据库
错误做法:把所有历史对话塞回 prompt。
本项目做法:JSONL memory 持久化,prompt 只保留摘要和证据 ID。
反模式 3:让所有子 Agent 都能写文件
错误做法:并发 worker 同时修改代码。
本项目做法:fanout 默认禁用 workspace_write、workspace_edit、run_command,只做 read/search brainstorm。
反模式 4:没有恢复机制
错误做法:任务跑 3 小时,进程断了,一切重来。
本项目做法:state、heartbeat、checkpoint 原子写。
反模式 5:只评估最终答案,不评估过程
错误做法:只看 pass/fail。
本项目做法:benchmark 同时统计工具调用、证据、obligation、target patch、模型健康和 failure class。
反模式 6:把 Agent 安全交给模型自觉
错误做法:提示“不要做危险操作”。
本项目做法:工具层阻止危险路径和命令,harness 拒绝不合格 final。
11. 对 Agent 初学者的实践建议
11.1 先做单 Agent,再做多 Agent
先实现一个会:
- 读文件;
- 跑命令;
- 记录证据;
- 引用证据回答;
- 失败后继续修复。
再加入 planner、workers、critics、director。
11.2 先做 evidence,再做 memory
很多人一上来做“长期记忆”,但更基础的是 evidence。没有 evidence id 的 memory,只是另一堆可能幻觉的文本。
11.3 先做 verifier,再做 benchmark
如果 final claim 都无法验证,就谈不上 benchmark。先定义什么叫“合格回答”:
- factual claim 必须有 evidence;
- 计算 claim 必须有 command;
- strong verification claim 必须有 obligation;
- coding task 必须有产物和 post-edit run。
11.4 把失败当成一等公民
Agent 不是每次都成功。你需要记录:
- 模型失败;
- parse 失败;
- tool 失败;
- command timeout;
- verifier fail;
- final rejected;
- stagnation stop。
这些记录不是噪音,而是改进 Agent 的主要数据。
11.5 工具结果要短给模型、长存磁盘
模型需要的是“下一步足够的信息”,人类审计需要的是完整记录。两者不要混为一谈。
12. 用一句话理解每个核心文件
| 文件 | 一句话 |
|---|---|
swarm/config.py | 把模型 endpoint 和 Agent 角色解耦。 |
swarm/llm.py | 一个依赖少、可观测、支持重试/stream 的 Chat Completions client。 |
swarm/ir.py | 把模型 JSON 文本解析成受控动作。 |
swarm/tools.py | Agent 的眼睛、手、shell 和安全边界。 |
swarm/schema.py | 把工具结果变成可引用证据,把结论变成可验证 claim。 |
swarm/verify.py | 确定性检查 final 是否有证据支撑。 |
swarm/memory.py | append-only JSONL 记忆。 |
swarm/context.py | 不靠模型总结的确定性上下文压缩。 |
swarm/research.py | 固定 planner-worker-critic-synthesizer 并发研究流水线。 |
swarm/director.py | 强模型主导、harness 约束的自主研究/编码循环。 |
swarm/autonomy.py | 多轮可恢复 loop,复用 ResearchSwarm。 |
swarm/target.py | 目标工作区隔离、diff、patch apply。 |
swarm/build_policy.py | 编码任务的完成门槛。 |
swarm/benchmarks.py | 用 staged benchmark 评估 harness 行为和任务结果。 |
swarm/audit.py | 事后观察模型健康、工具、证据、压缩和失败模式。 |
swarm/cli.py | 把这些能力包装成用户可用命令。 |
13. 本项目最值得带走的架构信条
- 协议优先:先定义模型允许输出什么,再谈智能。
- 证据优先:没有 evidence id 的事实声明不可信。
- 计算优先可验证:命令输出要能被机器解析成 obligations。
- 状态外置:prompt 不是数据库,JSONL/state/checkpoint 才是。
- 工具有边界:能力和约束一起设计。
- 强模型做策略,程序做裁判:不要让模型既当选手又当裁判。
- 并发用于多视角,不用于逃避验证。
- 长任务必须可恢复。
- 失败路径也是产品功能。
- 评测 harness,而不只是评测模型。
14. 下一步可以如何继续演进?
从当前项目出发,合理的演进路线是:
- 保持小内核稳定:继续强化
director、tools、verifier、benchmark。 - 引入 typed agent 框架:把 worker/final schema 迁移到 PydanticAI 这类类型化输出系统。
- 引入 durable graph:把 director/fanout/checkpoint 迁移到 LangGraph 的图状态与 checkpoint。
- 增强 retrieval:把 workspace lexical retrieve 升级到 LlamaIndex 或更强的本地索引。
- 扩大 benchmark:覆盖更多真实 coding/research 场景,特别是长任务和隐藏测试。
- 强化沙箱:把
run_command放入容器/隔离用户,进一步降低长时间自治风险。
但无论换什么框架,本文讲的核心不变量都应该保留:
模型输出受控动作 -> 工具执行真实世界 -> 结果变成证据 -> 结论引用证据 -> 程序验证结论这就是从“会聊天的模型”到“能工作的 Agent”的关键跨越。