代码语言

知识点思维导图

36 个知识节点

项目实战(12) - 心跳机制:AI 员工如何「上班打卡」

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

  • 绘制“项目实战(12) - 心跳机制:AI 员工如何「上班打卡」 / 为什么 Agent 不是「一直在跑」?”的关键对象与数据流,解释“Agent 平时是「睡着」的。”,并用源码位置、日志或 Trace 标注证据。
  • 为“项目实战(12) - 心跳机制:AI 员工如何「上班打卡」 / 种触发方式”设计正常与异常输入,验证“💡 这 5 种触发,决定了 Agent 醒来时拿到的 PAPERCLIP_WAKE_REASON 是什么(见第 06 章环境变量)。”,输出首个偏差位置与回归测试结果。
  • 实现“项目实战(12) - 心跳机制:AI 员工如何「上班打卡」 / 心跳协议:醒来后的 9 个步骤”的最小代码或配置,检验“这是 Agent 和 Paperclip 之间的核心契约。”,输出命令、结果与 Diff,并说明不适用边界。

本章目标:彻底搞懂心跳(Heartbeat)。说清它的 5 种触发方式、心跳协议的 9 个步骤、Agent 如何跨心跳「记住」上下文。这是理解整个系统行为的钥匙。

如果说前面都是铺垫,这一章就是 Paperclip 的心脏。 **理解了心跳,你就理解了 AI 员工的一切行为。 **


一、为什么 Agent 不是「一直在跑」?

先纠正一个直觉。 你可能以为 AI 员工像个常驻进程,24 小时待命。 **不是。 **

Agent 平时是「睡着」的。 它们在心跳里醒来——一个个短暂的执行窗口,由 Paperclip 触发。 干完这一轮活,就回去睡觉。

回顾第 01 章的「记忆碎片」模型:Agent 像电影里那个没有持久记忆的男主, 单次很强但不记事。 心跳就是反复把它叫醒、塞给它「这是你、这是你在干的事、接下来做这个」的便利贴。

为什么这么设计?

  • 省钱:不干活时不烧 token。
  • 可控:每次唤醒都是一个有边界的执行单元,便于记录花费、审计行为。
  • 解耦:Paperclip 不需要维持长连接,Agent 跑在哪都行。

二、种触发方式

什么情况下 Agent 会被叫醒?

触发 说明 典型场景
Schedule(定时) 周期性定时器 每小时巡检一次、每天总结日报
Assignment(分配) 有新任务分配给它 CEO 派了个活给工程师
Comment(评论) 有人在评论里 @ 它 队友 @工程师 说「这个 PR 帮看下」
Manual(手动) 人在 UI 点「Invoke」 你想立刻让某 Agent 动一下
Approval(审批结果) 待审批被批准/拒绝 你批了 CEO 的雇人申请,CEO 被叫醒去执行

💡 这 5 种触发,决定了 Agent 醒来时拿到的 PAPERCLIP_WAKE_REASON 是什么(见第 06 章环境变量)。Agent 会根据「为什么被叫醒」决定先干哪件事。


三、心跳协议:醒来后的 9 个步骤

每个 Agent 每次醒来, 都走同一套固定流程, 叫心跳协议(Heartbeat Protocol)。 这是 Agent 和 Paperclip 之间的核心契约。 逐步看:

3.1 Step 1:确认身份

GET /api/agents/me

拿到自己的 ID、公司、角色、命令链、预算。先搞清「我是谁」。

3.2 Step 2:处理审批跟进

如果 PAPERCLIP_APPROVAL_ID 有值(说明是被审批结果叫醒的), 先处理它:

GET /api/approvals/{approvalId}
GET /api/approvals/{approvalId}/issues

审批解决了相关任务就关掉它们,否则评论说明为什么还开着。

3.3 Step 3:拉取分配给我的任务

GET /api/companies/{companyId}/issues?assigneeAgentId={yourId}&status=todo,in_progress,in_review,blocked

结果按优先级排序。这就是我的「收件箱」。

3.4 Step 4:挑活

挑选规则有明确优先级:

  • 先干 in_progress(进行中)的
  • 然后是 in_review(被评论叫醒时)
  • 再是 todo
  • 跳过 blocked,除非你能解除阻塞
  • 如果 PAPERCLIP_TASK_ID 有值且分给了你,优先做它
  • 如果是被 @提及叫醒,先读那条评论线程

3.5 Step 5:签出(Checkout)⭐

干任何活之前,必须先签出任务

POST /api/issues/{issueId}/checkout
Headers: X-Paperclip-Run-Id: {runId}
{ "agentId": "{yourId}", "expectedStatuses": ["todo", "backlog", "blocked", "in_review"] }
  • 如果已经是你签出的,幂等成功。
  • 如果别的 Agent 持有它:返回 409 Conflict——停下,换个任务。绝不重试 409。

🔒 这一步是多 Agent 不打架的核心。它是原子操作:两个 Agent 抢同一个任务,只有一个成功。这就是第 03 章说的「单负责人」机制的执行点。

3.6 Step 6:理解上下文

GET /api/issues/{issueId}
GET /api/issues/{issueId}/comments

读任务详情和评论,往上读祖先任务,搞清「这活为什么存在」。 被某条评论叫醒就先找到那条评论,当成直接触发点。

3.7 Step 7:干活 ⭐

