Day 139 · 后台 Agent:webhook、邮件与定时任务触发,收件箱式审批
不是所有 Agent 都长在聊天框里。新工单的 webhook、客服邮箱里的新邮件、每天早上的定时扫描都能把 Agent 叫起来;它在后台起草好回复,停下来进收件箱,等人批准、改写、提意见或忽略。今天把验签、去重、领任务、断点续跑、收件箱和死信一层层搭出来,全部实跑。
不是所有 Agent 都长在聊天框里。新工单的 webhook、客服邮箱里的新邮件、每天早上的定时扫描都能把 Agent 叫起来;它在后台起草好回复,停下来进收件箱,等人批准、改写、提意见或忽略。今天把验签、去重、领任务、断点续跑、收件箱和死信一层层搭出来,全部实跑。
结论要冲正时,由代码(不是模型)起草贷记单,调查图在审批节点用 interrupt 暂停,主管在命令行或网页上批准或驳回,图从磁盘上的 checkpoint 恢复。给 Day 123 的 draft_credit_note 加显式幂等键和 BEGIN IMMEDIATE,补上 approved、issued、rejected 三个状态,两人审批门槛,签发前再查一次额度,驳回后改写给客户的话。11 个测试把权限边界钉死,其中一个证明了 Day 123 的「已有草稿就返回」挡不住批准之后的重放。
一张要等主管审批的退款工单,可能挂起两个小时;一个 worker 进程,可能在第五步的时候被重新部署杀掉。今天写一个最小的持久化运行时:每一步按幂等键落库,重放时已完成的步骤直接取结果;租约机制让死掉的 worker 的任务被别人接手;遇到审批就挂起,批准后从断点继续。
退款审批要等主管几个小时,年度对账要跑一个下午,中间发版重启、机器被回收都很正常。今天讲持久化执行(durable execution)的原理:把每一步的结果记进日志,重启后重放。再讲 Agent 特有的麻烦:模型输出不确定,重放时怎么办;副作用做了一半,怎么不重复退款。最后自己写一个带日志重放和幂等键的运行器,并对比 Temporal、Restate、DBOS 和 LangGraph checkpoint。
把跑十几分钟的批量工单处理从 HTTP 请求里挪到任务队列,用 arq 做异步 worker;分清哪些错误该重试、重试几层;用幂等键保证退款不会因为重试建两次;再用 LangGraph 的 checkpoint 让崩在半路的任务从断点接着跑。