KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
06. 把往返变成有边界的运行 — keel 龙骨
前一章只处理一次工具。现实任务可能需要先查事件,再查服务负责人,再生成报告。Harness 必须知道何时继续、何时失败、何时停止。
前一章只处理一次工具。现实任务可能需要先查事件,再查服务负责人,再生成报告。Harness 必须知道何时继续、何时失败、何时停止。
先看一条状态变化
queued
-> running
-> waiting_for_model
-> executing_tool
-> waiting_for_model
-> completed
如果模型不断要求工具,运行不能无限循环;如果用户取消,迟到的工具结果也不能把运行改回成功。
状态、事件和消息分开
| 对象 | 例子 | 主要用途 |
|---|---|---|
| Message | assistant.tool_call |
让模型理解协议历史 |
| State | step=2, status=executing_tool |
让 Harness 判断下一步和恢复 |
| Event | tool.started |
让日志、监控和回放知道发生了什么 |
消息可以被裁剪,状态可以被更新,事件应该追加记录。不要把运行状态只藏在消息文本里。
核心循环
flowchart TD
A[开始或恢复运行] --> B[请求模型]
B --> C[解析 Decision]
C --> D{final?}
D -->|是| E[校验并完成]
D -->|否| F{tool_call?}
F -->|否| G[协议失败]
F -->|是| H[Registry + Schema + Policy]
H -->|拒绝| I[记录拒绝并终止/等待]
H -->|允许| J[执行工具]
J --> K[记录 Result 和 State]
K --> L{预算/取消/deadline?}
L -->|否| B
L -->|是| M[停止并分类]
停止条件属于 Harness,不属于模型提示词。至少需要 max_steps、整次运行 deadline、取消信号和成本预算。
运行确定性测试
python -m unittest discover -s courses/foundation/agent-harness/course/project/tests -v
先观察固定 fake model 的结果,再读 harness.py:
- fake model 返回最终决定时,状态怎样变为 completed;
- fake model 返回未知工具时,怎样产生失败;
- fake model 永远返回工具调用时,怎样因 max steps 停止;
- 工具失败时,结果怎样回到事件和状态。
这四个行为是程序不变量,不应依赖真实模型本次是否选择了某个工具。
四种终止不是一回事
completed 得到符合协议和业务校验的结果
failed 发生不可恢复的模型、协议、工具或策略错误
cancelled 用户或上游主动停止
limit_reached 达到步数、时间或成本上限
这些状态会影响 API 响应、重试和运营指标,所以不能用一个 None 代替。
本章自测
如果工具执行成功,但写入事件失败,运行应该报告什么?至少要让系统能发现“业务动作可能已发生,但审计不完整”,而不是静默返回成功。这个问题会在可靠性章节继续展开。