事件订阅与主响应渲染
理解事件 envelope、临时与持久事件、子代理归属和启动阶段的订阅窗口。
开启 streaming: true 后,临时增量与持久消息共同出现在事件流中。临时事件不会写入会话日志,恢复后也不会重放;持久事件可以保存在日志中供恢复。
公共 envelope
| 字段 | 作用 |
|---|---|
id | UUID v4 事件标识 |
timestamp | ISO 8601 时间 |
parentId | 前一事件 ID,首个为 null |
agentId | 子代理实例标识,根代理和会话级事件省略 |
ephemeral | true 为临时;缺省或 false 为持久 |
type | 事件类型 discriminator |
data | 该类型专属 payload |
TypeScript 根据 event.type 缩窄 data;其他语言可能使用分开的事件 data 类型。不要假设所有事件都存在相同字段。
主聊天只展示根代理文本
session.on("assistant.message_delta", (event) => {
if (!event.agentId) {
process.stdout.write(event.data.deltaContent);
}
});子代理事件进入同一 session 流,可转到进度或 trace UI。归属使用 envelope 的 agentId;部分 data 中旧 parentToolCallId 已弃用,不能再作为通用主/子代理判定。
parentId 表达前后事件链,不是子代理父子关系。messageId 将文本增量关联到最终完整消息;渲染时避免把已累积增量和完整消息重复追加。
常用响应与用量事件
| 事件 | 关键字段与用途 |
|---|---|
assistant.turn_start、assistant.turn_end | turnId,跟踪模型轮次 |
assistant.intent | 临时 intent,描述正在做的工作 |
assistant.message_delta | 临时 messageId、deltaContent |
assistant.message | 完整 messageId、content,可含 toolRequests |
assistant.reasoning_delta、assistant.reasoning | 以 reasoningId 关联的增量与完整推理内容 |
assistant.streaming_delta | 临时 totalResponseSizeBytes,网络进度而非文本 |
assistant.usage | 临时单次模型使用、token、缓存、延迟、endpoint 与追踪 ID |
session.usage_info | 临时上下文 tokenLimit、currentTokens、messagesLength |
session.usage_checkpoint | 持久累计用量,供恢复记账 |
usage 中 reasoningTokens 是 outputTokens 的子集,不应再次相加;cost 在事件参考中描述为模型倍率成本,不能直接当作美元。详细计费使用相应 SDK 用量类型与官方计费规则。
创建返回前也可能有事件
会话 create/resume 返回前可能已经产生事件,尤其是恢复 pending work。之后才安装订阅会漏掉启动窗口,getMessages 无法补回临时 idle 等事件。
官方当前为 Rust 提供 prepare_session、prepare_resume_session:先取得 PreparedSession 并订阅,再调用 start。prepare 同步且不触发协议活动;未启动即丢弃不留会话状态,取消启动 future 会清理自己持有的注册,不能影响已接管同 ID 的重试。
Rust 默认事件缓冲为 512,可用 event_buffer_capacity 配置,0 会报错。慢订阅者收到 Lagged 与丢失数量,不会反压会话循环;需要完整启动事件时应扩大缓冲或同时持续消费。不要外推为所有语言相同的缓存 API。
云端由服务器分配 ID 时,ID 返回前事件无法路由。提前指定 session_id 才能从开始建立路由;PreparedSession 保证的是已可路由事件不会因缺订阅者而丢弃。
会话状态
session.idle 是临时完成处理信号,可含 data.aborted;session.error 含 errorType、message 及可选 statusCode/追踪信息。压缩开始 payload 为空,完成事件给 success、token 变化、checkpoint 和可选压缩模型用量。