message_update 事件深入
1145 字
6 分钟
message_update 事件深入
message_update 事件深入
message_update 是 AgentEvent 系统中最特殊的事件: 它既是高层事件,又携带底层事件; 它既是业务边界,又包含技术细节。
理解 message_update,就是理解两层事件系统的连接点。
数据结构:两个关联字段
message_update 的类型定义揭示了两层关系:
{ type: "message_update"; message: AgentMessage; // 高层累积状态 assistantMessageEvent: AssistantMessageEvent; // 底层流事件}两个字段,两种视角:
message:当前累积的消息状态(业务层关心的”结果”)assistantMessageEvent:当前触发的底层事件(技术层关心的”过程”)
每次底层事件触发时,message_update 同时携带:
- 底层事件的增量信息(delta)
- 高层消息的累积状态(message)
关联一:AgentMessage 类型树
AgentMessage 是三种消息类型的联合:
AgentMessage│├── UserMessage│ ├── role: "user"│ ├── content: string | Content[]│ └── timestamp: number│├── AssistantMessage ⭐(message_update中最常见)│ ├── role: "assistant"│ ├── content: ContentPart[] ← 多种内容块│ │ ├── TextContent { type: "text", text }│ │ ├── ThinkingContent { type: "thinking", thinking }│ │ └── ToolCall { type: "toolCall", id, name, arguments }│ ├── usage: Usage ← token统计│ ├── stopReason: StopReason ← 结束原因│ └── timestamp: number│└── ToolResultMessage ├── role: "toolResult" ├── toolCallId: string ← 对应的ToolCall.id ├── content: Content[] ├── isError: boolean ← 执行是否失败 └── timestamp: numbermessage_update 中的实际类型:
流式响应期间,message 通常是 AssistantMessage,正在累积 content 数组。
关联二:AssistantMessageEvent 类型树
13种底层事件,每种都携带 partial: AssistantMessage(当前累积状态):
AssistantMessageEvent(13种)│├── start│ ├── type: "start"│ └── partial: AssistantMessage│├── text_delta ⭐(最常用)│ ├── type: "text_delta"│ ├── contentIndex: number ← content数组的索引│ ├── delta: string ← 增量文本│ └── partial: AssistantMessage│├── text_end│ ├── type: "text_end"│ ├── contentIndex: number│ ├── content: string ← 完整文本│ └── partial: AssistantMessage│├── toolcall_start│ ├── type: "toolcall_start"│ ├── contentIndex: number│ └── partial: AssistantMessage│├── toolcall_delta│ ├── type: "toolcall_delta"│ ├── contentIndex: number│ ├── delta: string ← JSON片段│ └── partial: AssistantMessage│├── toolcall_end ⭐(常用)│ ├── type: "toolcall_end"│ ├── contentIndex: number│ ├── toolCall: ToolCall ← 完整工具调用对象│ └── partial: AssistantMessage│├── thinking_delta│ ├── type: "thinking_delta"│ ├── contentIndex: number│ ├── delta: string ← 思考增量│ └── partial: AssistantMessage│├── done│ ├── type: "done"│ ├── reason: "stop" | "length" | "toolUse"│ └── message: AssistantMessage│└── error ⭐(错误处理) ├── type: "error" ├── reason: "aborted" | "error" ├── error: AssistantMessage └── (无partial,因为流已终止)关键理解:
contentIndex:指示正在更新content数组的哪个元素delta:增量字符串,每次新增的部分content:完整字符串,块结束时的结果partial:持续更新的累积状态(除 error 外)
类型复用关系
多个类型在不同位置共享:
| 类型 | 出现位置 | 说明 |
|---|---|---|
| AssistantMessage | message, partial, done, error | 核心消息类型,多处使用 |
| ToolCall | content[], toolcall_end.toolCall | 工具调用定义,两处共享 |
| Usage | AssistantMessage.usage | Token统计 |
| StopReason | AssistantMessage.stopReason, done.reason, error.reason | 结束原因 |
| Content[] | UserMessage, AssistantMessage, ToolResultMessage | 内容块数组 |
实际访问示例
访问高层累积状态
获取当前消息的累积内容、模型信息、token用量:
agent.subscribe((event) => { if (event.type !== "message_update") return;
const currentMessage = event.message;
if (currentMessage.role === "assistant") { console.log("累积内容块:", currentMessage.content.length); console.log("当前model:", currentMessage.model);
// 查看第一个文本块(如果已生成) if (currentMessage.content[0]?.type === "text") { console.log("文本长度:", currentMessage.content[0].text.length); } }});访问底层事件细节
根据底层事件类型分发处理:
agent.subscribe((event) => { if (event.type !== "message_update") return;
const e = event.assistantMessageEvent;
switch (e.type) { case "text_delta": // 实时文本增量 process.stdout.write(e.delta); console.log("块索引:", e.contentIndex); break;
case "toolcall_end": // 工具调用参数完整 console.log("工具:", e.toolCall.name); console.log("参数:", e.toolCall.arguments); break;
case "thinking_delta": // 思考过程(可选显示) console.log("[思考]", e.delta); break;
case "error": // 错误处理 console.log("错误:", e.reason); console.log("信息:", e.error.errorMessage); break; }});通过 partial 查看累积过程
partial 字段持续更新,可用于预览生成过程:
agent.subscribe((event) => { if (event.type !== "message_update") return;
const e = event.assistantMessageEvent;
// 文本增量时,查看已生成的完整内容 if (e.type === "text_delta") { const textBlock = e.partial.content[e.contentIndex]; if (textBlock?.type === "text") { console.log("已生成:", textBlock.text); // 包含之前的 + 新delta } }
// 工具调用增量时,查看参数累积过程 if (e.type === "toolcall_delta") { const toolBlock = e.partial.content[e.contentIndex]; if (toolBlock?.type === "toolCall") { console.log("参数累积:", toolBlock.arguments); // 不完整JSON } }});message vs partial 的区别
两者通常指向同一个对象,但有细微差别:
| 字段 | 类型 | 来源 | 说明 |
|---|---|---|---|
| message | AgentMessage | pi-agent-core | Agent层面的消息状态 |
| partial | AssistantMessage | pi-ai | API层面的累积状态 |
实际使用:
- 流式响应中,两者通常是同一个 AssistantMessage 对象
- message 是 Agent 维度的统一接口(可能是 User/Assistant/ToolResult)
- partial 仅限于 AssistantMessage,是 API 层的累积状态
推荐:需要累积状态时,优先用 e.partial,因为类型更明确。
支持与分享
如果这篇文章对你有帮助,欢迎分享给更多人或赞助支持!
message_update 事件深入
https://firefly.cuteleaf.cn/posts/learn-pi/event&message/04-message_update深入/ 相关文章 智能推荐
1
AbortController 与 terminate 设计原理
pi 深入理解两种中断机制的设计原理:AbortController的预先注册模式与terminate的返回值携带模式
2
Message 与 Tool 的时序关系
pi 理解工具调用的两阶段设计:LLM生成参数与Agent执行工具的时序边界与协作方式
3
AgentEvent 核心使用场景
pi 掌握流式输出、状态获取、工具处理、错误处理这四大核心场景,覆盖90%的开发需求
4
AgentEvent 类型系统详解
pi 深入理解 AgentEvent 的7种业务事件和 AssistantMessageEvent 的13种技术事件
5
AgentEvent 系统分层设计理念
pi 理解 pi-agent-core 和 pi-ai 的分层设计,掌握 AgentEvent 与 AssistantMessageEvent 的职责边界
随机文章 随机推荐