跳转到内容

心跳执行模型:DB 驱动的 Agent 唤醒与调度

心跳执行模型:DB 驱动的 Agent 唤醒与调度

1. 问题定义

在多 Agent 编排系统中,如何高效、可靠地唤醒 Agent 执行任务?简单的轮询(定时轮询每个 Agent)存在以下问题:

  • 无效唤醒:没有任务的 Agent 也被唤醒,浪费 token
  • 重复唤醒:同一 Agent 被多次触发,导致并发执行冲突
  • 预算失控:唤醒前不检查预算,Agent 执行到超出预算才停止
  • 状态丢失:Agent 进程崩溃后,唤醒队列中的任务无法恢复

心跳执行模型通过 DB 驱动的唤醒队列解决这些问题。

2. 核心架构

3. 唤醒队列设计

3.1 队列存储

唤醒请求持久化到数据库表(如 agent_wakeup_requests),包含:

字段作用
agent_id目标 Agent
issue_id关联任务
trigger_type触发类型(scheduled / event / manual)
coalesce_key合并键,相同键的请求合并为一个
statuspending / processing / completed / skipped
created_at创建时间,用于优先级排序

3.2 Coalescing(合并)

当同一 Agent 在短时间内收到多个唤醒请求时,合并为一个执行:

  • 按 coalesce_key 合并:相同 Agent + 相同触发源的请求合并
  • 保留最新上下文:合并时保留最新的 issue 关联和参数
  • 避免并发冲突:同一 Agent 的 run 在执行中时,新请求排队

4. 触发器类型

4.1 定时触发(Scheduled)

基于 cron 表达式的定时唤醒,常用于:

  • Agent 定期检查分配的任务
  • 周期性报告生成
  • 例行维护和监控

4.2 事件触发(Event-driven)

由系统事件触发的唤醒:

事件行为
新任务分配给 Agent立即唤醒 Agent 开始执行
任务被 @-mention唤醒 Agent 处理提及
上级 Agent 下发子任务唤醒子 Agent
审批通过/拒绝唤醒 Agent 调整策略

4.3 手动触发(Manual)

由人类操作者(董事会)手动触发,用于:

  • 强制 Agent 立即执行
  • 调试和测试
  • 紧急干预

5. 执行前检查

5.1 预算预检

在执行 Agent 之前,检查该 Agent 的月度预算消耗:

预算检查流程:
1. 查询当前月度已消耗金额
2. 对比预算政策的 warn_percent 和 hard_limit
3. 若已超 hard_limit → 跳过执行,记录 skipped 事件
4. 若达到 warn_percent → 继续执行,但记录 warning 事件
5. 若正常 → 继续执行

关键设计:预算检查是执行前的预检,而非执行中监控。这避免了 Agent 已经开始执行后被强行中断的中间状态。

5.2 工作空间解析

确定 Agent 执行时需要的工作目录:

  • 项目工作空间:Agent 关联的项目目录
  • 执行工作空间:git worktree 或 operator branch,隔离执行环境
  • 运行时服务:dev server、preview URL 等

5.3 Secret 注入

将 Agent 执行所需的 API Key、数据库连接字符串等敏感信息注入到执行环境:

  • Secret 在运行时解析,不暴露给提示词
  • 按 Agent scope 过滤,Agent 只能获取自己绑定的 Secret
  • 解析结果缓存,避免每次心跳都解密

6. 执行模式

6.1 Local CLI/Session 模式

启动或恢复本地 CLI Agent 会话(如 Claude Code、Codex):

伪代码:
process = spawn(agent_command, args)
pipe stdout/stderr to run_log
await process.exit
parse exit_code, usage, session_state
return execution_result

6.2 Command Execution 模式

执行任意命令或脚本:

伪代码:
process = spawn(command, args, cwd=workspace_dir)
inject env_vars (secrets, workspace paths)
pipe stdout/stderr to run_log
await process.exit

6.3 Fire-and-Forget Webhook 模式

通知外部 Agent(如 OpenClaw)执行:

伪代码:
http.post(agent_webhook_url, {
issue_id, task_description, context
})
# 不等待结果,Agent 完成后回调报告

7. 执行后处理

7.1 成本事件记录

从 Adapter 执行结果中提取 token 使用量和成本:

维度说明
Agent哪个 Agent 消耗的
Issue哪个任务产生的
Provider哪个模型提供商
Model哪个模型
Cost USD美元成本
Tokensinput / output / cached

7.2 会话状态持久化

保存 Agent 的会话状态,支持下次心跳恢复:

  • 会话 ID 和会话参数
  • 未完成的工具调用状态
  • 压缩/摘要后的上下文

7.3 审计日志

所有心跳执行写入活动日志(activity log),记录:

  • 谁触发了执行
  • 执行了哪个 Agent 的哪个任务
  • 执行结果(成功/失败/跳过)
  • 成本和时间

8. 孤儿恢复(Recovery)

当 Agent 进程异常退出或心跳执行超时,可能产生孤儿 run:

8.1 检测机制

  • Liveness 检查:定期检查运行中的 heartbeat run 是否还在产出日志
  • Watchdog 决策:超时后自动标记为 orphaned
  • 恢复动作表:系统自动生成 recovery action 记录

8.2 恢复策略

场景策略
进程意外退出,执行锁仍在释放执行锁,创建 recovery action
孤儿 run 超过最大重试次数标记为 failed,升级人工处理
Agent 会话可恢复恢复会话上下文,重新入队唤醒

9. 陷阱与对策

陷阱后果对策
高频心跳浪费 token预算快速消耗Coalescing 合并重复唤醒 + 预算预检
并发唤醒导致双分配同一任务被两个 Agent 同时执行原子 checkout + 执行锁
预算竞态(多个 Agent 同时通过预检)总消耗超出预算预算检查时加乐观锁,或使用余额扣减
孤儿 run 无法检测Agent 已死但系统认为还在运行Liveness watchdog + 超时自动标记
Secret 注入泄漏敏感信息出现在日志中日志脱敏(log redaction),Secret 值替换为 [REDACTED]

10. 参考来源

  • Paperclip Heartbeat Service — server/src/services/heartbeat.ts(361KB,完整实现)
  • Paperclip Agent Wakeup Requests Schema — packages/db/src/schema/agent_wakeup_requests.ts
  • Paperclip Run Liveness — server/src/services/run-liveness.ts
  • Paperclip SPEC-implementation.md — §5.1 Heartbeat invocation