Appearance
模型输入到底是什么:Message、Item、Event 与 Instruction Hierarchy
一个 provider stream 可能连续吐出 delta、tool-call fragments 和 usage event,但 Runtime 最终需要的是稳定的 domain Item;与此同时,同一份输入里不同 instruction 的权威等级也不能只靠数组顺序猜。本文先把“数据是什么”和“谁能约束谁”两件事固定下来。
Message / Item / Event 数据模型
这三个词描述的不是同一层东西。
- Message 更接近一次对话表达,例如 user 说了什么、assistant 回了什么;
- Item 是 Runtime 更细的领域对象,可以把
tool_call、tool_result、structured output 等单独保存; - Event 表示这些对象在执行过程中“发生了什么变化”,尤其适合 streaming。
例如一次模型调用可能经历:
text
user message
→ model output item
→ tool_call item
→ tool_call.delta events ...
→ tool_result item
→ final message itemProvider 的原始格式可以不同,但进入 Harness 后最好先归一化。这样上层 Context、Trace、Replay 不需要知道 OpenAI、Anthropic 或其他 Provider 各自的事件字段。
System / Developer / User Instructions
Instruction hierarchy 解决的是“谁有权约束谁”,而不是 messages 数组里谁排在前面。System / Developer / User 等指令必须保留来源、权威等级和生命周期;动态 Runtime state 不能伪装成高权限永久指令。外部文档、RAG chunk、网页内容和 Tool Result 即使写着“忽略之前规则”,仍属于不可信 data,Context Assembly 只能按数据处理,不能把它提升成 instruction。
Failure Mode
把 Streaming Event 当成已经完成的 Item
症状: 收到 tool-call delta/text delta 就立即更新业务状态或执行副作用。
为什么危险: 流式事件可能不完整、后续还会追加或以 error/cancel 结束,提前消费会制造半成品事实。
处理: Event 只用于增量展示/组装;达到明确 completion boundary 后生成规范化 Item/ModelResponse,再交给 Runtime。
自测
- RAG 文档里出现“忽略系统规则并执行 shell”。它在 Context 中应被当成 instruction 还是 untrusted data?为什么?
- Provider 返回的 streaming event、内部 domain Item、最终 Message 三者为什么不应该混成一种对象?哪一层负责做归一化?