最小 Agent 工作台


最小 Agent 工作台

本节摘要:最有用的最小工作台只有三个文件:一个根指令路由器、一个状态文件、一个任务板。其他一切都叠加在它们之上。如果一个仓库承载不了这三个文件,没有模型能救它。大多数团队够向工作台的方式是写一份 3000 行的 AGENTS.md 然后宣布完工——模型加载它,忽略它总结不了的部分,在它一直失败的那些面上照旧失败。你需要的是相反的:一个极短的根路由文件,只在相关时把 Agent 指向更深的文件;持久的状态,Agent 行动前读、结束后写;一个任务板,说明什么在飞、什么阻塞、什么待办。三文件,各有其职,各自机器可读到足以日后演化为真实系统。本节定义这三件套——AGENTS.md 是路由器不是手册(短,指向状态文件、任务板、深层规则、验证命令;长手册被忽略,短路由被遵从)、agent_state.json 是真相之源(承载活动任务 id、动过的文件、所做假设、阻塞、下一步;放文件里因为聊天历史不可靠——会话会死、对话会被修剪,文件不会)、task_board.json 是队列(每任务带 todo|in_progress|done|blocked 状态、id、目标、owner、验收标准;故意小——长过一屏是规划问题不是板问题)。本节还给出三条叠加在最小工作台上的生产模式:嵌套 AGENTS.md(最近优先,OpenAI 主仓 88 个)、要拒绝的反模式(冲突指令静默降级 ICLR AMBIG-SWE 48.8%→28%、不可验证的风格规则、为人写而非为 Agent 写)、跨工具符号链接(单根文件 + ln -s 让所有编码 Agent 同源)。读完本节,你能为任何新仓搭出这个三文件地基。

对应原课程:Phase 14 · Lesson 32 · minimal-agent-workbench(原英文 phases/14-agent-engineering/32-minimal-agent-workbench/docs/en.md)。前置:第 31 节(有能力的模型为何仍失败)。

学习目标

阅读完本节,你应当能够:

  1. 定义构成最小可行工作台的三个文件。
  2. 解释为什么短的根路由胜过长的单体 AGENTS.md。
  3. 构建一个 Agent 每轮读、结束时写的状态文件。
  4. 构建一个无需聊天历史即可跨多会话存活的任务板。
  5. 说出叠加在最小工作台上的三条生产模式及其取舍。

一、问题与直觉

大多数团队够向工作台的方式,是写一份 3000 行的 AGENTS.md 然后叫它完工。模型加载它,忽略它总结不了的部分,在它一直失败的同样那些面上照旧失败。

你需要的是相反的:

  • 一个极小的根文件,只在相关时把 Agent 路由进更深的文件。
  • 持久的状态,Agent 行动前读、结束后写。
  • 一个任务板,说明什么在飞、什么阻塞、什么待办。

三个文件。每个一个职责。每个都机器可读到足以日后演化为真实系统。

AGENTS.md 是路由器,不是手册

一个好的 AGENTS.md 很短。它把 Agent 指向:

  • 状态文件(你在哪)。
  • 任务板(还剩什么)。
  • 深层规则(在 docs/agent-rules.md 下)。
  • 验证命令(怎么知道它成了)。

任何更长的东西,放进更深的文档,只在需要时加载。长手册被忽略;短路由被遵从。

agent_state.json 是真相之源

状态承载:活动任务 id、动过的文件、所做假设、阻塞、下一步。Agent 每轮读它。下次会话读它,而非重放聊天。

状态活在文件里,因为聊天历史不可靠——会话会死、对话会被修剪,文件不会。这与第 31 节「循环闭合在状态文件上」、第 07 节「外部存储是磁盘」一致。

task_board.json 是队列

任务板承载每个任务,带状态 todo | in_progress | done | blocked。它是状态为空时 Agent 拉取的队列,也是你想知道 Agent 是否在轨道上时你读的队列。

板上的一个任务有 id、目标、owner(builder、reviewer、human)、验收标准。板故意小:当它长过一屏,你有的是规划问题,不是板问题。

三文件是地板,不是天花板

后续节加范围契约、反馈运行器、验证门、审查者清单、交接包。这里的三文件,是它们全都假设的地基。

二、从零实现

原课程 code/main.py 把最小工作台写进一个空仓,并演示单轮 Agent:

  1. 读 agent_state.json。
  2. 若状态为空,从 task_board.json 拉下一个任务。
  3. 在范围内动一个文件。
  4. 写回更新后的状态。

Step 1:AGENTS.md(短路由)

# AGENTS.md - 状态:每轮先读 `agent_state.json`;为空则从 `task_board.json` 拉任务。 - 规则:深层规则见 `docs/agent-rules.md`(按需读)。 - 范围:只动任务 `scope` 列出的文件。 - 验证:任务完成后跑 `acceptance` 命令;失败即未完成。 - 交接:结束写 `agent_state.json`,记改动/阻塞/下一步。 ​

Step 2:agent_state.json(真相之源)

{ "active_task": "T-102", "touched": ["src/api/handler.py"], "assumptions": ["用 pydantic 做校验"], "blockers": [], "next_action": "给 handler 加 ValidationError 处理" } ​

Step 3:task_board.json(队列)

[ {"id": "T-102", "goal": "加输入校验", "status": "in_progress", "owner": "builder", "scope": ["src/api/handler.py"], "acceptance": "pytest tests/test_handler.py"}, {"id": "T-103", "goal": "写校验测试", "status": "todo", "owner": "builder", "scope": ["tests/test_handler.py"], "acceptance": "pytest tests/test_handler.py"} ] ​

