a↗Agent 工程实战中文课程 / v1.0.0⌕ 搜索课程/
本页目录

L05 将对话原型服务化:任务、审批、事件流

适用章节:M05–M06。本实验允许多种正确实现;验收不变量固定,不强制特定框架。

工程事故

用户点了两次提交,产生两个Run;等待批准的请求挂着HTTP连接半小时;刷新后浏览器重放事件,把同一条结果追加三次。你需要把任务寿命与一次连接的寿命分开。

最终交付

持久任务模型、审批记录、API接口实现或完整契约测试、SSE重连设计;一份Outbox故障说明。参考内核不提供完整HTTP服务器。

已提供材料

specs/API_CONTRACT.md、reference/agentlab/durability.py、reference/agentlab/business.py

先独立写出预期行为再看参考解。所有商店、订单、试次与价格单位都是教学构造;不连接真实资金系统。

接口与不可破坏的约束

遵循API_CONTRACT:创建任务返回202与run_id;请求幂等键绑定租户、用户和规范化请求体。模型生成的“确认”不能代替人类批准。审批绑定金额、对象版本、operation_id与有效期。

事件流按(run_id,seq)去重。连接中断不取消任务;取消是单独的经过授权操作。审批与任务终态都保存在服务端,而不是仅放localStorage。

实施步骤

  1. 实现Run表、Event表、Outbox表。在一个事务内创建Run+初始事件+待投递消息。
  2. 提供create/get/claim三个内核操作,验证相同请求幂等与不同请求冲突。
  3. 画出QUEUED、RUNNING、WAITING_APPROVAL等合法转移。等待状态不持有执行lease。
  4. 实现审批提案与确认入口;同时测试旧摘要、过期和已消费提案。
  5. 实现事件游标:重连从after_seq继续,客户端用主键去重;过旧游标返回resync_required并提供快照。
  6. 接上HTTP层时先用契约测试,再做一个最小Console。不要让UI直接调用数据库或持有Provider密钥。

验收矩阵

故障/动作 期望
同key同请求POST两次 同run_id,仅一条初始Outbox
同key不同请求 409语义冲突
事务提交后未投递进程退出 Outbox仍可恢复投递
投递成功但未mark_sent 允许重复投递,消费者必须去重
after_seq=1重连 只回seq>1;客户端仍处理重复网络帧
等待审批时claim NOT_RUNNABLE
其他租户读run/events NOT_FOUND

如何运行已有参考测试

在包根目录运行:

python -m unittest discover -s reference/tests -v

本实验主要参考测试类为DurabilityTests。已有测试默认验证reference/;测试通过不代表你的starter/实现通过。接入自己的实现时,将被测模块显式替换/注入,保持测试和领域契约不变,不要修改断言来迁就实现。

评分

事务/幂等25;审批25;事件与重连20;权限15;服务边界与测试15。

出现跨租户泄露、未经批准的退款或伪造结果时,不以其他分数抵消。允许记录未完成的选修功能,但必须说明范围。

进阶挑战

为等待状态添加经过认证的resume事务:校验当前version和审批→QUEUED→写新Outbox,三者原子提交。并发两次批准只能唤醒一次。

提交前自查

保存代码版本、运行命令、输入数据版本、输出日志、失败案例与设计决策。解释至少一个被你否决的方案。没有运行的测试标记“未运行”,不写“预计通过”。参考解见对应答案。