KEEL · 龙骨 · A CURRICULUM FOR THE AI ERA

02. 一个动作需要哪些不会含糊的字段? — keel 龙骨

如果整个执行链只传递这段数据,出了问题几乎无法恢复:

如果整个执行链只传递这段数据,出了问题几乎无法恢复:

{"tool": "set_pool_limit", "value": 40}

它没有目标环境、业务意图、稳定标识、资源版本、deadline,也无法判断第二次收到它时是重试还是新请求。

先分清五个对象

对象 谁创建 回答的问题
ActionProposal 模型 “根据当前资料,我建议做什么?”
ActionCommand Harness “系统准备以哪个可信身份,对哪个资源做什么?”
ActionAttempt 执行网关 “这是该命令的第几次实际尝试?”
ExecutionReceipt Adapter/外部系统 “外部系统确认了什么?”
ActionEvent Harness/网关 “状态在何时因什么原因发生变化?”

Proposal 可以被拒绝或修改;Command 一旦进入审批和幂等记录,就必须保持不可变;Attempt 可以有多个;Receipt 是每次尝试的事实;Event 用来恢复因果链。

ActionCommand 的可信字段

项目中的命令包含以下信息:

class ActionCommand(BaseModel):
    command_id: str
    run_id: str
    intent_id: str
    kind: ActionKind
    target: ResourceRef
    arguments: dict[str, JsonValue]
    idempotency_key: str
    deadline_at: datetime

这些字段的来源不相同:

标识符各自解决什么

run_id             关联整次 Agent 运行
intent_id          关联用户的一次稳定业务意图
command_id         标识一个不可变命令
attempt_id         标识一次网络/执行尝试
idempotency_key    让外部系统识别重复业务提交
external_reference 让本地记录重新查询外部事实

不要用一个 request_id 代替全部含义。一次业务意图可能经过多个命令,每个命令又可能多次尝试。

Fingerprint 固定动作含义

对以下字段做规范化后再计算摘要:

action kind + target + normalized arguments

同一幂等键再次出现时:

时间戳、attempt ID 这类每次变化的字段不能进入 fingerprint,否则每次重试都会变成“新动作”。

状态转换由程序控制

stateDiagram-v2
    [*] --> proposed
    proposed --> ready: 校验并固定命令
    ready --> running: 创建 attempt
    running --> succeeded: 明确成功回执
    running --> failed: 明确失败回执
    running --> pending: 外部系统异步受理
    running --> unknown: 无法确认结果
    pending --> succeeded: 轮询/回调确认
    pending --> failed: 轮询/回调确认
    unknown --> succeeded: 对账确认
    unknown --> failed: 对账确认未生效
    unknown --> manual_review: 无法自动判断

模型可以建议下一步,但不能直接把 unknown 改成 succeeded。

运行契约示例

python courses/advanced/real-world-execution/course/project/examples/01_action_contract.py

观察 Proposal 如何被 Harness 转成带有可信租户、稳定 ID、deadline 和 fingerprint 的 Command。

检查理解

下一章:让 Ollama 只负责提出动作

进入 keel 阅读