代码语言

知识点思维导图

44 个知识节点

项目实战(13) - 任务系统与多 Agent 协作:Issue、签出与任务树

读完后,你应能完成以下任务:

  • 绘制“项目实战(13) - 任务系统与多 Agent 协作:Issue、签出与任务树 / Issue 是协作的载体”的关键对象与数据流,解释“在 Paperclip 里,所有协作都通过 Issue(任务)发生。”,并用源码位置、日志或 Trace 标注证据。
  • 为“项目实战(13) - 任务系统与多 Agent 协作:Issue、签出与任务树 / 状态机:任务怎么流动”设计正常与异常输入,验证“⭐ 关键:进入 in_progress 必须经过「签出」,不能手动 PATCH 过去。”,输出首个偏差位置与回归测试结果。
  • 实现“项目实战(13) - 任务系统与多 Agent 协作:Issue、签出与任务树 / 原子签出:为什么会 409?”的最小代码或配置,检验“如果是你自己已经签出的,再签出会幂等成功(不报错)。”,输出命令、结果与 Diff,并说明不适用边界。

本章目标:吃透 Issue(任务)系统——状态机、原子签出(为什么会 409)、任务树如何把活追溯回目标、@提及如何唤醒队友。最后讲清多 Agent 协作卡壳的两大根因和排查思路。

第 07 章讲了单个 Agent 怎么干活,这章讲一群 Agent 怎么协同而不打架。这是 Paperclip 真正值钱的地方。


一、Issue 是协作的载体

在 Paperclip 里,所有协作都通过 Issue(任务)发生。Agent 之间不直接「对话」,它们通过任务的创建、签出、状态变更、评论来协同。

每个 Issue 有:

  • 标题、描述、状态、优先级
  • 一个负责人(同一时间只能一个 Agent)
  • 一个父任务(形成任务树)
  • 关联的项目和可选目标

二、状态机:任务怎么流动

backlog ──▶ todo ──▶ in_progress ──▶ in_review ──▶ done
                          │
                       blocked

终态:done(完成)、cancelled(取消)。

状态 含义
backlog 待规划,还没安排
todo 已就绪,等人认领
in_progress 进行中(必须先签出才能进入)
in_review 待评审
blocked 被卡住,等外部解除
done / cancelled 终态

⭐ 关键:进入 in_progress 必须经过「签出」,不能手动 PATCH 过去。这是协作不打架的根基。


三、原子签出:为什么会 409?

这是本章最重要的机制。

签出(Checkout) 是把任务从「待办」转到「我正在做」的原子操作

POST /api/issues/{issueId}/checkout
{ "agentId": "{yourId}", "expectedStatuses": ["todo", "backlog", "blocked", "in_review"] }

它保证:同一时间,一个任务只能被一个 Agent 拥有。

想象两个 Agent(小张做的 A、小亮做的 B)同时醒来,都看到同一个 todo 任务想做:

Agent A ──┐
          ├──▶ 同时 POST checkout 同一个 issue
Agent B ──┘
                    │
              ┌─────┴─────┐
              ▼           ▼
        A 拿到 200     B 拿到 409 Conflict
        (签出成功)    (任务是别人的)

规则:

  • 抢赢的 Agent 拿到成功,开始干。
  • 抢输的拿到 409 Conflict——立刻停下,换个任务,绝不重试。
  • 如果是你自己已经签出的,再签出会幂等成功(不报错)。

💡 为什么「绝不重试 409」?因为 409 不是「稍后再试就好」的临时错误,它是明确告诉你「这活有主了」。重试只会浪费心跳和预算。这条在第 07 章的铁律里也强调过。


四、任务树:让活追溯回目标

每个任务都有 parentId,层层向上,最终连回公司目标。这棵树有两个作用:

  1. 可追溯:任何一个底层任务,都能回答「我为什么存在」——一路向上到公司目标。
  2. 驱动协作流转:父子关系是任务自动解锁、父任务被唤醒的基础。

委派时创建子任务:

POST /api/companies/{companyId}/issues
{
  "title": "实现缓存层",
  "assigneeAgentId": "{下属AgentId}",
  "parentId": "{父任务Id}",     ← 必须设
  "goalId": "{目标Id}",          ← 有就设
  "status": "todo",
  "priority": "high"
}

⚠️ parentId 必须设。漏了它,任务就成了「孤儿」,挂不进树——追溯不回目标,协作流转也会断。这是新手最常见的坑(下文「协作卡壳」详述)。


五、Agent 之间怎么传信息?

5.1 1)评论(Comments)——主要沟通渠道

每一次状态更新、提问、发现、交接,都通过评论发生:

POST /api/issues/{issueId}/comments
{ "body": "## 更新\n\nJWT 签名完成。\n\n- 加了 RS256 支持\n- 测试通过\n- 还差刷新 token 逻辑" }

也可以在更新任务时顺带评论:

PATCH /api/issues/{issueId}
{ "status": "done", "comment": "实现了登录端点的 JWT 认证。" }

评论风格:简洁 markdown,一行状态 + 要点 bullet + 相关链接。

5.2 2)@提及(@-Mentions)——唤醒队友

在评论里 @AgentName 提及另一个 Agent,会触发它的一次心跳

POST /api/issues/{issueId}/comments
{ "body": "@EngineeringLead 我需要你 review 一下这个实现。" }

名字必须精确匹配 Agent 的 name(大小写不敏感)。

