事件与 OpenTelemetry Schema¶
本页记录 Agent 循环发出的事件名称、负载,以及 adapters/otel 的映射。它是
兼容性说明,不是投递保证。
事件信封¶
event.Event 是所有 Sink 共享的线格式:
| 字段 | 类型 | 含义 |
|---|---|---|
type |
string | 稳定的事件名 |
sessionId |
string | 会话标识 |
runId |
string | 运行标识;Agent 循环之外可能为空 |
data |
object | 事件负载;可能不存在 |
at |
RFC 3339 时间戳 | 发出时间;发送方留空时由框架设为 UTC |
事件是进程内通知。event.Sink 不承诺重试、投递或持久化。event.MultiSink
遇到第一个 Sink 错误即停止,因此后续 Sink 可能收不到该事件。
Agent 事件类型¶
| 类型 | data 键 | 触发时机 |
|---|---|---|
run.started |
无 | 运行进入受治理循环 |
run.completed |
无 | 运行成功返回 |
run.failed |
error(string) |
运行返回错误,包括策略或审批拒绝 |
tool.call |
name(string)、arguments(object) |
工具调用即将执行 |
tool.interrupt |
name(string)、arguments(object) |
工具调用等待审批决定 |
arguments 可能包含租户数据、提示词、文件路径或调用方提供的凭据。持久化或
导出前必须脱敏。
Go 结束顺序¶
尚未发布的 Go 源码先执行 AfterRun middleware,包括结构化输出校验和修复,
然后依次执行 OnRunComplete、checkpoint 投影、记忆写入和 run.completed。
校验或修复失败时不发送最终 checkpoint、不保存答案,也不发送完成通知。
原始模型消息和文本增量仍是临时输出,可能已在最终校验之前发送。
OnRunComplete 接收已验证结果的副本。它可以返回错误来阻止完成,但修改副本
不会改写最终结果、运行 ID、checkpoint 投影或记忆记录。需要主动转换输出时,
应使用结束提交前的 AfterRun middleware。
完成 hook、checkpoint 回调或记忆写入出错会阻止完成通知,并进入运行失败路径。
若 run.completed 的 Sink 自身返回错误,Run 会返回该错误并调用 OnRunError,
但不再尝试 run.failed,因为 fail-fast Sink 可能已向部分消费者发送完成通知。
因此收到完成通知不保证 Run 返回 nil;即使同时返回结果,也必须检查错误。
这些回调和写入不是原子事务。checkpoint 投影之后记忆写入仍可能失败;事件投递 失败也不会回滚已写入的记忆。checkpoint stream part 是最终结果投影,不代表 持久 checkpoint 已落盘或 exactly-once 执行。需要事务持久化时由消费者实现。 历史 source tag 保留原来的回调顺序,其他 Core 的生命周期需要分别验证。
已进入的 middleware 即使在后续 BeforeRun 失败时也会执行 AfterRun,范围仅限
已进入的前缀,包括返回错误的回调;启动拒绝仍不发送运行事件。AfterRun 返回
错误不再阻断后续清理,后续回调接收原始执行错误或第一个结束错误,第一个错误
保持优先。普通回调 panic 仍向外传播,不保证在 AfterRun panic 后继续清理。
内置调用限制和工具选择通过内部运行 ID 清理状态,不再依赖非空 Result。
Stream 投影¶
agent.Options.OnStream 接收 agent.StreamPart。它是独立的类型化投影,不是
event.Sink 事件:
values、updates、messages、tasks、debug、checkpointtasks当前携带工具任务状态转换的status、name和arguments
Stream 投影按加法演进。使用方必须忽略未知 kind 和未知 data 字段。
兼容规则¶
- v2 模块线内事件类型字符串保持稳定。重命名或删除需要新的主版本。
- 次要版本可以新增事件类型和
data键。 - 使用方必须忽略未知事件类型和未知 data 键。
data值必须保持 JSON 可序列化。允许嵌套 map 和 slice。- 事件顺序是单个 Sink 的发送顺序。并发工具调用可能按完成顺序发出事件。
event.MultiSink是 fail-fast,不是 best-effort 扇出。- 事件负载不是持久审计记录。需要持久化的产品应在确认运行前写入存储。
OpenTelemetry 映射¶
adapters/otel 将一个事件映射为一个 span:
| Span 字段 | 值 |
|---|---|
| 名称 | praxo.<event type> |
praxo.event.type |
事件类型 |
praxo.session.id |
会话 ID(存在时) |
praxo.run.id |
运行 ID(存在时) |
praxo.event.at |
UTC 发出时间(存在时) |
praxo.event.data.<key> |
选中的数据值,仅通过 AllowedDataKeys |
Event.Data 默认不导出。选中某个键会导出其 fmt.Sprint 值,且不会脱敏。
没有单独脱敏策略时,不要选择 arguments、结果、凭据或其他敏感字段。
事件 span 继承传给 Emit 的 context 中的父 span。每个 span 表示一个事件,
不是完整运行的持续时间。
验证¶
conformance.CheckEventSink验证 Sink 能接受格式正确的事件。- OTel 适配器测试覆盖 span 命名、属性、数据排除、允许列表和父 trace 继承。
- 这些检查不证明投递、保留或后端访问控制。