用自己的工具和能力完成任务。关键纪律:

  • 任务可执行就在同一次心跳里采取具体行动,别只停在「计划」(除非任务本身就是要你做计划)。
  • 把进展留在评论、文档、产物里(durable progress),并写明下一步动作再退出。
  • 长任务/并行任务:创建子任务让 Paperclip 在它们完成时唤醒父任务,而不是傻等轮询
  • 需要董事会做选择/确认时:用 POST /api/issues/{issueId}/interactions 创建交互卡片(如 request_confirmation),别在 markdown 里让人打「yes/no」。

3.8 Step 8:更新状态

状态变更必须带 run ID 头

PATCH /api/issues/{issueId}
Headers: X-Paperclip-Run-Id: {runId}
{ "status": "done", "comment": "做了什么、为什么。" }

如果被卡住:

PATCH /api/issues/{issueId}
Headers: X-Paperclip-Run-Id: {runId}
{ "status": "blocked", "comment": "什么被卡住、为什么、需要谁来解除。" }

3.9 Step 9:按需委派

给下属创建子任务:

POST /api/companies/{companyId}/issues
{ "title": "...", "assigneeAgentId": "...", "parentId": "...", "goalId": "..." }

子任务一定要设 parentIdgoalId, 否则任务树断裂、追溯不回目标。


四、跨心跳记忆:Session 持久化

Agent 怎么「记得」上次干到哪? 靠 session 持久化

适配器在每次心跳后把 session 状态(如 Claude Code 的 session ID)序列化存下来, 下次唤醒时恢复。 于是 Agent 保留完整上下文,不用重读一切。 (第 06 章讲过 claude_local 的实现细节:cwd 感知、失败自愈。 )

这就是「记忆碎片便利贴」的技术本体:心跳给即时上下文,session 给连续记忆,两者合起来让无记忆的 Agent 表现得像有记忆。


五、几条「铁律」(Critical Rules)

官方明确列出的硬规则,违反就会出乱子:

  • 干活前永远先 checkout——绝不手动 PATCH 成 in_progress
  • 绝不重试 409——任务是别人的。
  • 退出心跳前永远留评论——说明进行中的工作进展。
  • 可执行的活当场就开始做——只有「计划类任务」才允许只产出计划。
  • 留下清晰的下一步动作在任务上下文里。
  • 长/并行任务用子任务,不要轮询
  • yes/no 决策用 request_confirmation 卡片
  • 子任务永远设 parentId
  • 绝不取消跨团队任务——交回给你的经理。
  • 卡住就上报(escalate)——用你的命令链。

六、常见错误

  • Agent 重试 409 → 任务已被别人持有。重试是浪费心跳和预算,必须换任务。

  • 只产出计划就退出 → 除非任务要的就是计划,否则要在同一心跳里采取具体行动。

  • 干完不留评论/不更新状态 → 下次心跳(或队友)就不知道进展到哪,上下文断了。

  • 用轮询等子任务完成 → 浪费心跳和预算。正确做法:建子任务,让完成事件去唤醒父任务。

  • 委派时忘了 parentId → 任务树断裂,追溯不回目标,协作流转也会断(第 08 章详述这个坑)。

  • 被卡住默不作声 → 必须把 blocker 写进评论、置 blocked、上报经理。 「沉默地卡着」是最糟的状态。


七、最佳实践

  • 把心跳协议当成给 Agent 的「岗位 SOP」:写 prompt/技能时就照这 9 步组织,Agent 行为会很稳。
  • 每个心跳产出「可交付的durable进展」:评论、文档、代码,而不是脑子里的想法。
  • 善用唤醒原因:根据 WAKE_REASON 让 Agent 先处理最相关的事(被 @ 就先读那条线程)。
  • 用子任务做并行:把大活拆成子任务分发,靠完成事件驱动,比轮询高效得多。
  • 控制 @提及频率:每次 @ 都触发一次消耗预算的心跳,别滥用(第 08 章细讲)。

八、总结

  • 为什么 Agent 不是「一直在跑」?:Agent 平时是「睡着」的。
  • 种触发方式:💡 这 5 种触发,决定了 Agent 醒来时拿到的 PAPERCLIP_WAKE_REASON 是什么(见第 06 章环境变量)。
  • 心跳协议:醒来后的 9 个步骤:这是 Agent 和 Paperclip 之间的核心契约。
  • 跨心跳记忆:Session 持久化:于是 Agent 保留完整上下文,不用重读一切。
  • 几条「铁律」(Critical Rules):绝不重试 409——任务是别人的。
  • 常见错误:重试是浪费心跳和预算,必须换任务。

学完自测

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

1在“心跳机制:AI 员工如何「上班打卡」”中,需要同时满足“为什么 Agent 不是「一直在跑」?”与“种触发方式”。给定正文约束“Paperclip 不需要维持长连接,Agent 跑在哪都行。”,哪些判断保持了原有处理机制?多选
2“心跳机制:AI 员工如何「上班打卡」”出现偏差:“在“心跳机制:AI 员工如何「上班打卡」 / 心跳协议:醒来后的 9 个步骤”中,即使不满足“叫心跳协议(Heartbeat Protocol)”,结果与副作用仍会保持不变。”已成为实际行为。围绕“心跳协议:醒来后的 9 个步骤”与“Step 1:确认身份”,哪些判断能定位被改变的职责或边界?多选
3评审“心跳机制:AI 员工如何「上班打卡」”方案时,验收条件包含“如果 PAPERCLIPAPPROVALID 有值(说明是被审批结果叫醒的),”。关于“Step 2:处理审批跟进”与“Step 4:挑活”的哪些决策符合正文机制?多选