从零理解 Agent 架构:以 Swarm 项目为例

面向读者:刚开始学习 LLM Agent 的开发者。本文不假设你熟悉 LangChain、LangGraph 或复杂多智能体框架,而是用本项目 swarm 的实际实现来解释:一个能读文件、写代码、跑命令、并留下可审计证据的 Agent 应该如何设计。

项目快照:基于 2026-07-05 当前工作区代码与文档整理。

0. 一句话概括本项目

swarm 是一个高并发、工具驱动、证据优先的研究/编码 Agent 原型。它的核心不是“让模型自由发挥”,而是把职责分清:

  • 模型负责判断下一步该读什么、查什么、写什么、运行什么、什么时候收束;
  • 程序 harness负责执行工具、记录证据、限制风险、压缩上下文、恢复状态、验证最终声明;
  • 工作区保存问题、产物、日志、报告、可复现实验和补丁。

这就是本项目最重要的设计哲学:

让 LLM 做判断,让确定性程序做约束。

如果你是 Agent 初学者,可以把这个项目看成“怎样把 ChatGPT 变成可靠工作流”的一份工程范例。


1. 初学者先理解:什么是 Agent?

普通 LLM 调用大致是:

用户问题 -> 模型回答

Agent 则多了一个循环:

用户目标
  -> 模型决定下一步动作
  -> 程序执行动作(搜索、读文件、写文件、跑命令)
  -> 观察真实结果
  -> 模型基于结果再决定下一步
  -> ...
  -> 最终答案/产物

所以,一个实用 Agent 至少包含五件东西:

层次作用本项目中的对应实现
模型接口调用一个或多个 LLMswarm.llm.ChatClient
控制循环决定下一步、处理模型输出swarm.research.ResearchSwarmswarm.director.ResearchDirector
工具系统把模型动作变成真实操作swarm.tools.ToolRegistry
记忆/状态保存过程、证据、断点swarm.memory.Memorydirector_state.jsonheartbeat.json
验证与评估防止幻觉和未验证结论swarm.verifySWARM_VERIFICATION_JSONswarm.build_policyswarm.benchmarks

很多 Agent 项目失败,是因为只关注“模型会不会推理”,忽略了后四层。本项目的精华正是把后四层做成了可观察、可恢复、可验证的工程内核。


2. 项目整体架构鸟瞰

当前代码主要分为四条工作流:

  1. swarm run:固定流程的并发研究 Swarm。
  2. swarm loop:多轮可恢复自治循环。
  3. swarm director:强模型主导的“研究导演”模式。
  4. swarm solve/build/research/agent:面向普通任务的独立工作区模式。

其中最值得学习的是两种架构:

  • 固定流水线式 Swarm:规划多个角度,并发 worker 搜索/验证,再由 critic 和 synthesizer 汇总。
  • Director 自主循环:每一步由强模型选择 toolfanoutcheckpointfinal,但所有动作必须通过 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、并发、上下文大小;
  • 同一角色可以换模型,同一模型也可以承担多个角色。

对应代码:

  • ProviderConfigbase_urlmodelapi_key_envmax_concurrencysafe_context_chars
  • RuntimeConfig:请求超时、重试、stream 设置;
  • SwarmConfig.provider_for_role(role):把角色映射到 provider。

初学者可学到的原则:

Agent 架构里不要写死“哪个模型做什么”。应该写“哪个角色需要什么能力”,再由配置决定模型实现。

精华 3:工具不是函数列表,而是安全边界

ToolRegistry 提供的工具大致分为四类:

工具类别例子是否能作为事实证据
外部/资料检索web_searchweb_content可以
工作区观察workspace_listworkspace_readworkspace_searchworkspace_file_infoworkspace_git_diff可以
执行验证run_command可以,而且最强
状态变更workspace_writeworkspace_editwrite_note通常不能直接证明事实

这个区分非常关键。写了一个文件,并不能证明这个文件是对的;只有读到的内容、搜索结果、命令输出、哈希信息、测试结果等,才可以作为事实声明的证据。

工具层还做了安全约束:

  • 所有 workspace path 必须相对目标工作区,阻止绝对路径和 .. 逃逸;
  • 写入 .git 等 VCS 元数据会被拒绝;
  • run_command 有危险命令 denylist,例如 rmsudoddmkfscurl | 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_writewrite_note 这类 non-grounding evidence;
  • 如果声明“验证了覆盖/唯一性/证书/不变量”,是否引用了带 SWARM_VERIFICATION_JSONrun_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 上下文窗口有限,而且长上下文并不总可靠。本项目采用:

  1. 工具完整结果写入 JSONL memory;
  2. 当前 prompt 只携带必要摘要、证据 ID 和最近交互;
  3. 超预算时用确定性 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.mddirector_summary.jsonverification.json:最终产物。

