AI 深度技能之-解读Hermes Agent(五)- 并非只有 Kanban

0 阅读13分钟

上一篇用 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:

  1. 更新 .tasks/03-*.md 状态为 ready(退回编码阶段)
  2. 在 .handoffs/03→04.json 中补充 review_feedback 字段
  3. 更新 .tasks/04-*.md 状态为 blocked,reason 为 "等待 03 修复"

完成协议

如果 verdict 为 approved:

  1. 更新 .tasks/04-*.md 状态为 done
  2. 写 .handoffs/04→final.json 包含审查通过结论
  3. 更新 .tasks/05-merge.md 状态为 ready

注意 @reviewer.md 的退回协议:它定义了"退回"这个动作的完整文件操作——更新哪些文件、写什么字段。这就是纯 Markdown 协议的精髓:没有 API 调用,只有文件读写


运行时:一次完整的流水线

假设仓库已经初始化好了。现在用一条需求跑完整流水线:

d2_pipeline_flow.png

上图展示了四个阶段的完整接力。每个阶段都遵循七步协议(读取 → 匹配 → 确认 → 执行 → 写产出 → 更新状态 → 提交触发下一阶段)。下面是每一步的实际操作。

第一步:创建需求

# 在仓库根目录
claude --agent @pm "分析需求:给 CRM 加一个客户标签批量导入功能"

@pm Agent 被拉起,它读取 TEAMAGENTS.mdAGENTS.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 定义的协议。下图展示了协议的七个步骤:

编排协议流程

协议的七个步骤

  1. 读取 TEAMAGENTS.md — 获取当前阶段的路由规则
  2. 匹配 assignee — 找到对应的 agents/*.md 角色文件
  3. 读取 .tasks/N.md — 确认任务状态为 ready
  4. 启动 Agent 执行 — 注入 AGENTS.md + agents/*.md 作为上下文
  5. 写产出到 .handoffs/ — 结构化 JSON 交接包
  6. 更新状态.tasks/N.md → done,.tasks/N+1.md → ready
  7. 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_eventsgit log
并发控制TTL 锁 + reclaimGit 分支 / 文件锁
可视化Dashboard GUIgit 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-mdTICK.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 KanbanAGENTS.md + TEAMAGENTS.md
状态存储SQLite WALMarkdown + JSON 文件
调度器Dispatcher 守护进程 60s 轮询Git Hook / Cron / 手动
工具集kanban_* 内置函数无,Agent 读文件自驱
容错自动重试 + 熔断 + TTL 锁Git 回滚 + 人工查看日志
可视化Dashboard GUI + WebSocketgit 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.mdTEAMAGENTS.md,让 Kanban 的 Worker 在执行时也读这两个文件。Kanban 管调度和状态,Markdown 管角色行为和交接协议。


总结

Hermes Kanban 解决的是"怎么自动调度",AGENTS.md + TEAMAGENTS.md 解决的是"怎么定义行为和契约"。两者不是替代关系,是不同层面的工具。

纯 Markdown 方案的核心价值:

  1. 零依赖——任何支持 AGENTS.md 的 Agent 都能参与流水线(Claude Code、Codex、Cursor、Gemini CLI、Aider……)
  2. Git 原生审计——每次状态变更都是一个 commit,git log 就是完整执行历史
  3. 人机通用——人和 Agent 读同一份文件,理解同一套协议
  4. 框架无关——不绑定任何特定框架,换工具不需要改协议

代价是:

  1. 没有自动调度,靠 Git Hook / Cron / 手动
  2. 没有结构化数据库,状态靠文件解析
  3. 没有 GUI Dashboard
  4. 容错靠人工

但如果你已经在用 Git 做协作,如果你用的 Agent 工具不统一,如果你不想被框架锁定——两个 Markdown 文件就是最轻量的流水线方案。


参考: