KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

02. Wake-up、Signal、Timer 和 Task 有什么区别? — keel 龙骨

长周期 Agent 不能靠一个常驻 Python 线程“等着”。进程会重启、机器会缩容、用户输入会延迟,等待本身必须成为持久化状态。课程把各种继续运行的原因统一建模为 WakeupRequest,但保留它们的来源和取消语义。

长周期 Agent 不能靠一个常驻 Python 线程“等着”。进程会重启、机器会缩容、用户输入会延迟,等待本身必须成为持久化状态。课程把各种继续运行的原因统一建模为 WakeupRequest,但保留它们的来源和取消语义。

四种继续原因

类型 触发者 典型用途 关键字段
Timer 调度器 10 分钟后轮询部署状态 due_at、时区/时钟版本
Signal 用户或外部系统 审批、补充参数、webhook signal_id、来源身份、payload
Task completion 异步工具/服务 查询报表、批量导出完成 task_id、状态、结果引用
Retry 运行时 暂时性网络或限流错误 attempt、退避策略、deadline

它们都能进入 pending -> claimed -> fired/failed,但不应把外部 signal 伪装成 timer,也不应把尚未完成的 task 当成成功结果。LangGraph interrupts强调恢复点会保存状态并等待外部输入;当前 MCP Tasks 扩展则用 durable task ID、轮询/通知和明确终态表达 deferred result。Tasks 是需要双方协商支持的官方扩展,不是所有 MCP 客户端都具备的核心能力。

唤醒契约

最小请求至少包含:wakeup_id、run_id、kind、due_at、来源、去重键、取消策略和 payload schema。wakeup_id 是业务意图的身份,不是每次投递的消息 ID;消息重复投递仍应指向同一个请求。

配套项目的 SQLiteEventStore.schedule() 对相同 ID 的相同载荷幂等,对不同载荷报冲突;claim_due() 才会产生一次 delivery attempt 和 lease。运行:

python courses/advanced/advanced-agent-systems/course/project/examples/03_wakeup_and_lease.py

观察 worker A 持有 lease 时 worker B 无法领取,过期后 B 才能接管。这个结果比“线程睡醒了”更接近队列、webhook 和人工审批的共同协议。

取消与迟到输入

取消不是简单删除 wakeup:需要记录请求者、时间、原因和当前状态。已经 fired 的请求不能被取消来掩盖已发生的副作用;迟到 signal 必须依据 run 的终态和版本拒绝或转成新的业务请求。

本章检查点

下一章:租约、幂等和重复投递怎样一起工作?

进入 keel 阅读