上一篇用 Hermes Kanban 的 SQLite 看板编排了一条"需求 → 设计 → 编码 → 审查"流水线。但如果你不想装 Hermes、不想跑守护进程、不想被框架锁定——能不能用两个 Markdown 文件搞定同样的事?能。AGENTS.md 定义个体行为,TEAMAGENTS.md 定义团队契约,Git 就是你的数据库。
为什么是这两个文件
先理清两个文件各自的职责:
| 文件 | 定位 | 作用 | 类比 |
|---|---|---|---|
| AGENTS.md | 全局约束 | 构建/测试命令、代码规范、安全边界——所有 Agent 继承 | 公司员工手册 |
| TEAMAGENTS.md | 团队契约 | 流水线阶段、角色路由、交接协议、状态机规则 | 项目 SOP 文档 |
AGENTS.md 是 2026 年被 60k+ 开源项目采用的开放标准(由 Linux 基金会托管),原生支持 Claude Code、Codex、Cursor、Gemini CLI 等主流 Agent。你不用装任何东西,在仓库根目录放一个 Markdown 文件就行。
TEAMAGENTS.md 不是官方标准,而是一种社区约定——多个团队(AWS sample、Claude Code Agent Teams、tick-md)都在用类似的模式:用一个 Markdown 文件定义多 Agent 协作契约。这个文件的核心价值是:让任何 Agent 读完后就知道该干哪步、找谁交接、产出写哪里。
整体架构:
上图展示了仓库中的文件分布:
- 根目录:
AGENTS.md(全局约束)+TEAMAGENTS.md(编排契约) agents/目录:每个角色一个 Markdown 文件(@pm.md/@designer.md/@coder.md/@reviewer.md).tasks/目录:任务卡片(Markdown 文件,含状态和 assignee).handoffs/目录:交接包(JSON 文件,结构化产出物).logs/目录:执行日志(文本追加)
全部是纯文件,Git 原生版本管理,人能读,Agent 也能读。
AGENTS.md:全局约束
这是仓库根目录的 AGENTS.md,所有 Agent 继承:
# AGENTS.md
## 项目概述
全栈 CRM 系统,前端 React 19 + TypeScript,后端 Go + PostgreSQL。
## 构建与测试
- 安装依赖: `pnpm install`
- 启动开发: `pnpm dev`
- 运行测试: `pnpm test`
- 类型检查: `pnpm tsc --noEmit`
- Lint: `pnpm lint`
## 代码规范
- TypeScript strict mode
- 单引号,不加分号
- 函数优先,避免 class
- 所有公开函数必须有 JSDoc 注释
- 提交前必须通过 `pnpm lint && pnpm test`
## 安全边界
- 不允许安装新依赖(需在 PR 中说明理由)
- 不允许修改 .github/workflows/ 下文件
- 不允许直接操作生产数据库
- 敏感配置只在 .env 中,禁止硬编码
## 目录约定
- agents/ — Agent 角色定义(每个文件一个角色)
- .tasks/ — 任务卡片(Markdown,含状态)
- .handoffs/ — 交接包(JSON,结构化产出)
- .logs/ — 执行日志(纯文本追加)
关键设计:这个文件不包含任何流水线编排信息。它只管"在这[SYSTEM_NOTE: Content compressed. Read the full version if needed.]
# @reviewer
## 角色
代码审查员。审查 @coder 的产出,决定通过还是退回。
## 输入协议
1. 读取 .handoffs/ 目录下最新 `*→04.json` 文件获取上游产出
2. 读取 .tasks/04-*.md 确认状态为 ready
3. 读取 AGENTS.md 获取代码规范基线
## 工作流程
1. 用 `git diff` 查看本分支与 main 的差异
2. 逐文件审查,检查:
- 是否符合 AGENTS.md 中的代码规范
- 是否有测试覆盖新增逻辑
- 是否有安全风险(SQL 注入、XSS、硬编码密钥)
- 命名是否清晰,函数是否过长
3. 写审查报告
## 产出协议
```json
{
"verdict": "approved" | "changes_requested",
"issues": [{"severity": "critical|major|minor", "file": "path", "line": 42, "message": "..."}],
"summary": "整体评价..."
}
退回协议
如果 verdict 为 changes_requested:
- 更新 .tasks/03-*.md 状态为 ready(退回编码阶段)
- 在 .handoffs/03→04.json 中补充
review_feedback字段 - 更新 .tasks/04-*.md 状态为 blocked,reason 为 "等待 03 修复"
完成协议
如果 verdict 为 approved:
- 更新 .tasks/04-*.md 状态为 done
- 写 .handoffs/04→final.json 包含审查通过结论
- 更新 .tasks/05-merge.md 状态为 ready
注意 @reviewer.md 的退回协议:它定义了"退回"这个动作的完整文件操作——更新哪些文件、写什么字段。这就是纯 Markdown 协议的精髓:没有 API 调用,只有文件读写。
运行时:一次完整的流水线
假设仓库已经初始化好了。现在用一条需求跑完整流水线:
上图展示了四个阶段的完整接力。每个阶段都遵循七步协议(读取 → 匹配 → 确认 → 执行 → 写产出 → 更新状态 → 提交触发下一阶段)。下面是每一步的实际操作。
第一步:创建需求
# 在仓库根目录
claude --agent @pm "分析需求:给 CRM 加一个客户标签批量导入功能"
@pm Agent 被拉起,它读取 TEAMAGENTS.md 和 AGENTS.md,然后:
# Agent 内部操作(你看不到,但这是它做的事)
cat .tasks/01-spec.md # 读任务卡片
cat TEAMAGENTS.md # 读路由规则
cat AGENTS.md # 读全局约束
# 执行需求分析(这一步是 Agent 的核心能力)
# 写产出
cat > .handoffs/01→02.json << 'EOF'
{
"task_id": "01",
"summary": "客户标签批量导入功能需求规格",
"user_stories": [
"作为销售经理,我想批量导入客户标签,以便快速给新客户分类",
"支持 CSV 格式,单次上限 5000 行"
],
"acceptance_criteria": [
"上传 CSV 文件,解析后预览前 10 行",
"确认后批量写入 customer_tags 表",
"重复标签自动跳过,返回跳过列表"
],
"constraints": ["不依赖第三方 CSV 解析库", "单次导入 < 3 秒"]
}
EOF
# 更新状态
sed -i 's/status: ready/status: done/' .tasks/01-spec.md
sed -i 's/status: todo/status: ready/' .tasks/02-design.md
# 提交
git add . && git commit -m "feat(spec): 需求分析完成 - 客户标签批量导入"
git push
第二步:自动触发设计阶段
# Git hook 或手动
claude --agent @designer
@designer 读取 .handoffs/01→02.json 拿到需求,然后:
# 读取上游产出
cat .handoffs/01→02.json
# 执行技术设计(Agent 核心能力)
# 产出:方案文档 + API 设计 + 数据模型
cat > docs/design/bulk-import-tags.md << 'EOF'
# 客户标签批量导入 - 技术设计
## API 设计
POST /api/customers/tags/bulk-import (multipart/form-data)
## 数据模型
无新增表,复用 customer_tags 表
## 流程
1. 接收 CSV 文件
2. 解析并验证(行数限制、格式校验)
3. 预览模式:返回前 10 行解析结果
4. 确认模式:批量 INSERT IGNORE
5. 返回:成功数、跳过数、跳过详情
EOF
# 写交接包
cat > .handoffs/02→03.json << 'EOF'
{
"task_id": "02",
"summary": "技术方案完成",
"design_doc": "docs/design/bulk-import-tags.md",
"api_endpoint": "POST /api/customers/tags/bulk-import",
"test_plan": "单元测试 CSV 解析 + 集成测试端到端",
"estimated_files": ["internal/api/handlers/bulk_import.go", "internal/service/tags.go"]
}
EOF
# 更新状态
sed -i 's/status: ready/status: done/' .tasks/02-design.md
sed -i 's/status: todo/status: ready/' .tasks/03-code.md
git add . && git commit -m "feat(design): 技术方案完成 - 批量导入"
git push
第三步:编码
claude --agent @coder
@coder 读取 .handoffs/02→03.json,拿到设计文档路径,开始编码:
cat .handoffs/02→03.json
# 编码实现(Agent 核心能力)
# 写后端代码 + 写测试 + 运行测试
# 确保通过测试
pnpm test
# 写交接包
cat > .handoffs/03→04.json << 'EOF'
{
"task_id": "03",
"summary": "编码完成",
"changed_files": [
"internal/api/handlers/bulk_import.go",
"internal/service/tags.go",
"internal/api/handlers/bulk_import_test.go"
],
"tests_passed": true,
"coverage": "87%",
"notes": "CSV 解析用 encoding/csv 标准库,无新依赖"
}
EOF
sed -i 's/status: ready/status: done/' .tasks/03-code.md
sed -i 's/status: todo/status: ready/' .tasks/04-review.md
git add . && git commit -m "feat(code): 批量导入实现完成"
git push
第四步:审查
claude --agent @reviewer
@reviewer 读取 .handoffs/03→04.json,审查代码:
cat .handoffs/03→04.json
# 审查代码
git diff main...HEAD
# 写审查结果
cat > .handoffs/03→04.json << 'EOF'
{
"verdict": "approved",
"issues": [
{"severity": "minor", "file": "bulk_import.go", "line": 42, "message": "错误信息可以更具体"}
],
"summary": "实现质量良好,测试覆盖充分,可以合并"
}
EOF
sed -i 's/status: ready/status: done/' .tasks/04-review.md
sed -i 's/status: todo/status: ready/' .tasks/05-merge.md
git add . && git commit -m "review: 审查通过 - 批量导入功能"
git push
如果审查不通过,@reviewer 会把 03-code.md 的状态改回 ready,并在交接包里写 review_feedback,然后 @coder 再次被触发——这就是退回循环。
编排协议详解
上面的流水线能跑起来,核心靠的是 TEAMAGENTS.md 定义的协议。下图展示了协议的七个步骤:
协议的七个步骤
- 读取 TEAMAGENTS.md — 获取当前阶段的路由规则
- 匹配 assignee — 找到对应的
agents/*.md角色文件 - 读取 .tasks/N.md — 确认任务状态为
ready - 启动 Agent 执行 — 注入
AGENTS.md+agents/*.md作为上下文 - 写产出到 .handoffs/ — 结构化 JSON 交接包
- 更新状态 —
.tasks/N.md→ done,.tasks/N+1.md→ ready - Git commit — 提交触发下一阶段
这个协议的精妙之处在于:它完全是约定,不是代码。Agent 读完 Markdown 文件就知道该干什么,不需要 API、不需要 SDK、不需要守护进程。
为什么纯文件能替代数据库
| 需求 | Hermes Kanban 方案 | Markdown 方案 |
|---|---|---|
| 状态存储 | SQLite WAL | .tasks/*.md 文件 |
| 交接数据 | task_runs.metadata JSON 字段 | .handoffs/N→N+1.json 文件 |
| 调度触发 | Dispatcher 60s 轮询 | Git hook / cron / 手动 |
| 审计日志 | task_events 表 | git log |
| 并发控制 | TTL 锁 + reclaim | Git 分支 / 文件锁 |
| 可视化 | Dashboard GUI | git log --grep 或 IDE 文件树 |
纯文件的代价是没有自动调度和实时仪表盘。但对于一个 2-4 人的流水线,这些不是刚需。
自动触发:Git Hook 方案
纯 Markdown 方案最大的问题是"谁来触发下一步"。答案是 Git Hook。
post-commit Hook
#!/bin/bash
# .git/hooks/post-commit
# 在每次 git commit 后自动检查是否需要触发下一阶段
# 获取最近提交的文件变更
CHANGED=$(git diff --name-only HEAD~1 HEAD)
# 检查是否更新了 .tasks/ 目录下的状态文件
if echo "$CHANGED" | grep -q ".tasks/.*-.*.md"; then
# 找到刚刚变为 ready 的任务
READY_TASK=$(grep -rl "status: ready" .tasks/ 2>/dev/null | head -1)
if [ -n "$READY_TASK" ]; then
# 从任务文件提取 assignee
ASSIGNEE=$(grep "^assignee:" "$READY_TASK" | awk '{print $2}')
echo "⚡ 触发 $ASSIGNEE 处理 $READY_TASK"
# 后台启动对应 Agent(不阻塞 git commit)
nohup claude --agent "$ASSIGNEE" > ".logs/$(basename $READY_TASK .md).log" 2>&1 &
fi
fi
Cron 定时轮询方案
如果不用 Git Hook,可以跑一个 cron:
# crontab -e
*/2 * * * * cd /path/to/repo && ./scripts/dispatch.sh
#!/bin/bash
# scripts/dispatch.sh — 每 2 分钟扫描一次
cd /path/to/repo
# 找到 ready 状态的任务
READY=$(grep -rl "status: ready" .tasks/ 2>/dev/null)
for TASK_FILE in $READY; do
# 检查是否已有同名 .lock 文件(防并发)
LOCK=".tasks/.$(basename $TASK_FILE).lock"
if [ -f "$LOCK" ]; then
# 检查是否超时(15 分钟)
AGE=$(($(date +%s) - $(stat -c %Y "$LOCK" 2>/dev/null || echo 0)))
if [ $AGE -lt 900 ]; then
continue
fi
echo "⚠️ 锁超时,清理 $LOCK"
rm "$LOCK"
fi
# 加锁
echo $$ > "$LOCK"
# 提取 assignee
ASSIGNEE=$(grep "^assignee:" "$TASK_FILE" | awk '{print $2}')
echo "⚡ 触发 $ASSIGNEE 处理 $TASK_FILE"
# 启动 Agent
timeout 600 claude --agent "$ASSIGNEE" > ".logs/$(basename $TASK_FILE .md).log" 2>&1
# 释放锁
rm "$LOCK"
done
这个 30 行的 bash 脚本就是 Markdown 方案的"Dispatcher"。不优雅,但能用。
Fan-out 并行:多任务同时 ready
流水线不总是线性的。有时候一个阶段要拆成多个并行子任务。
任务文件定义并行
.tasks/02-design-a.md:
---
id: 02-a
title: 方案 A 调研
assignee: @designer
status: ready
depends_on: [01]
gate: any # 01 完成即可启动
---
.tasks/02-design-b.md:
---
id: 02-b
title: 方案 B 调研
assignee: @designer
status: ready
depends_on: [01]
gate: any
---
.tasks/03-synth.md:
---
id: 03
title: 方案综合
assignee: @designer
status: todo
depends_on: [02-a, 02-b]
gate: all # 必须 02-a 和 02-b 都完成
---
调度脚本支持 gate
#!/bin/bash
# scripts/dispatch_gated.sh — 支持 depends_on + gate 的调度
cd /path/to/repo
for TASK_FILE in .tasks/*.md; do
STATUS=$(grep "^status:" "$TASK_FILE" | awk '{print $2}')
[ "$STATUS" = "ready" ] || continue
# 解析 depends_on
DEPS=$(grep "^depends_on:" "$TASK_FILE" | sed 's/depends_on: //;s/[//g;s/]//g;s/,/ /g')
GATE=$(grep "^gate:" "$TASK_FILE" | awk '{print $2}')
GATE=${GATE:-all}
ALL_DONE=true
ANY_DONE=false
for DEP in $DEPS; do
DEP_FILE=$(grep -rl "^id: $DEP$" .tasks/ 2>/dev/null | head -1)
DEP_STATUS=$(grep "^status:" "$DEP_FILE" | awk '{print $2}')
if [ "$DEP_STATUS" = "done" ]; then
ANY_DONE=true
else
ALL_DONE=false
fi
done
# gate 检查
if [ "$GATE" = "all" ] && [ "$ALL_DONE" = true ]; then
echo "✅ $TASK_FILE 依赖全部满足 (gate: all)"
# 启动 Agent...
elif [ "$GATE" = "any" ] && [ "$ANY_DONE" = true ]; then
echo "✅ $TASK_FILE 至少一个依赖完成 (gate: any)"
# 启动 Agent...
else
echo "⏳ $TASK_FILE 等待依赖"
fi
done
这就是 Markdown 方案实现 kind=dependency 的方式——解析 YAML frontmatter,检查依赖状态。不如 Hermes 的自动依赖追踪优雅,但透明、可调试。
退回与重试:审查不通过
审查不通过是流水线最常见的分支。在 Markdown 方案里,退回就是改文件状态:
# @reviewer 审查不通过时的操作
# 1. 把 03-code.md 状态改回 ready
sed -i 's/status: done/status: ready/' .tasks/03-code.md
# 2. 在交接包里补充 review_feedback
python3 -c "
import json
with open('.handoffs/03→04.json', 'r') as f:
data = json.load(f)
data['verdict'] = 'changes_requested'
data['review_feedback'] = {
'issues': [ {'file': 'bulk_import.go', 'line': 42, 'message': '错误处理不够具体'}, {'file': 'bulk_import_test.go', 'line': 15, 'message': '缺少边界测试'} ],
'must_fix_before': '2026-07-15'
}
with open('.handoffs/03→04.json', 'w') as f:
json.dump(data, f, indent=2, ensure_ascii=False)
"
# 3. 自己状态标为 blocked
sed -i 's/status: ready/status: blocked/' .tasks/04-review.md
git add . && git commit -m "review: 退回编码阶段 - 需修复 2 个问题"
@coder 被[SYSTEM_NOTE: Content compressed. Read the full version if needed]ispatcher" bash 脚本 + Git Hook + 手动触发。没有 GUI Dashboard,但 git log + tree .tasks/ 就是你的看板。
建议引入的辅助工具
如果你觉得纯 bash 脚本太原始,可以引入这些:
| 工具 | 用途 | 是否必须 |
|---|---|---|
tick-md | TICK.md 文件锁定 + 依赖追踪 + MCP | 可选 |
jq | 解析 .handoffs/ JSON | 推荐 |
yq | 解析任务文件 YAML frontmatter | 推荐 |
entr | 文件变更触发命令 | 可选 |
tmux | 多 Agent 并行会话 | 可选 |
最佳实践
1. 交接包必须结构化
// ✅ 好的交接包
{
"task_id": "02",
"summary": "技术方案完成",
"design_doc": "docs/design/bulk-import.md",
"changed_files": ["file1.go", "file2.go"],
"tests_passed": true,
"coverage": "87%",
"decisions": [{"decision": "用标准库 csv", "reason": "无新依赖"}]
}
// ❌ 坏的交接包
{
"summary": "搞定了,看 git log 吧"
}
下游 Agent 依赖交接包里的字段决定下一步行为。模糊的交接包等于断了流水线。
2. 状态文件用 YAML frontmatter
---
id: 03
title: 编码实现
assignee: @coder
status: ready
depends_on: [02]
gate: all
created_at: 2026-07-12T10:00:00Z
updated_at: 2026-07-12T14:30:00Z
---
## 任务描述
...
## 执行记录
- 2026-07-12 14:30 @coder 开始执行
YAML frontmatter 让 bash 脚本能用 grep/awk 解析,也让人能读正文。
3. 日志只追加不覆盖
# .logs/03-code.md
[2026-07-12 14:30] @coder started
[2026-07-12 14:35] created bulk_import.go
[2026-07-12 14:40] tests passed (87% coverage)
[2026-07-12 14:42] @coder completed
用 >> 追加,不用 > 覆盖。Git 天然有版本历史,但追加日志让当前会话内的过程可见。
4. 每个阶段一个 Git 分支
git checkout -b feat/bulk-import-01-spec
# @pm 工作并提交
git push
git checkout -b feat/bulk-import-02-design
# @designer 工作并提交
git push
# 审查通过后合并到 main
git checkout main
git merge feat/bulk-import-04-review
分支隔离让每个阶段的文件变更不互相干扰,合并时也有自然的检查点。
5. TEAMAGENTS.md 是活文档
每次发现交接协议有歧义,立刻在 TEAMAGENTS.md 里补充说明。这个文件会越来越厚,但每一条都是用真实踩坑换来的。
与 Hermes Kanban 的对比
| 维度 | Hermes Kanban | AGENTS.md + TEAMAGENTS.md |
|---|---|---|
| 状态存储 | SQLite WAL | Markdown + JSON 文件 |
| 调度器 | Dispatcher 守护进程 60s 轮询 | Git Hook / Cron / 手动 |
| 工具集 | kanban_* 内置函数 | 无,Agent 读文件自驱 |
| 容错 | 自动重试 + 熔断 + TTL 锁 | Git 回滚 + 人工查看日志 |
| 可视化 | Dashboard GUI + WebSocket | git log + tree + IDE |
| 框架依赖 | 需安装 Hermes Agent | 零依赖,任何 Agent 通用 |
| 审计 | task_events 表 | git log --stat |
| 并行支持 | 多 Worker 同时拉取 | 需额外 bash 脚本 |
| 适合场景 | 无人值守长期运行 | 人机协作,阶段性触发 |
| 学习成本 | 学 Hermes CLI + Kanban 概念 | 会写 Markdown 就行 |
选择建议
选 Hermes Kanban 如果:
- 流水线需要 7×24 无人值守运行
- 有 5+ 个 Agent Profile 并行
- 需要实时仪表盘监控
- 团队中有非技术人员需要看 Dashboard
选 AGENTS.md + TEAMAGENTS.md 如果:
- 流水线是人按节奏触发的(不是全自动跑)
- 团队用多种 Agent 工具(Claude Code、Codex、Cursor 混用)
- 不想引入额外框架
- Git 是你的主要协作工具
- 团队规模小(1-3 人 + 3-5 Agent)
两者可以共存:在 Hermes Profile 的 workspace/ 下放 AGENTS.md 和 TEAMAGENTS.md,让 Kanban 的 Worker 在执行时也读这两个文件。Kanban 管调度和状态,Markdown 管角色行为和交接协议。
总结
Hermes Kanban 解决的是"怎么自动调度",AGENTS.md + TEAMAGENTS.md 解决的是"怎么定义行为和契约"。两者不是替代关系,是不同层面的工具。
纯 Markdown 方案的核心价值:
- 零依赖——任何支持 AGENTS.md 的 Agent 都能参与流水线(Claude Code、Codex、Cursor、Gemini CLI、Aider……)
- Git 原生审计——每次状态变更都是一个 commit,
git log就是完整执行历史 - 人机通用——人和 Agent 读同一份文件,理解同一套协议
- 框架无关——不绑定任何特定框架,换工具不需要改协议
代价是:
- 没有自动调度,靠 Git Hook / Cron / 手动
- 没有结构化数据库,状态靠文件解析
- 没有 GUI Dashboard
- 容错靠人工
但如果你已经在用 Git 做协作,如果你用的 Agent 工具不统一,如果你不想被框架锁定——两个 Markdown 文件就是最轻量的流水线方案。
参考:
- AGENTS.md 官方标准:agents.md
- AGENTS.md GitHub 60k+ 示例:github.com/openai/code…
- Claude Code Agent Teams 文档:eesel.ai 2026 指南
- AWS Agent Team 示例:github.com/aws-samples…
- tick-md 多 Agent 协调:purplehorizons.io/blog/tick-m…
- 上一篇 Hermes Kanban 指南:
hermes-kanban-pipeline.md