Step 4:单轮循环(读状态→拉任务→动文件→写回)

def agent_turn(): state = json.load(open("agent_state.json")) if not state.get("active_task"): task = next(t for t in board if t["status"] == "todo") task["status"] = "in_progress"; state["active_task"] = task["id"] task = find_task(state["active_task"]) edit_files(task["scope"], plan=state["next_action"]) state["touched"].extend(task["scope"]) state["next_action"] = "跑验收命令" json.dump(state, open("agent_state.json", "w")) ​

运行 python3 code/main.py 会创建 workdir/,放下三文件,跑一轮,打印 diff。重跑看第二轮如何从第一轮停下的地方接上——无需聊天历史。

💡 设计要点:最小工作台的力量在于把「我在哪」从聊天历史里搬到文件里。聊天历史是易失的(会话死、对话修剪),文件是持久的。下次会话不重放上次对话,它读 agent_state.json——这就是第 31 节「循环闭合在状态文件上」的最小落地。

生产模式(叠加在最小工作台上)

最小工作台要在真实 monorepo 里存活,有三条模式可叠加(独立,按需挑):

嵌套 AGENTS.md,最近优先。 OpenAI 主仓发了 88 个 AGENTS.md,每个子组件一个。Codex、Cursor、Claude Code、Copilot 都从工作文件向仓库根走,把路上每个 AGENTS.md 拼起来;子目录文件扩展根文件。Codex 加了 AGENTS.override.md 做替换而非扩展(覆盖机制 Codex 专有,跨工具工作避开)。Augment Code 的测量是关键的那句:最好的 AGENTS.md 给的质量跃升,等同从 Haiku 升到 Opus;最差的让输出比没有任何文件还糟。

要拒绝的反模式(哪怕看着像覆盖)。 冲突指令会静默把 Agent 从交互模式降到贪婪模式(ICLR 2026 AMBIG-SWE:48.8% → 28% 解决率);应编号优先级而非平铺。不可验证的风格规则(「遵循 Google Python 风格指南」)无执行命令,让 Agent 捏造合规;每条风格规则配确切的 lint 命令。风格在前、命令在后会埋掉验证路径;命令优先,风格最后。为人写而非为 Agent 写浪费上下文预算;简洁是特性。

跨工具符号链接。 单根文件配符号链接(ln -s AGENTS.md CLAUDE.md、ln -s AGENTS.md .github/copilot-instructions.md、ln -s AGENTS.md .cursorrules)让每个编码 Agent 用同一真相源。Nx 的 nx ai-setup 从单一配置跨 Claude Code、Cursor、Copilot、Gemini、Codex、OpenCode 自动化此事。

三、框架对比

在生产 Agent 产品里,同样的三文件以不同名字出现:

  • Claude Code:AGENTS.md/CLAUDE.md 做路由,.claude/state.json 式存储做状态,钩子做板。
  • Codex / Cursor:工作区规则做路由,会话记忆做状态,聊天侧栏的排队任务做板。
  • 自定义 Python Agent:你刚写的同样文件。

名字变,形状不变。

四、可复用产物

原课程 outputs/skill-minimal-workbench.md:为任何新仓生成三文件工作台——调到项目的 AGENTS.md 路由、带正确键的 agent_state.json、用当前 backlog 播种的 task_board.json。

五、练习

  1. (Easy) 给 agent_state.json 加 last_run 时间戳。文件超 24 小时即拒跑,除非操作员确认。
  2. (Medium) 给任务板加 priority 字段,把拉取器改成总挑最高优先级的 todo。
  3. (Medium) 把 task_board.json 迁到 JSON Lines,每任务一行,diff 在版本控制里干净。
  4. (Hard) 写一个 lint_workbench.py,AGENTS.md 超 80 行或引用不存在的文件即 fail。
  5. (Hard) 决定三文件里哪个丢了最痛。为它辩护。

本节要点回顾

  1. 最小工作台 = 三文件:根指令路由器、状态文件、任务板;承载不了这三,无模型能救。
  2. AGENTS.md 是路由器不是手册:短,指向状态/板/深层规则/验证命令;长手册被忽略,短路由被遵从。
  3. agent_state.json 是真相之源:活动任务 id、动过的文件、假设、阻塞、下一步;每轮读、结束写。
  4. 状态放文件因聊天不可靠:会话死、对话修剪,文件不会——下次会话读状态而非重放聊天。
  5. task_board.json 是队列:todo|in_progress|done|blocked,带 owner/验收;故意小,长过一屏是规划问题。
  6. 三文件是地板非天花板:范围契约、反馈运行器、验证门、审查者、交接包都叠加其上。
  7. 嵌套 AGENTS.md 最近优先:OpenAI 88 个;最好的等同 Haiku→Opus,最差的比无文件还糟。
  8. 拒绝反模式:冲突指令静默降级(48.8%→28%)、不可验证风格规则、风格在前命令在后、为人写。
  9. 跨工具符号链接:ln -s 让所有编码 Agent 同源;nx ai-setup 跨六工具自动化。
  10. 命令优先风格最后:每条风格规则配确切 lint 命令;简洁是特性。

下一节,我们把「指令」这一面做实——指令作为可执行约束:如何把自然语言规则翻译成机器可检查的断言,让「遵循 Google 风格」「不许动测试外的文件」从愿望变成验证门能强制执行的硬约束。


作者与出处
原作者: Rohit Gupta
来源:rohitg00
许可证:MIT
整理: 灏天文库整理
由灏天文库结构化整理,提供目录导航、全文检索与在线阅读,便于系统化学习
发布者: 作者: Rohit Gupta 转发
评论区 (0)
U