写状态时使用同目录临时文件加 os.replace,避免进程中断留下半截 JSON。

这让长任务具备三个能力:

  1. 运行中可以观察进度;
  2. 中断后可以从 evidence、steps、fanouts、checkpoints 继续;
  3. 完成后可以审计每一步。

对应实现:

  • 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

完成后可以:

  1. target-diff 导出 patch;
  2. 人类 review;
  3. target-apply --check 检查;
  4. 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.mdFINAL_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_callcall_toolanswer 等别名。

这一层是 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_noteworkspace_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

这是最复杂但也最有价值的部分。建议分块读:

  1. DirectorOptions:先看有哪些控制参数;
  2. _initial_transcript():理解 director 可以做哪些 move;
  3. run() 前半段:resume、preflight、initial fanout;
  4. run() 主循环:parse、guard、tool/fanout/checkpoint/final;
  5. final guard:为什么最终声明会被拒绝;
  6. _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.jsonheartbeat.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 clientprovider router、LiteLLM 等
Durable orchestration自写 director state loopLangGraph
Typed worker自写 JSON protocol + dataclassPydanticAI
Retrieval本地 lexical search + web CLILlamaIndex
Benchmark自写 staged benchmark更系统的数据集/评测平台

这个取舍对初学者非常有启发:

先用小内核把 Agent 的不变量跑通,再考虑框架化;不要一开始就把错误藏进复杂框架里。


10. 设计反模式:本项目刻意避免了什么?

反模式 1:把模型回答当事实

错误做法:模型说“测试通过了”,就信。

本项目做法:必须有 run_command evidence;强命题必须有 structured obligation。

反模式 2:把 prompt 当数据库

错误做法:把所有历史对话塞回 prompt。

本项目做法:JSONL memory 持久化,prompt 只保留摘要和证据 ID。

反模式 3:让所有子 Agent 都能写文件

错误做法:并发 worker 同时修改代码。

本项目做法:fanout 默认禁用 workspace_writeworkspace_editrun_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

先实现一个会:

  1. 读文件;
  2. 跑命令;
  3. 记录证据;
  4. 引用证据回答;
  5. 失败后继续修复。

再加入 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.pyAgent 的眼睛、手、shell 和安全边界。
swarm/schema.py把工具结果变成可引用证据,把结论变成可验证 claim。
swarm/verify.py确定性检查 final 是否有证据支撑。
swarm/memory.pyappend-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. 本项目最值得带走的架构信条

  1. 协议优先:先定义模型允许输出什么,再谈智能。
  2. 证据优先:没有 evidence id 的事实声明不可信。
  3. 计算优先可验证:命令输出要能被机器解析成 obligations。
  4. 状态外置:prompt 不是数据库,JSONL/state/checkpoint 才是。
  5. 工具有边界:能力和约束一起设计。
  6. 强模型做策略,程序做裁判:不要让模型既当选手又当裁判。
  7. 并发用于多视角,不用于逃避验证
  8. 长任务必须可恢复
  9. 失败路径也是产品功能
  10. 评测 harness,而不只是评测模型。

14. 下一步可以如何继续演进?

从当前项目出发,合理的演进路线是:

  1. 保持小内核稳定:继续强化 director、tools、verifier、benchmark。
  2. 引入 typed agent 框架:把 worker/final schema 迁移到 PydanticAI 这类类型化输出系统。
  3. 引入 durable graph:把 director/fanout/checkpoint 迁移到 LangGraph 的图状态与 checkpoint。
  4. 增强 retrieval:把 workspace lexical retrieve 升级到 LlamaIndex 或更强的本地索引。
  5. 扩大 benchmark:覆盖更多真实 coding/research 场景,特别是长任务和隐藏测试。
  6. 强化沙箱:把 run_command 放入容器/隔离用户,进一步降低长时间自治风险。

但无论换什么框架,本文讲的核心不变量都应该保留:

模型输出受控动作 -> 工具执行真实世界 -> 结果变成证据 -> 结论引用证据 -> 程序验证结论

这就是从“会聊天的模型”到“能工作的 Agent”的关键跨越。