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: number

message_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 外)

类型复用关系#

多个类型在不同位置共享:

类型出现位置说明
AssistantMessagemessage, partial, done, error核心消息类型,多处使用
ToolCallcontent[], toolcall_end.toolCall工具调用定义,两处共享
UsageAssistantMessage.usageToken统计
StopReasonAssistantMessage.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 的区别#

两者通常指向同一个对象,但有细微差别:

字段类型来源说明
messageAgentMessagepi-agent-coreAgent层面的消息状态
partialAssistantMessagepi-aiAPI层面的累积状态

实际使用

  • 流式响应中,两者通常是同一个 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深入/
作者
AltumSisy
发布于
2026-05-27
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
AltumSisy
Hello, I'm AltumSisy.
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
站点统计
文章
32
分类
3
标签
25
总字数
68,347
运行时长
0
最后活动
0 天前

文章目录