API reference
Events
全部 We0 事件类型及其 payload 字段参考。
We0Agent.stream() 以异步迭代方式产出 We0Event。每个事件都是一个 TypedDict,必带 type 字段,按 type 取值区分形态。
事件分为三类:
| 类别 | 类型前缀 | 来源 |
|---|---|---|
| 模型流事件(LLM) | text-* / reasoning-* / tool-* / step-* / finish / provider-error | 单次模型调用的增量输出与工具交互 |
| 会话事件(Session) | session.* | engine 对整轮请求的编排、状态与重试 |
| 提问事件(Question) | question.* | agent 向外部发起的交互式提问 |
import asyncio
abort = asyncio.Event()
async for event in agent.stream(
abort=abort,
session_id=session_id,
messages=[message],
):
# 事件是 TypedDict,用 event["type"] 取类型,用键访问字段
if event["type"] == "text-delta":
print(event["text"], end="")
elif event["type"] == "tool-call":
print(f"\n调用工具 {event['name']}: {event['input']}")
elif event["type"] == "finish":
print(f"\n结束原因:{event.get('reason')}")易错点:事件是
TypedDict而非对象,必须用event["type"]、event["text"]这样的键访问,不能用属性访问(event.type)。
We0EventType 与 We0Event 的联合类型定义在 we0agent.domain.types.event,各事件结构体定义在 we0agent.domain.events 与 we0agent.question.events。
通用约定
- 标记为「否」的字段为
NotRequired,可能不存在,读取时应使用event.get(...)并处理缺省。 - 几乎所有 LLM 事件都带可选的
metadata: dict[str, Any],承载 provider 透传的附加信息。 id字段用于把同一段输出的 start / delta / end 串联起来,同一段共享相同id。- Session 与 Question 事件都带
timestamp,为毫秒级 Unix 时间戳(int)。
文本事件
模型正文输出,按 text-start → 多个 text-delta → text-end 的顺序产出,同段共享 id。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
text-start | id | str | 是 | 文本段标识 |
metadata | dict[str, Any] | 否 | 附加信息 | |
text-delta | id | str | 是 | 所属文本段标识 |
text | str | 是 | 本次增量文本 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
text-end | id | str | 是 | 文本段标识 |
metadata | dict[str, Any] | 否 | 附加信息 |
推理事件
模型推理(思维链)输出,结构与文本事件一致,仅 type 不同。是否产出取决于 provider 是否暴露推理内容。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
reasoning-start | id | str | 是 | 推理段标识 |
metadata | dict[str, Any] | 否 | 附加信息 | |
reasoning-delta | id | str | 是 | 所属推理段标识 |
text | str | 是 | 本次增量推理文本 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
reasoning-end | id | str | 是 | 推理段标识 |
metadata | dict[str, Any] | 否 | 附加信息 |
工具输入事件
模型决定调用某个工具时,先以流式方式产出工具入参,顺序为 tool-input-start → 多个 tool-input-delta → tool-input-end,同次调用共享 id 与 name。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
tool-input-start | id | str | 是 | 工具调用标识 |
name | str | 是 | 工具名 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
tool-input-delta | id | str | 是 | 工具调用标识 |
name | str | 是 | 工具名 | |
text | str | 是 | 入参增量片段(通常为 JSON 字符串分片) | |
tool-input-end | id | str | 是 | 工具调用标识 |
name | str | 是 | 工具名 | |
metadata | dict[str, Any] | 否 | 附加信息 |
注意:
tool-input-delta没有metadata字段。text是入参的增量分片,需要拼接后才是完整入参,完整入参以tool-call事件中的input为准。
工具执行事件
工具入参就绪后产出 tool-call,执行完成后产出 tool-result(成功)或 tool-error(失败)。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
tool-call | id | str | 是 | 工具调用标识 |
name | str | 是 | 工具名 | |
input | Any | 是 | 完整入参 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
tool-result | id | str | 是 | 工具调用标识 |
name | str | 是 | 工具名 | |
result | Any | 是 | 工具返回结果 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
tool-error | id | str | 是 | 工具调用标识 |
name | str | 是 | 工具名 | |
message | str | 是 | 错误信息 | |
error | Any | 否 | 原始错误对象 | |
metadata | dict[str, Any] | 否 | 附加信息 |
工具的定义与执行约定参见 AnyToolDefinition。
步骤与收口事件
一次模型调用(step)由 step-start 开始、step-finish 结束。整轮请求的所有 step 结束后产出 finish。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
step-start | index | int | 是 | step 序号(从 0 起) |
step-finish | index | int | 是 | step 序号 |
reason | NormalizedFinishReason | 是 | 本次 step 的结束原因 | |
usage | UsageMetadata | 否 | 本次 step 的 token 用量 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
finish | reason | NormalizedFinishReason | 否 | 整轮请求的结束原因 |
usage | UsageMetadata | 否 | 整轮请求的 token 用量 | |
metadata | dict[str, Any] | 否 | 附加信息 |
reason 取自 NormalizedFinishReason(对齐 OpenAI Chat Completions 语义),可能取值:
| 取值 | 说明 |
|---|---|
stop | 模型正常结束 |
tool_calls | 模型请求调用工具 |
length | 达到长度上限被截断 |
content_filter | 命中内容过滤 |
function_call | 旧式 function call 结束 |
guardrail_intervened | 护栏介入(Bedrock 特有) |
eos | 到达序列结束符 |
finish_reason_unspecified | 未指定结束原因 |
malformed_function_call | function call 格式错误(Vertex AI 特有) |
注意:
step-start与step-finish的字段是index(非id),且无metadata(step-start无任何可选字段)。finish的reason是可选的。
Provider 错误事件
模型调用过程中 provider 返回的错误。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
provider-error | message | str | 是 | 错误信息 |
error | Any | 否 | 原始错误对象 | |
code | str | 否 | 错误码 | |
status_code | int | 否 | HTTP 状态码 | |
retryable | bool | 否 | 是否可重试 | |
metadata | dict[str, Any] | 否 | 附加信息 |
会话事件
会话事件由 engine 在编排整轮请求时产出,描述 step 编排、运行状态、文件 diff、错误与重试、上下文压缩。全部携带毫秒级 timestamp。
session.step.started / session.step.ended
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
session.step.started | step_index | int | 是 | step 序号 |
agent | str | 是 | 执行该 step 的 agent 标识 | |
model_id | str | 是 | 使用的模型标识 | |
provider_id | str | 否 | provider 标识 | |
timestamp | int | 是 | 毫秒时间戳 | |
session.step.ended | step_index | int | 是 | step 序号 |
result | Literal["continue", "compact", "stop", "error"] | 是 | step 编排结果 | |
finish_reason | AssistantFinish | 否 | 助手结束原因,取值 stop / tool_calls / unknown | |
error | str | 否 | 错误信息(result 为 error 时存在) | |
timestamp | int | 是 | 毫秒时间戳 |
result 含义:continue 继续下一 step;compact 触发上下文压缩;stop 整轮结束;error 出错。
session.status
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
session.status | status | IdleStatus | BusyStatus | RetryStatus | 是 | 当前会话状态 |
timestamp | int | 是 | 毫秒时间戳 |
status 本身也是带 type 的结构体:
| status.type | 附加字段 | 说明 |
|---|---|---|
idle | 无 | 空闲 |
busy | 无 | 运行中 |
retry | attempt: int、message: str、next: int | 重试中,next 为下次重试的毫秒时间戳 |
session.diff
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
session.diff | diff | list[SessionDiffItem] | 是 | 本轮产生的文件变更列表 |
timestamp | int | 是 | 毫秒时间戳 |
SessionDiffItem 字段:
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
additions | int | 是 | 新增行数 |
deletions | int | 是 | 删除行数 |
file | str | 否 | 文件路径 |
patch | str | 否 | unified diff 文本 |
status | Literal["added", "deleted", "modified"] | 否 | 变更类型 |
文件快照与 diff 的机制参见 Snapshots。
session.error
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
session.error | message | str | 是 | 错误信息 |
code | str | 否 | 错误码 | |
status_code | int | 否 | HTTP 状态码 | |
retryable | bool | 否 | 是否可重试 | |
metadata | dict[str, Any] | 否 | 附加信息 | |
timestamp | int | 是 | 毫秒时间戳 |
session.retried
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
session.retried | attempt | int | 是 | 当前重试次数 |
message | str | 是 | 触发重试的信息 | |
next_retry_at | int | 是 | 下次重试的毫秒时间戳 | |
timestamp | int | 是 | 毫秒时间戳 |
session.compaction.started / session.compaction.ended
上下文压缩的开始与结束事件。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
session.compaction.started | trigger | str | 是 | 触发来源 |
overflow | bool | 是 | 是否因上下文溢出触发 | |
agent | str | 是 | 触发压缩的 agent 标识 | |
timestamp | int | 是 | 毫秒时间戳 | |
session.compaction.ended | trigger | str | 是 | 触发来源 |
overflow | bool | 是 | 是否因上下文溢出触发 | |
agent | str | 是 | 触发压缩的 agent 标识 | |
compacted | bool | 是 | 是否实际执行了压缩 | |
error | str | 否 | 错误信息(压缩失败时存在) | |
timestamp | int | 是 | 毫秒时间戳 |
提问事件
agent 向外部发起交互式提问时产出,全部携带毫秒级 timestamp 与 session_id。
| type | 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|---|
question.asked | request_id | QuestionID | 是 | 提问请求标识 |
session_id | str | 是 | 所属会话标识 | |
payload | JsonValue | 是 | 提问内容(深拷贝) | |
timestamp | int | 是 | 毫秒时间戳 | |
question.replied | session_id | str | 是 | 所属会话标识 |
request_id | QuestionID | 是 | 提问请求标识 | |
answers | JsonValue | 是 | 回复内容(深拷贝) | |
timestamp | int | 是 | 毫秒时间戳 | |
question.rejected | session_id | str | 是 | 所属会话标识 |
request_id | QuestionID | 是 | 提问请求标识 | |
timestamp | int | 是 | 毫秒时间戳 |
注意:
question.asked的字段顺序为request_id、session_id,而question.replied/question.rejected为session_id、request_id。字段名一致,访问时不受顺序影响。
事件发布端口
除直接消费 stream() 产出的事件外,还可以在构造 We0Agent 时通过 event_publishers 注入外部发布端口。端口需继承 We0EventPublisher 抽象基类:
from we0agent.domain.types.event import We0Event
from we0agent.protocols.events import We0EventPublisher
class LoggingPublisher(We0EventPublisher):
async def publish(self, *, session_id: str, event: We0Event) -> None:
# 将每个 We0 事件转发到外部系统(日志、消息队列、WebSocket 等)
print(session_id, event["type"])We0EventPublisher 是事件发布端口基类。注入 event_publishers 的对象应显式继承它,并实现 async publish(*, session_id, event)。