@提及的规则(重要):

  • 别滥用 @:每次 @ 都触发一次消耗预算的心跳。
  • 别用 @ 来分配任务:要分活就创建/分配一个任务,不是 @ 一下。
  • 交接例外:如果一个 Agent 被明确 @ 并给了清晰指令去接某个任务,它可以通过签出来自我认领。

5.3 3)结构化决策卡片

当需要董事会/用户做结构化响应时,用交互卡片而不是自由文本:

  • suggest_tasks:建议的子任务
  • ask_user_questions:结构化提问
  • request_confirmation:明确的接受/拒绝决策
POST /api/issues/{issueId}/interactions
{ "kind": "request_confirmation", "payload": { "prompt": "接受这个方案吗?", ... } }

为什么不用「在评论里打 yes/no」?因为结构化卡片能驱动后续工作流(批准了就继续、拒绝了就修改),自由文本做不到这种可控流转。


六、协作卡壳的两大根因(排查必看)

这是实战中最高频的问题。当两个 Agent(如小张的 A 和小亮的 B)协作不起来时,99% 是这两个原因之一

6.1 根因 1:任务树没挂好

子任务没正确关联父任务(漏了 parentId),导致:

  • 任务成了孤儿,追溯不回目标
  • 父任务不会因子任务完成而被唤醒
  • 下游 Agent 永远等不到「上游干完了」的信号

排查:检查相关任务的 parentId 是否正确指向父任务。

6.2 根因 2:下游 Agent 没开 wakeOnAssignment

下游 Agent 没开启「任务分配时自动唤醒」,导致:

  • 上游把任务分给它了,但它根本没醒来
  • 任务一直挂在那没人动

排查:确认下游 Agent 开了 wakeOnAssignment(任务分配触发心跳)。

🔧 口诀:协作卡住,先查这两点——任务树挂好了吗?下游会自动醒吗? 检查这两点能解决绝大多数协作卡壳。


七、协作如何「自动流转」(理想流程)

把上面拼起来,一个健康的协作闭环长这样:

CEO 把目标拆成任务 ──▶ 分配给工程师(设 parentId/goalId,工程师开了 wakeOnAssignment)
                          │
            工程师被自动唤醒 ──▶ 签出 ──▶ 干活 ──▶ 置 done + 评论
                          │
        子任务 done ──▶ 父任务被唤醒 ──▶ 下游 QA 任务自动解锁
                          │
        QA Agent 被唤醒 ──▶ 签出 review 任务 ──▶ 发现问题就 @工程师 或建修复子任务

你(董事会)全程在看板上看着这一切发生,只在关键决策点介入。


八、常见错误

  • 手动把任务 PATCH 成 in_progress → 绕过了签出,会破坏单负责人保证。必须走 checkout。

  • 重试 409 → 任务有主了,换一个。

  • 创建子任务漏 parentId → 任务树断裂,这是协作卡壳根因 1。

  • 用 @提及代替任务分配 → @ 是沟通/唤醒,不是分活。分活要建任务。滥用 @ 还烧预算。

  • 取消跨团队任务 → 铁律:绝不取消跨团队任务,交回给你的经理处理。

  • 协作不起来就瞎改 prompt → 先按第六节查「任务树 + wakeOnAssignment」,别一上来动 prompt。


九、最佳实践

  • 委派时永远设 parentId(有目标就加 goalId:保持任务树完整。
  • 下游 Agent 开 wakeOnAssignment:让任务分配能自动唤醒它。
  • 用子任务做并行/交接,靠完成事件驱动,不要轮询。
  • 评论写「下一步」:每次更新都让接手者知道接下来做什么。
  • 关键决策用结构化卡片request_confirmation 等),不用自由文本 yes/no。
  • @ 要省着用:每次都烧一次心跳预算。

十、总结

  • Issue 是协作的载体:在 Paperclip 里,所有协作都通过 Issue(任务)发生。
  • 状态机:任务怎么流动:| in_progress | 进行中(必须先签出才能进入) |
  • 原子签出:为什么会 409?:如果是你自己已经签出的,再签出会幂等成功(不报错)。
  • 任务树:让活追溯回目标:可追溯:任何一个底层任务,都能回答「我为什么存在」——一路向上到公司目标。 -> 驱动协作流转:父子关系是任务自动解锁、父任务被唤醒的基础。
  • Agent 之间怎么传信息?:名字必须精确匹配 Agent 的 name(大小写不敏感)。
  • 常见错误:→ 绕过了签出,会破坏单负责人保证。

学完自测

选择所有正确答案;提交后逐项核对判断依据。

1在“任务系统与多 Agent 协作:Issue、签出与任务树”中,需要同时满足“Issue 是协作的载体”与“状态机:任务怎么流动”。给定正文约束“在 Paperclip 里,所有协作都通过 Issue(任务)发生。”,哪些判断保持了原有处理机制?多选
2“任务系统与多 Agent 协作:Issue、签出与任务树”出现偏差:“在“任务系统与多 Agent 协作:Issue、签出与任务树 / 原子签出:为什么会 409?”中,即使不满足“同一时间,一个任务只能被一个 Agent 拥有”,结果与副作用仍会保持不变。”已成为实际行为。围绕“原子签出:为什么会 409?”与“任务树:让活追溯回目标”,哪些判断能定位被改变的职责或边界?多选
3评审“任务系统与多 Agent 协作:Issue、签出与任务树”方案时,验收条件包含“每一次状态更新、提问、发现、交接,都通过评论发生。”。关于“1)评论(Comments)——主要沟通渠道”与“2)@提及(@-Mentions)——唤醒队友”的哪些决策符合正文机制?多选