KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA
09. 完成一个有预算、可恢复的事故诊断 Agent — keel 龙骨
结课项目把前八章放回同一条 Harness 运行。目标不是再写一个孤立的 summarize() 函数,而是让系统能够回答:模型本轮看到了什么、为什么没看到另一条材料、压缩改变了什么、工具轨迹是否合法、worker 重启后从哪里继续,以及质量收益是否值得。
结课项目把前八章放回同一条 Harness 运行。目标不是再写一个孤立的 summarize() 函数,而是让系统能够回答:模型本轮看到了什么、为什么没看到另一条材料、压缩改变了什么、工具轨迹是否合法、worker 重启后从哪里继续,以及质量收益是否值得。
1. 最终任务
用户输入:
支付服务今天又超时,和上次事故有关吗?
判断现在是否恢复,给出证据和下一步,但不要执行写操作。
系统可访问:
- 当前 error rate 与订单成功率;
- 最近部署和配置变更;
- 历史事故
INC-42; - 只读查询工具;
- 有租户作用域的长期记忆;
- 上一 checkpoint 和事件历史。
正确回答不能仅凭“相似事故”宣布根因,也不能因为 error rate 下降就忽略订单仍失败。结论必须带当前证据 ID,并明确不确定性和下一步只读调查。
2. 最终架构
flowchart TD
A[用户目标 + Run State] --> B[身份/租户/ACL 过滤]
C[工具结果 / 监控 / 记忆] --> B
B --> D[Candidate 标准化]
D --> E[TokenCounter]
E --> F[BudgetPlan]
F --> G[Dependency-aware Selector]
G --> H{达到触发条件?}
H -->|否| J[Tool Trace Validator]
H -->|是| I[Compaction]
I --> J
J --> K[Provider Adapter / Model]
K --> L[Usage Reconcile]
L --> M[Event + Checkpoint]
M --> A
每个方框只有一个主要责任。MCP、向量库或供应商 conversation state 可以接入某些边界,但不能替代整条管线的预算、权限和恢复契约。
3. 阶段一:测量与预算
交付:
{
"window_limit": 8192,
"output_reserve": 800,
"fixed_reserve": 128,
"safety_margin": 256,
"system_tokens": 420,
"tool_schema_tokens": 760,
"dynamic_budget": 5828,
"counter_version": "teaching-counter@v1"
}
先用 CharTokenCounter 跑通,再明确替换成哪个真实 tokenizer。必须测试固定部分超过 input budget 时不会调用模型;不能通过删用户原始目标来让请求勉强成立。
4. 阶段二:候选与完整工具轨迹
候选至少包含当前任务、最新监控、部署记录、INC-42 记忆、tool call/result。执行顺序:
- 在候选产生前过滤 tenant 与权限;
- 为每项分配稳定 ID、kind、freshness、source;
- 把 call/result 建立 dependency;
- selector 输出 selected、dropped、by-kind token;
- 组装后运行 tool trace validator。
必须制造预算不足,证明 call/result 要么同时保留,要么同时被转换为带来源的旧轨迹摘要。
5. 阶段三:Compaction 与恢复
初始实验可以在 input budget 80% 触发,目标压到 55%,但报告中标明这是待校准策略,不是行业标准。
摘要输出至少分为:
已知当前事实
历史事实与来源
未决问题
证据 IDs
失败/未知工具结果
禁止推断的空白
保存 context.measured、context.compacted 和 versioned checkpoint。模拟 worker 在摘要生成后崩溃并重放同一任务,证明:同版本相同内容幂等;同版本不同内容冲突;旧版本无法覆盖新版本。
6. 阶段四:真实模型与生产替换
只有确定性不变量通过后才接真实模型:
- 用目标 tokenizer 替换字符估算;
- 用受约束摘要模型或供应商 compaction 替换规则摘要;
- 用真实只读监控/事故 API 替换固定数据;
- 用事务数据库或 durable workflow 替换内存 checkpoint;
- 保留本地预算、来源、工具轨迹和恢复校验。
模型负责语义选择和生成,不负责绕过身份、预算、call ID、版本与停止条件。
7. 一次运行必须留下的证据
run-42
context.measured 6120 / budget 7000
context.selected selected=8 dropped=2
context.compacted 6120 -> 3810 sources=...
context.validated tool_trace=valid
model.completed response_schema=valid
provider.usage estimate=3810 actual=3924 output=486
checkpoint.saved history_version=7
最终回答中的每个关键结论能回到 monitor:*、deployment:* 或 incident:*。摘要文本本身不能成为唯一证据。
8. 故障矩阵
| 故障 | 期望动作 | 必须保存的证据 |
|---|---|---|
| tokenizer 不可用 | 拒绝或保守降级 | counter error、未调用模型 |
| dynamic budget < 0 | 减工具/缩任务/拒绝 | budget report |
| 摘要为空或超时 | 按风险降级或暂停 | strategy、reason、deadline |
| orphan tool result | 拒绝装配 | offending call ID |
| outcome unknown | 保留未知并对账 | idempotency/evidence ID |
| checkpoint 重放 | 返回同版本或冲突 | run/version/hash |
| 迟到结果到达取消运行 | 丢弃状态变更 | current run status |
| 跨租户记忆候选 | 在选择前过滤 | policy decision,不记录敏感正文 |
9. 评估报告
对 full history、recent trim、structured summary、evidence retrieval 做同数据对照。报告至少包含:
- 任务正确率与关键事实召回;
- 错误确定性陈述;
- evidence 引用正确率;
- tool schema failure;
- token、延迟、调用次数和成功任务成本;
- 跨租户与敏感信息泄露;
- checkpoint 重放一致性。
只有收益覆盖新增复杂度、延迟和错误风险后,策略才能进入生产 Harness。
10. 运行现有证据
python courses/foundation/context-engineering/course/project/examples/01_measure_and_budget.py
python courses/foundation/context-engineering/course/project/examples/02_select_context.py
python courses/foundation/context-engineering/course/project/examples/03_compaction_strategies.py
python courses/foundation/context-engineering/course/project/examples/04_compact_tool_trace.py
python courses/foundation/context-engineering/course/project/examples/05_trigger_and_events.py
python courses/foundation/context-engineering/course/project/examples/06_recover_after_compaction.py
python -m unittest discover -s courses/foundation/context-engineering/course/project/tests -v
这些示例是可重复教学切片,不是完整生产服务。结课实现要把它们串进一个 Harness,并补真实 provider adapter 与运行存储。
11. 最终验收
- 能区分 state、memory、context、checkpoint 和供应商 conversation state;
- 使用完整消息计数并对账实际 usage;
- 预算报告能解释固定开销、动态空间与 dropped IDs;
- 候选经过权限、新鲜度、依赖和稳定选择;
- 压缩有来源、版本、失败降级和质量评估;
- 不拆 tool call/result,不把 unknown 写成 success;
- 重复事件和 worker 重启不会产生不同历史版本;
- 最终结论引用原始 evidence,而不是引用摘要自己;
- 能用质量、成本、延迟和风险共同做发布决定。
如果项目只能回答“摘要从 6120 变成 3810”,它仍然只是压缩演示;当它能解释每一次选择、失败和恢复时,才形成了 Context Engineering 系统。