diff --git a/docs/en/docs/ai/chat/conversation.md b/docs/en/docs/ai/chat/conversation.md index 4c9c8407..03cc25d9 100644 --- a/docs/en/docs/ai/chat/conversation.md +++ b/docs/en/docs/ai/chat/conversation.md @@ -142,15 +142,17 @@ In streaming mode, the server keeps pushing run progress as `event: message` eve ``` event: message -data: {"event":"chat_started","workflow_run_id":"wr_...","data":{"chat_uid":"ct_9f2c1a5b","message_id":42}} +data: {"event":"chat_started","workflow_run_id":"745910371102313","data":{"chat_uid":"ct_9f2c1a5b","message_id":42}} event: message -data: {"event":"message","workflow_run_id":"wr_...","data":{"text":"Tesla"}} +data: {"event":"message","workflow_run_id":"745910371102313","data":{"text":"Tesla"}} event: message -data: {"event":"workflow_finished","workflow_run_id":"wr_...","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"..."}}} +data: {"event":"workflow_finished","workflow_run_id":"745910371102313","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"..."}}} ``` +See [SSE Events](/docs/ai/chat/events) for the full list of event types, their payload structures, and parsing guidance. + ### Response Status | Status | Description | Schema | diff --git a/docs/en/docs/ai/chat/events.md b/docs/en/docs/ai/chat/events.md new file mode 100644 index 00000000..22d71d14 --- /dev/null +++ b/docs/en/docs/ai/chat/events.md @@ -0,0 +1,404 @@ +--- +slug: events +title: SSE Events +sidebar_position: 4 +language_tabs: false +toc_footers: [] +includes: [] +search: true +highlight_theme: '' +headingLevel: 2 +--- + +In streaming mode (`Accept: text/event-stream`), [Start Conversation](/docs/ai/chat/conversation) and [Continue Conversation](/docs/ai/chat/continue) push the run progress as a sequence of SSE events. This page lists every event type and how to parse it. + +## Frame Format + +Every SSE frame uses the same envelope: the SSE `event` field is always `message`, and the `data` field is a JSON object: + +``` +event: message +data: {"event":"","workflow_run_id":"745910371102313","data":{...}} +``` + +| Name | Type | Description | +| --------------- | ------ | ------------------------------------------------------------------ | +| event | string | Event type. Dispatch on this field | +| workflow_run_id | string | ID of this run, a numeric ID in string form (e.g. `"745910371102313"`); identical across all events of the same run | +| data | object | Event payload; structure varies by event type (see below) | + +Parsing rules: + +- **Dispatch on `data.event`**, not on the SSE `event` field (which is always `message`). +- **Ignore unknown event types.** New event types may be added at any time; a client that only handles the events it knows stays forward compatible. +- Unless noted otherwise, `started_at` / `finished_at` are Unix timestamps in seconds, and `elapsed_time` is a duration in seconds. + +## Typical Event Sequences + +A run always begins with `chat_started` and ends with `chat_finished`. What happens in between depends on the outcome: + +**Succeeded:** + +``` +chat_started → workflow_started → thinking_started → message (type=think) ... +→ node_tool_use_started / node_tool_use_finished ... +→ thinking_finished → message (type=answer) ... +→ workflow_finished (status=succeeded) → chat_finished +``` + +**Interrupted** (the Agent needs your input; resume via [Continue Conversation](/docs/ai/chat/continue)): + +``` +chat_started → workflow_started → ... → human_interaction_required → chat_finished +``` + +Note: an interrupted run does **not** emit `workflow_finished`. When you continue an interrupted run, the resumed stream does **not** emit `workflow_started` again. + +**Failed:** + +``` +chat_started → workflow_started → ... → workflow_finished (status=failed) → chat_finished +``` + +## Minimal Client + +For a plain question-and-answer integration you only need to handle four events; everything else is optional progress display: + +| Event | What to do | +| ---------------------------- | ------------------------------------------------------------------- | +| `message` (`type=answer`) | Append `data.text` to the answer being displayed | +| `human_interaction_required` | Show the questions and call Continue Conversation with the answers | +| `workflow_finished` | Read the final `status` and `outputs.answer`; show errors if failed | +| `chat_finished` | Close the stream; the run is over | + +## Conversation Lifecycle + +### chat_started + +The first event of every stream. The conversation and message records have been created; save `chat_uid` (for follow-up questions) and `message_id` (for continuing after an interrupt). + +| Name | Type | Description | +| ---------- | ------ | ---------------------------------------------- | +| chat_id | int64 | Internal ID of the conversation | +| chat_uid | string | Conversation identifier, used in follow-up requests | +| message_id | int64 | Message ID of this round | + +```json +{"event":"chat_started","workflow_run_id":"745910371102313","data":{"chat_id":1001,"chat_uid":"ct_9f2c1a5b","message_id":42}} +``` + +### chat_finished + +The last event of every stream. After this the server closes the connection. + +| Name | Type | Description | +| ------------- | ------ | ----------------------------------------------- | +| chat_id | int64 | Internal ID of the conversation | +| chat_uid | string | Conversation identifier | +| message_id | int64 | Message ID of this round | +| error | string | Error detail; empty on success | +| error_message | string | User-facing error message; empty on success | + +## Run Lifecycle + +### workflow_started + +The Agent run has started. Not emitted when resuming an interrupted run via Continue Conversation. + +| Name | Type | Description | +| ----------- | ------ | ------------------------------------------------------ | +| workflow_id | int64 | ID of the workflow backing this Agent | +| started_at | int64 | Start time (Unix seconds) | +| inputs | object | Run inputs | +| hit_cache | bool | `true` if the answer is served from cache; the stream then goes straight to the answer | + +### workflow_finished + +The run has ended — successfully, with a failure, or stopped by the user. Read the final result here. + +| Name | Type | Description | +| ------------- | -------- | ------------------------------------------------------------------------ | +| status | string | `succeeded` / `failed` / `stopped` | +| outputs | object | Run outputs; `outputs.answer` is the complete final answer text | +| elapsed_time | number | Run duration in seconds | +| error | string | Localized error description; only when `status` is `failed` | +| error_code | int32 | Error code; only when `status` is `failed` | +| error_message | string | User-facing error message; only on failure | +| error_args | object | Extra error context (e.g. `workflow_run_id`); may be omitted | +| process_data | object[] | Process stages the run went through; for display only | + +```json +{"event":"workflow_finished","workflow_run_id":"745910371102313","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"Tesla (TSLA.US) recently..."}}} +``` + +Notes: + +- `outputs.answer` is the authoritative full answer. If you assembled the answer from `message` events, you can use this to verify or replace it. +- When `status` is `stopped` (run stopped by the user), `outputs.answer` contains the partial answer generated so far. + +## Answer Streaming + +### message + +Incremental text chunks. This is the highest-frequency event; concatenate `text` fragments in arrival order. + +| Name | Type | Description | +| -------------------- | ------ | --------------------------------------------------------------------------- | +| text | string | Incremental text fragment | +| type | string | `answer` — final answer text; `think` — reasoning process; `process` — stage progress description | +| key | string | Identifier of the stream segment the fragment belongs to. Fragments with the same `key` form one continuous block — group by `key` when rendering | +| started_at | int64 | Time this segment started (Unix seconds) | +| stage | string | Stage identifier; only for `type=process` | +| stage_title | string | Stage title while running; only for `type=process` | +| stage_finished_title | string | Stage title after it finishes; only for `type=process` | +| outputs | object | Extra payload attached to the fragment; usually absent | + +```json +{"event":"message","workflow_run_id":"745910371102313","data":{"text":"Tesla","type":"answer","key":"n_llm_1:answer","started_at":1752048000}} +``` + +Parsing: + +- Only `type=answer` fragments belong to the user-visible answer. Concatenating all of them yields the same text as `workflow_finished.outputs.answer`. +- `type=think` fragments are the Agent's intermediate reasoning — show them in a collapsible "thinking" section or ignore them. +- `type=process` fragments describe stage progress and come with `stage` fields for grouping. + +## Thinking Phase + +### thinking_started + +The Agent has entered the reasoning phase (analyzing the question, planning tool calls). Between this and `thinking_finished`, `message` events with `type=think` and tool-call events may arrive. + +| Name | Type | Description | +| ---------- | ----- | ------------------------- | +| started_at | int64 | Start time (Unix seconds) | + +### thinking_finished + +The reasoning phase is over; answer text (`message` with `type=answer`) follows. + +| Name | Type | Description | +| ------------ | ----- | ----------------------------- | +| finished_at | int64 | Finish time (Unix seconds) | +| elapsed_time | int32 | Reasoning duration in seconds | + +## Tool Calls + +The Agent calls tools (market data, account info, web search, …) while generating the answer. Each call is bracketed by a started/finished pair — match them by `tool_use_id`. + +This pair covers **all ordinary tool calls**. Only two special cases are reported with their own event families instead: spawning a subagent (`subagent_*`, see below) and calling another Agent as a tool (`agent_tool_*`, see below). If your Agent uses neither feature, every tool call arrives as `node_tool_use_started` / `node_tool_use_finished`. + +### node_tool_use_started + +A tool call has started. + +| Name | Type | Description | +| -------------- | -------- | ------------------------------------------------------------------------------ | +| tool_use_id | string | Unique ID of this call; use it to match the finished event | +| tool_name | string | Localized display name of the tool (e.g. shown in your UI) | +| tool_func_name | string | Locale-stable tool identifier; use this for logic keyed on the tool kind | +| tool_args | string | Call arguments as a JSON string | +| tips | string | Progress text suitable for direct display (e.g. "Searching the web…") | +| tip_chips | string[] | Short tags accompanying `tips`; may be omitted | +| iteration | int | Round number. Calls in the same round (same `iteration`) run in parallel | +| started_at | int64 | Start time (Unix seconds) | + +### node_tool_use_finished + +The tool call has ended. + +| Name | Type | Description | +| -------------- | -------- | ---------------------------------------------------------------------- | +| tool_use_id | string | Matches the `tool_use_id` of the started event | +| status | string | `succeeded` / `failed` | +| error | string | Error description on failure | +| elapsed_time | number | Call duration in seconds | +| started_at | int64 | Start time (Unix seconds) | +| tool_name | string | Localized display name | +| tool_func_name | string | Locale-stable tool identifier | +| tool_args | string | Call arguments as a JSON string | +| tool_type | string | Tool category | +| tips | string | Progress text | +| tip_chips | string[] | Short tags; may be omitted | +| iteration | int | Round number | +| is_thinking | bool | `true` if the call happened during the thinking phase | +| outputs | object | Filtered call results, see below | + +`outputs` only carries fields that are meant for display: + +| Field | Description | +| ------------------------- | ----------------------------------------------------------------- | +| outputs.references | Sources referenced by the tool result | +| outputs.reference_domains | Domains of the referenced sources | +| outputs.query | The query the tool executed | +| outputs.text | Raw response text of the tool | +| outputs.tool_args | Parsed request arguments | +| outputs.data | Structured result; present only for selected tools | + +```json +{"event":"node_tool_use_finished","workflow_run_id":"745910371102313","data":{"tool_use_id":"call_abc123","status":"succeeded","elapsed_time":1.42,"tool_name":"Web Search","tool_func_name":"web_search","tool_args":"{\"query\":\"TSLA stock news\"}","tool_type":"builtin","tips":"Searched the web","iteration":1,"is_thinking":true,"outputs":{"query":"TSLA stock news","references":[{"index":1,"title":"...","url":"..."}]}}} +``` + +## Subagent Events + +When the Agent spawns a subagent to work on a sub-task, the subagent's lifecycle is reported with a dedicated event family instead of `node_tool_use_*`. + +### subagent_started + +| Name | Type | Description | +| ----------- | ------ | ----------------------------------------------- | +| node_id | string | ID of the node that spawned the subagent | +| tool_use_id | string | Unique ID of this spawn; matches the finished event | +| started_at | int64 | Start time (Unix seconds) | +| goal | string | Goal assigned to the subagent | +| prompt | string | Full task prompt given to the subagent | +| subagent_id | string | Subagent identifier; may be omitted | +| tools | array | Tools granted to the subagent; may be omitted | + +### subagent_progress + +Emitted every time the subagent calls one of its own tools. Use it to render a live timeline inside the subagent card. + +| Name | Type | Description | +| -------------------- | ------ | ------------------------------------------------------- | +| node_id | string | ID of the node that spawned the subagent | +| parent_tool_call_id | string | `tool_use_id` of the owning `subagent_started` event | +| subagent_tool_name | string | Name of the tool the subagent called | +| subagent_tool_args | string | Arguments of that call (JSON string) | +| subagent_status | string | Status of that call: `running` / `succeeded` / `failed` | +| subagent_duration_ms | int64 | Duration of that call in **milliseconds** | +| subagent_iteration | int | The subagent's internal round number | +| started_at | int64 | Start time (Unix seconds) | + +### subagent_finished + +| Name | Type | Description | +| ------------ | ------ | -------------------------------------------------------------------- | +| node_id | string | ID of the node that spawned the subagent | +| tool_use_id | string | Matches the `tool_use_id` of `subagent_started` | +| status | string | `succeeded` / `failed` | +| started_at | int64 | Start time (Unix seconds) | +| elapsed_time | number | Total subagent duration in seconds | +| error | string | Error description on failure | +| outputs | object | Subagent result: typically `goal`, `result`, and `subagent_tools` (the timeline of tool calls it made) | + +## Agent Tool Events + +When the Agent delegates to another Agent as a tool, that inner run is reported with the `agent_tool_*` family. The shape mirrors the subagent events. + +### agent_tool_started + +| Name | Type | Description | +| --------------- | -------- | -------------------------------------------------- | +| node_id | string | ID of the calling node | +| tool_use_id | string | Unique ID of this call; matches the finished event | +| agent_tool_name | string | Identifier of the Agent being called | +| title | string | Display title; may be omitted | +| started_at | int64 | Start time (Unix seconds) | +| tool_args | string | Call arguments (JSON string) | +| tool_name | string | Localized display name | +| tips | string | Progress text; may be omitted | +| tip_chips | string[] | Short tags; may be omitted | +| is_thinking | bool | `true` if called during the thinking phase | + +### agent_tool_progress + +Emitted for each inner tool call the delegated Agent makes. + +| Name | Type | Description | +| ------------------- | ------ | -------------------------------------------------------- | +| node_id | string | ID of the calling node | +| parent_tool_call_id | string | `tool_use_id` of the owning `agent_tool_started` event | +| agent_tool_name | string | Identifier of the Agent being called | +| inner_tool_name | string | Name of the inner tool the delegated Agent called | +| inner_tool_args | string | Arguments of that inner call (JSON string) | +| status | string | Status of the inner call: `running` / `succeeded` / `failed` | +| duration_ms | int64 | Duration of the inner call in **milliseconds** | +| started_at | int64 | Start time (Unix seconds) | +| is_thinking | bool | `true` if during the thinking phase | + +### agent_tool_finished + +| Name | Type | Description | +| --------------- | -------- | ------------------------------------------------- | +| node_id | string | ID of the calling node | +| tool_use_id | string | Matches the `tool_use_id` of `agent_tool_started` | +| agent_tool_name | string | Identifier of the Agent being called | +| status | string | `succeeded` / `failed` | +| started_at | int64 | Start time (Unix seconds) | +| elapsed_time | number | Total duration in seconds | +| error | string | Error description on failure | +| tool_args | string | Call arguments (JSON string) | +| outputs | object | Result of the delegated Agent | +| tool_type | string | Tool category | +| tips | string | Progress text; may be omitted | +| tip_chips | string[] | Short tags; may be omitted | +| is_thinking | bool | `true` if during the thinking phase | + +## Interrupt + +### human_interaction_required + +The run is paused: the Agent needs more information or confirmation from you. Collect answers to `questions` and call [Continue Conversation](/docs/ai/chat/continue) — the answers are keyed by `tool_call_id`. + +| Name | Type | Description | +| --------------- | -------- | ------------------------------------------------------------------ | +| node_id | string | ID of the node that triggered the interrupt | +| tool_call_id | string | ID of this inquiry; the outer key of `answers_by_tool_call` when continuing | +| questions | object[] | Questions you need to answer | +| ∟ question | string | Question text; the inner key of `answers_by_tool_call` | +| ∟ options | object[] | Options; empty means free-form answer | +| ∟∟ description | string | Option text | +| ∟ multi_select | boolean | Whether multiple options may be selected | +| message_id | int64 | ID of the paused message; used in the Continue Conversation URL | +| chat_id | int64 | ID of the owning conversation | + +```json +{"event":"human_interaction_required","workflow_run_id":"745910371102313","data":{"node_id":"n_ask_human","tool_call_id":"call_abc123","questions":[{"question":"Which time range would you like to check?","options":[{"description":"Past week"},{"description":"Past month"}],"multi_select":false}],"message_id":43,"chat_id":1001}} +``` + +After this event the stream ends with `chat_finished`; an interrupted run does not emit `workflow_finished`. + +## Auxiliary Events + +These events are informational; a minimal client can ignore all of them. + +### query_masked + +Sensitive content in the user query was masked before processing. Display `masked_query` instead of the original query. + +| Name | Type | Description | +| ------------ | ------ | ----------------------- | +| raw_query | string | The original user query | +| masked_query | string | The masked query | + +### plan_changed + +The Agent created or updated its task plan. + +| Name | Type | Description | +| ---------- | ------ | ---------------------------------------- | +| node_id | string | ID of the planning node | +| started_at | int64 | Time of the change (Unix seconds) | +| outputs | object | The current plan content | + +This event additionally carries a top-level `tool_name` field (sibling of `data`) identifying the planning tool. + +### context_compress_started / context_compress_finished + +Long conversations trigger context compression; these events bracket the compression. Unlike other events, the timestamps here are RFC 3339 strings. + +`context_compress_started`: + +| Name | Type | Description | +| ---------- | ------ | ------------------------------- | +| started_at | string | Start time (RFC 3339) | +| inputs | object | Compression input summary | + +`context_compress_finished`: + +| Name | Type | Description | +| ---------- | ------ | ------------------------------- | +| created_at | string | Finish time (RFC 3339) | +| inputs | object | Compression input summary | +| outputs | object | Compression result summary | diff --git a/docs/zh-CN/docs/ai/chat/conversation.md b/docs/zh-CN/docs/ai/chat/conversation.md index 1a06a96b..5e0d8732 100644 --- a/docs/zh-CN/docs/ai/chat/conversation.md +++ b/docs/zh-CN/docs/ai/chat/conversation.md @@ -142,15 +142,17 @@ curl -N -X POST "https://openapi.longbridge.com/v1/ai/agents/123/conversations" ``` event: message -data: {"event":"chat_started","workflow_run_id":"wr_...","data":{"chat_uid":"ct_9f2c1a5b","message_id":42}} +data: {"event":"chat_started","workflow_run_id":"745910371102313","data":{"chat_uid":"ct_9f2c1a5b","message_id":42}} event: message -data: {"event":"message","workflow_run_id":"wr_...","data":{"text":"特斯拉"}} +data: {"event":"message","workflow_run_id":"745910371102313","data":{"text":"特斯拉"}} event: message -data: {"event":"workflow_finished","workflow_run_id":"wr_...","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"..."}}} +data: {"event":"workflow_finished","workflow_run_id":"745910371102313","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"..."}}} ``` +完整的事件类型列表、负载结构与解析方式见 [SSE 事件](/zh-CN/docs/ai/chat/events)。 + ### Response Status | Status | Description | Schema | diff --git a/docs/zh-CN/docs/ai/chat/events.md b/docs/zh-CN/docs/ai/chat/events.md new file mode 100644 index 00000000..2d58dc0e --- /dev/null +++ b/docs/zh-CN/docs/ai/chat/events.md @@ -0,0 +1,404 @@ +--- +slug: events +title: SSE 事件 +sidebar_position: 4 +language_tabs: false +toc_footers: [] +includes: [] +search: true +highlight_theme: '' +headingLevel: 2 +--- + +流式模式(`Accept: text/event-stream`)下,[发起对话](/zh-CN/docs/ai/chat/conversation)和[继续对话](/zh-CN/docs/ai/chat/continue)会以一系列 SSE 事件推送运行过程。本页列出所有事件类型及解析方式。 + +## 帧格式 + +每一帧 SSE 都使用同样的信封结构:SSE 的 `event` 字段恒为 `message`,`data` 字段是一个 JSON 对象: + +``` +event: message +data: {"event":"","workflow_run_id":"745910371102313","data":{...}} +``` + +| 名称 | 类型 | 说明 | +| --------------- | ------ | ------------------------------------------------ | +| event | string | 事件类型,按此字段分发处理 | +| workflow_run_id | string | 本次运行的 ID,为数字 ID 的字符串形式(如 `"745910371102313"`),同一次运行的所有事件中该值一致 | +| data | object | 事件负载,结构随事件类型而不同(见下文) | + +解析规则: + +- **按 `data.event` 分发**,而不是 SSE 的 `event` 字段(它恒为 `message`)。 +- **忽略未知事件类型。** 事件类型可能随时新增,只处理已知事件的客户端可保持向前兼容。 +- 除特别说明外,`started_at` / `finished_at` 为 Unix 秒级时间戳,`elapsed_time` 为秒数。 + +## 典型事件序列 + +一次运行始于 `chat_started`、止于 `chat_finished`,中间的事件取决于运行结果: + +**成功:** + +``` +chat_started → workflow_started → thinking_started → message (type=think) ... +→ node_tool_use_started / node_tool_use_finished ... +→ thinking_finished → message (type=answer) ... +→ workflow_finished (status=succeeded) → chat_finished +``` + +**中断**(Agent 需要你补充信息,通过[继续对话](/zh-CN/docs/ai/chat/continue)恢复): + +``` +chat_started → workflow_started → ... → human_interaction_required → chat_finished +``` + +注意:中断的运行**不会**发送 `workflow_finished`;继续被中断的运行时,恢复后的流**不会**再次发送 `workflow_started`。 + +**失败:** + +``` +chat_started → workflow_started → ... → workflow_finished (status=failed) → chat_finished +``` + +## 最简客户端 + +纯问答场景只需处理四种事件,其余事件都是可选的过程展示: + +| 事件 | 处理方式 | +| ---------------------------- | ------------------------------------------------------ | +| `message`(`type=answer`) | 将 `data.text` 追加到正在展示的回答中 | +| `human_interaction_required` | 展示问题,携带答案调用继续对话接口 | +| `workflow_finished` | 读取最终 `status` 和 `outputs.answer`;失败时展示错误 | +| `chat_finished` | 关闭流,本次运行结束 | + +## 会话生命周期 + +### chat_started + +每个流的第一个事件。会话和消息记录已创建;保存 `chat_uid`(用于追问)和 `message_id`(用于中断后继续)。 + +| 名称 | 类型 | 说明 | +| ---------- | ------ | -------------------------- | +| chat_id | int64 | 会话内部 ID | +| chat_uid | string | 会话标识,用于后续请求 | +| message_id | int64 | 本轮消息 ID | + +```json +{"event":"chat_started","workflow_run_id":"745910371102313","data":{"chat_id":1001,"chat_uid":"ct_9f2c1a5b","message_id":42}} +``` + +### chat_finished + +每个流的最后一个事件,之后服务端关闭连接。 + +| 名称 | 类型 | 说明 | +| ------------- | ------ | ------------------------------ | +| chat_id | int64 | 会话内部 ID | +| chat_uid | string | 会话标识 | +| message_id | int64 | 本轮消息 ID | +| error | string | 错误详情,成功时为空 | +| error_message | string | 面向用户的错误信息,成功时为空 | + +## 运行生命周期 + +### workflow_started + +Agent 运行已开始。通过继续对话恢复被中断的运行时不会发送此事件。 + +| 名称 | 类型 | 说明 | +| ----------- | ------ | ------------------------------------------------------ | +| workflow_id | int64 | 该 Agent 底层工作流的 ID | +| started_at | int64 | 开始时间(Unix 秒) | +| inputs | object | 运行输入 | +| hit_cache | bool | 为 `true` 时表示答案命中缓存,流会直接进入回答阶段 | + +### workflow_finished + +运行已结束——成功、失败或被用户停止。在此读取最终结果。 + +| 名称 | 类型 | 说明 | +| ------------- | -------- | ---------------------------------------------------------- | +| status | string | `succeeded` / `failed` / `stopped` | +| outputs | object | 运行输出;`outputs.answer` 为完整的最终回答文本 | +| elapsed_time | number | 运行耗时(秒) | +| error | string | 本地化的错误描述,仅 `status` 为 `failed` 时存在 | +| error_code | int32 | 错误码,仅 `status` 为 `failed` 时存在 | +| error_message | string | 面向用户的错误信息,仅失败时存在 | +| error_args | object | 额外错误上下文(如 `workflow_run_id`),可能省略 | +| process_data | object[] | 运行经过的过程阶段,仅用于展示 | + +```json +{"event":"workflow_finished","workflow_run_id":"745910371102313","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"特斯拉(TSLA.US)近期..."}}} +``` + +说明: + +- `outputs.answer` 是权威的完整回答。如果你通过 `message` 事件拼接了回答,可用它校验或替换。 +- `status` 为 `stopped`(用户停止运行)时,`outputs.answer` 为已生成的部分回答。 + +## 回答流式输出 + +### message + +增量文本片段。这是频率最高的事件,按到达顺序拼接 `text` 即可。 + +| 名称 | 类型 | 说明 | +| -------------------- | ------ | ------------------------------------------------------------------------ | +| text | string | 增量文本片段 | +| type | string | `answer` — 最终回答文本;`think` — 推理过程;`process` — 阶段进度描述 | +| key | string | 片段所属流段的标识。相同 `key` 的片段构成一个连续块,渲染时按 `key` 分组 | +| started_at | int64 | 该流段开始时间(Unix 秒) | +| stage | string | 阶段标识,仅 `type=process` 时存在 | +| stage_title | string | 阶段进行中的标题,仅 `type=process` 时存在 | +| stage_finished_title | string | 阶段完成后的标题,仅 `type=process` 时存在 | +| outputs | object | 附加在片段上的额外负载,通常不存在 | + +```json +{"event":"message","workflow_run_id":"745910371102313","data":{"text":"特斯拉","type":"answer","key":"n_llm_1:answer","started_at":1752048000}} +``` + +解析: + +- 只有 `type=answer` 的片段属于用户可见的回答,全部拼接后与 `workflow_finished.outputs.answer` 一致。 +- `type=think` 的片段是 Agent 的中间推理,可放入可折叠的「思考」区域展示,也可忽略。 +- `type=process` 的片段描述阶段进度,附带 `stage` 系列字段用于分组。 + +## 思考阶段 + +### thinking_started + +Agent 进入推理阶段(分析问题、规划工具调用)。在它与 `thinking_finished` 之间可能出现 `type=think` 的 `message` 事件和工具调用事件。 + +| 名称 | 类型 | 说明 | +| ---------- | ----- | -------------------- | +| started_at | int64 | 开始时间(Unix 秒) | + +### thinking_finished + +推理阶段结束,随后是回答文本(`type=answer` 的 `message`)。 + +| 名称 | 类型 | 说明 | +| ------------ | ----- | -------------------- | +| finished_at | int64 | 结束时间(Unix 秒) | +| elapsed_time | int32 | 推理耗时(秒) | + +## 工具调用 + +Agent 在生成回答的过程中会调用工具(行情、账户、联网搜索等)。每次调用都由一对 started/finished 事件包裹——用 `tool_use_id` 配对。 + +这对事件覆盖**所有普通工具调用**。只有两种特殊调用改用各自的事件族上报:派生子智能体(`subagent_*`,见下文)和把另一个 Agent 作为工具调用(`agent_tool_*`,见下文)。如果你的 Agent 没有使用这两项能力,所有工具调用都只会以 `node_tool_use_started` / `node_tool_use_finished` 出现。 + +### node_tool_use_started + +一次工具调用已开始。 + +| 名称 | 类型 | 说明 | +| -------------- | -------- | --------------------------------------------------------------- | +| tool_use_id | string | 本次调用的唯一 ID,用于与 finished 事件配对 | +| tool_name | string | 工具的本地化展示名(用于界面显示) | +| tool_func_name | string | 与语言无关的稳定工具标识,按工具类型处理逻辑时用它 | +| tool_args | string | 调用参数(JSON 字符串) | +| tips | string | 可直接展示的进度文案(如「正在联网搜索…」) | +| tip_chips | string[] | 与 `tips` 配套的短标签,可能省略 | +| iteration | int | 轮次编号。同一轮(相同 `iteration`)的调用是并行执行的 | +| started_at | int64 | 开始时间(Unix 秒) | + +### node_tool_use_finished + +工具调用已结束。 + +| 名称 | 类型 | 说明 | +| -------------- | -------- | ---------------------------------------- | +| tool_use_id | string | 与 started 事件的 `tool_use_id` 一致 | +| status | string | `succeeded` / `failed` | +| error | string | 失败时的错误描述 | +| elapsed_time | number | 调用耗时(秒) | +| started_at | int64 | 开始时间(Unix 秒) | +| tool_name | string | 本地化展示名 | +| tool_func_name | string | 稳定工具标识 | +| tool_args | string | 调用参数(JSON 字符串) | +| tool_type | string | 工具类别 | +| tips | string | 进度文案 | +| tip_chips | string[] | 短标签,可能省略 | +| iteration | int | 轮次编号 | +| is_thinking | bool | 为 `true` 表示调用发生在思考阶段 | +| outputs | object | 过滤后的调用结果,见下 | + +`outputs` 只携带用于展示的字段: + +| 字段 | 说明 | +| ------------------------- | -------------------------------- | +| outputs.references | 工具结果引用的来源 | +| outputs.reference_domains | 引用来源的域名 | +| outputs.query | 工具执行的查询 | +| outputs.text | 工具的原始响应文本 | +| outputs.tool_args | 解析后的请求参数 | +| outputs.data | 结构化结果,仅部分工具存在 | + +```json +{"event":"node_tool_use_finished","workflow_run_id":"745910371102313","data":{"tool_use_id":"call_abc123","status":"succeeded","elapsed_time":1.42,"tool_name":"联网搜索","tool_func_name":"web_search","tool_args":"{\"query\":\"TSLA stock news\"}","tool_type":"builtin","tips":"已联网搜索","iteration":1,"is_thinking":true,"outputs":{"query":"TSLA stock news","references":[{"index":1,"title":"...","url":"..."}]}}} +``` + +## 子智能体事件 + +Agent 派生子智能体处理子任务时,其生命周期使用独立的事件族上报,而不是 `node_tool_use_*`。 + +### subagent_started + +| 名称 | 类型 | 说明 | +| ----------- | ------ | ------------------------------------------ | +| node_id | string | 派生子智能体的节点 ID | +| tool_use_id | string | 本次派生的唯一 ID,与 finished 事件配对 | +| started_at | int64 | 开始时间(Unix 秒) | +| goal | string | 分配给子智能体的目标 | +| prompt | string | 交给子智能体的完整任务提示词 | +| subagent_id | string | 子智能体标识,可能省略 | +| tools | array | 授予子智能体的工具列表,可能省略 | + +### subagent_progress + +子智能体每调用一次自己的工具就发送一次,用于在子智能体卡片内实时渲染时间线。 + +| 名称 | 类型 | 说明 | +| -------------------- | ------ | ------------------------------------------------ | +| node_id | string | 派生子智能体的节点 ID | +| parent_tool_call_id | string | 所属 `subagent_started` 事件的 `tool_use_id` | +| subagent_tool_name | string | 子智能体调用的工具名 | +| subagent_tool_args | string | 该调用的参数(JSON 字符串) | +| subagent_status | string | 该调用的状态:`running` / `succeeded` / `failed` | +| subagent_duration_ms | int64 | 该调用耗时(**毫秒**) | +| subagent_iteration | int | 子智能体内部的轮次编号 | +| started_at | int64 | 开始时间(Unix 秒) | + +### subagent_finished + +| 名称 | 类型 | 说明 | +| ------------ | ------ | ------------------------------------------------------------------------ | +| node_id | string | 派生子智能体的节点 ID | +| tool_use_id | string | 与 `subagent_started` 的 `tool_use_id` 一致 | +| status | string | `succeeded` / `failed` | +| started_at | int64 | 开始时间(Unix 秒) | +| elapsed_time | number | 子智能体总耗时(秒) | +| error | string | 失败时的错误描述 | +| outputs | object | 子智能体结果:通常包含 `goal`、`result` 和 `subagent_tools`(其工具调用时间线) | + +## Agent 工具事件 + +Agent 把另一个 Agent 作为工具调用时,该内部运行使用 `agent_tool_*` 事件族上报,结构与子智能体事件相似。 + +### agent_tool_started + +| 名称 | 类型 | 说明 | +| --------------- | -------- | --------------------------------------- | +| node_id | string | 调用方节点 ID | +| tool_use_id | string | 本次调用的唯一 ID,与 finished 事件配对 | +| agent_tool_name | string | 被调用 Agent 的标识 | +| title | string | 展示标题,可能省略 | +| started_at | int64 | 开始时间(Unix 秒) | +| tool_args | string | 调用参数(JSON 字符串) | +| tool_name | string | 本地化展示名 | +| tips | string | 进度文案,可能省略 | +| tip_chips | string[] | 短标签,可能省略 | +| is_thinking | bool | 为 `true` 表示发生在思考阶段 | + +### agent_tool_progress + +被委托 Agent 每进行一次内部工具调用就发送一次。 + +| 名称 | 类型 | 说明 | +| ------------------- | ------ | ---------------------------------------------------- | +| node_id | string | 调用方节点 ID | +| parent_tool_call_id | string | 所属 `agent_tool_started` 事件的 `tool_use_id` | +| agent_tool_name | string | 被调用 Agent 的标识 | +| inner_tool_name | string | 被委托 Agent 调用的内部工具名 | +| inner_tool_args | string | 该内部调用的参数(JSON 字符串) | +| status | string | 内部调用的状态:`running` / `succeeded` / `failed` | +| duration_ms | int64 | 内部调用耗时(**毫秒**) | +| started_at | int64 | 开始时间(Unix 秒) | +| is_thinking | bool | 为 `true` 表示发生在思考阶段 | + +### agent_tool_finished + +| 名称 | 类型 | 说明 | +| --------------- | -------- | --------------------------------------------- | +| node_id | string | 调用方节点 ID | +| tool_use_id | string | 与 `agent_tool_started` 的 `tool_use_id` 一致 | +| agent_tool_name | string | 被调用 Agent 的标识 | +| status | string | `succeeded` / `failed` | +| started_at | int64 | 开始时间(Unix 秒) | +| elapsed_time | number | 总耗时(秒) | +| error | string | 失败时的错误描述 | +| tool_args | string | 调用参数(JSON 字符串) | +| outputs | object | 被委托 Agent 的结果 | +| tool_type | string | 工具类别 | +| tips | string | 进度文案,可能省略 | +| tip_chips | string[] | 短标签,可能省略 | +| is_thinking | bool | 为 `true` 表示发生在思考阶段 | + +## 中断 + +### human_interaction_required + +运行已暂停:Agent 需要你补充信息或确认。收集 `questions` 的答案后调用[继续对话](/zh-CN/docs/ai/chat/continue)——答案以 `tool_call_id` 为键。 + +| 名称 | 类型 | 说明 | +| -------------- | -------- | ----------------------------------------------------------- | +| node_id | string | 触发中断的节点 ID | +| tool_call_id | string | 本次询问的 ID,继续对话时作为 `answers_by_tool_call` 的外层键 | +| questions | object[] | 需要回答的问题 | +| ∟ question | string | 问题文本,继续对话时作为 `answers_by_tool_call` 的内层键 | +| ∟ options | object[] | 选项,为空表示自由输入 | +| ∟∟ description | string | 选项文本 | +| ∟ multi_select | boolean | 是否可多选 | +| message_id | int64 | 被暂停消息的 ID,用于继续对话接口的 URL | +| chat_id | int64 | 所属会话的 ID | + +```json +{"event":"human_interaction_required","workflow_run_id":"745910371102313","data":{"node_id":"n_ask_human","tool_call_id":"call_abc123","questions":[{"question":"你想查看哪个时间范围?","options":[{"description":"近一周"},{"description":"近一月"}],"multi_select":false}],"message_id":43,"chat_id":1001}} +``` + +此事件之后流以 `chat_finished` 结束;被中断的运行不会发送 `workflow_finished`。 + +## 辅助事件 + +以下事件均为信息性事件,最简客户端可全部忽略。 + +### query_masked + +用户提问中的敏感内容在处理前被脱敏。展示时用 `masked_query` 替换原始提问。 + +| 名称 | 类型 | 说明 | +| ------------ | ------ | -------------- | +| raw_query | string | 原始用户提问 | +| masked_query | string | 脱敏后的提问 | + +### plan_changed + +Agent 创建或更新了任务计划。 + +| 名称 | 类型 | 说明 | +| ---------- | ------ | ------------------------ | +| node_id | string | 规划节点的 ID | +| started_at | int64 | 变更时间(Unix 秒) | +| outputs | object | 当前计划内容 | + +此事件额外携带一个顶层 `tool_name` 字段(与 `data` 同级),标识规划工具。 + +### context_compress_started / context_compress_finished + +长对话会触发上下文压缩,这两个事件包裹压缩过程。与其他事件不同,这里的时间戳是 RFC 3339 字符串。 + +`context_compress_started`: + +| 名称 | 类型 | 说明 | +| ---------- | ------ | -------------------- | +| started_at | string | 开始时间(RFC 3339) | +| inputs | object | 压缩输入摘要 | + +`context_compress_finished`: + +| 名称 | 类型 | 说明 | +| ---------- | ------ | -------------------- | +| created_at | string | 结束时间(RFC 3339) | +| inputs | object | 压缩输入摘要 | +| outputs | object | 压缩结果摘要 | diff --git a/docs/zh-HK/docs/ai/chat/conversation.md b/docs/zh-HK/docs/ai/chat/conversation.md index 2a12e84d..d08a31bf 100644 --- a/docs/zh-HK/docs/ai/chat/conversation.md +++ b/docs/zh-HK/docs/ai/chat/conversation.md @@ -142,15 +142,17 @@ curl -N -X POST "https://openapi.longbridge.com/v1/ai/agents/123/conversations" ``` event: message -data: {"event":"chat_started","workflow_run_id":"wr_...","data":{"chat_uid":"ct_9f2c1a5b","message_id":42}} +data: {"event":"chat_started","workflow_run_id":"745910371102313","data":{"chat_uid":"ct_9f2c1a5b","message_id":42}} event: message -data: {"event":"message","workflow_run_id":"wr_...","data":{"text":"特斯拉"}} +data: {"event":"message","workflow_run_id":"745910371102313","data":{"text":"特斯拉"}} event: message -data: {"event":"workflow_finished","workflow_run_id":"wr_...","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"..."}}} +data: {"event":"workflow_finished","workflow_run_id":"745910371102313","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"..."}}} ``` +完整的事件類型列表、負載結構與解析方式見 [SSE 事件](/zh-HK/docs/ai/chat/events)。 + ### Response Status | Status | Description | Schema | diff --git a/docs/zh-HK/docs/ai/chat/events.md b/docs/zh-HK/docs/ai/chat/events.md new file mode 100644 index 00000000..08fa011b --- /dev/null +++ b/docs/zh-HK/docs/ai/chat/events.md @@ -0,0 +1,404 @@ +--- +slug: events +title: SSE 事件 +sidebar_position: 4 +language_tabs: false +toc_footers: [] +includes: [] +search: true +highlight_theme: '' +headingLevel: 2 +--- + +流式模式(`Accept: text/event-stream`)下,[發起對話](/zh-HK/docs/ai/chat/conversation)和[繼續對話](/zh-HK/docs/ai/chat/continue)會以一系列 SSE 事件推送運行過程。本頁列出所有事件類型及解析方式。 + +## 幀格式 + +每一幀 SSE 都使用同樣的信封結構:SSE 的 `event` 字段恆為 `message`,`data` 字段是一個 JSON 對象: + +``` +event: message +data: {"event":"","workflow_run_id":"745910371102313","data":{...}} +``` + +| 名稱 | 類型 | 說明 | +| --------------- | ------ | ------------------------------------------------ | +| event | string | 事件類型,按此字段分發處理 | +| workflow_run_id | string | 本次運行的 ID,為數字 ID 的字符串形式(如 `"745910371102313"`),同一次運行的所有事件中該值一致 | +| data | object | 事件負載,結構隨事件類型而不同(見下文) | + +解析規則: + +- **按 `data.event` 分發**,而不是 SSE 的 `event` 字段(它恆為 `message`)。 +- **忽略未知事件類型。** 事件類型可能隨時新增,只處理已知事件的客戶端可保持向前兼容。 +- 除特別說明外,`started_at` / `finished_at` 為 Unix 秒級時間戳,`elapsed_time` 為秒數。 + +## 典型事件序列 + +一次運行始於 `chat_started`、止於 `chat_finished`,中間的事件取決於運行結果: + +**成功:** + +``` +chat_started → workflow_started → thinking_started → message (type=think) ... +→ node_tool_use_started / node_tool_use_finished ... +→ thinking_finished → message (type=answer) ... +→ workflow_finished (status=succeeded) → chat_finished +``` + +**中斷**(Agent 需要你補充信息,通過[繼續對話](/zh-HK/docs/ai/chat/continue)恢復): + +``` +chat_started → workflow_started → ... → human_interaction_required → chat_finished +``` + +注意:中斷的運行**不會**發送 `workflow_finished`;繼續被中斷的運行時,恢復後的流**不會**再次發送 `workflow_started`。 + +**失敗:** + +``` +chat_started → workflow_started → ... → workflow_finished (status=failed) → chat_finished +``` + +## 最簡客戶端 + +純問答場景只需處理四種事件,其餘事件都是可選的過程展示: + +| 事件 | 處理方式 | +| ---------------------------- | ------------------------------------------------------ | +| `message`(`type=answer`) | 將 `data.text` 追加到正在展示的回答中 | +| `human_interaction_required` | 展示問題,攜帶答案調用繼續對話接口 | +| `workflow_finished` | 讀取最終 `status` 和 `outputs.answer`;失敗時展示錯誤 | +| `chat_finished` | 關閉流,本次運行結束 | + +## 會話生命週期 + +### chat_started + +每個流的第一個事件。會話和消息記錄已創建;保存 `chat_uid`(用於追問)和 `message_id`(用於中斷後繼續)。 + +| 名稱 | 類型 | 說明 | +| ---------- | ------ | -------------------------- | +| chat_id | int64 | 會話內部 ID | +| chat_uid | string | 會話標識,用於後續請求 | +| message_id | int64 | 本輪消息 ID | + +```json +{"event":"chat_started","workflow_run_id":"745910371102313","data":{"chat_id":1001,"chat_uid":"ct_9f2c1a5b","message_id":42}} +``` + +### chat_finished + +每個流的最後一個事件,之後服務端關閉連接。 + +| 名稱 | 類型 | 說明 | +| ------------- | ------ | ------------------------------ | +| chat_id | int64 | 會話內部 ID | +| chat_uid | string | 會話標識 | +| message_id | int64 | 本輪消息 ID | +| error | string | 錯誤詳情,成功時為空 | +| error_message | string | 面向用戶的錯誤信息,成功時為空 | + +## 運行生命週期 + +### workflow_started + +Agent 運行已開始。通過繼續對話恢復被中斷的運行時不會發送此事件。 + +| 名稱 | 類型 | 說明 | +| ----------- | ------ | ------------------------------------------------------ | +| workflow_id | int64 | 該 Agent 底層工作流的 ID | +| started_at | int64 | 開始時間(Unix 秒) | +| inputs | object | 運行輸入 | +| hit_cache | bool | 為 `true` 時表示答案命中緩存,流會直接進入回答階段 | + +### workflow_finished + +運行已結束——成功、失敗或被用戶停止。在此讀取最終結果。 + +| 名稱 | 類型 | 說明 | +| ------------- | -------- | ---------------------------------------------------------- | +| status | string | `succeeded` / `failed` / `stopped` | +| outputs | object | 運行輸出;`outputs.answer` 為完整的最終回答文本 | +| elapsed_time | number | 運行耗時(秒) | +| error | string | 本地化的錯誤描述,僅 `status` 為 `failed` 時存在 | +| error_code | int32 | 錯誤碼,僅 `status` 為 `failed` 時存在 | +| error_message | string | 面向用戶的錯誤信息,僅失敗時存在 | +| error_args | object | 額外錯誤上下文(如 `workflow_run_id`),可能省略 | +| process_data | object[] | 運行經過的過程階段,僅用於展示 | + +```json +{"event":"workflow_finished","workflow_run_id":"745910371102313","data":{"status":"succeeded","elapsed_time":3.21,"outputs":{"answer":"特斯拉(TSLA.US)近期..."}}} +``` + +說明: + +- `outputs.answer` 是權威的完整回答。如果你通過 `message` 事件拼接了回答,可用它校驗或替換。 +- `status` 為 `stopped`(用戶停止運行)時,`outputs.answer` 為已生成的部分回答。 + +## 回答流式輸出 + +### message + +增量文本片段。這是頻率最高的事件,按到達順序拼接 `text` 即可。 + +| 名稱 | 類型 | 說明 | +| -------------------- | ------ | ------------------------------------------------------------------------ | +| text | string | 增量文本片段 | +| type | string | `answer` — 最終回答文本;`think` — 推理過程;`process` — 階段進度描述 | +| key | string | 片段所屬流段的標識。相同 `key` 的片段構成一個連續塊,渲染時按 `key` 分組 | +| started_at | int64 | 該流段開始時間(Unix 秒) | +| stage | string | 階段標識,僅 `type=process` 時存在 | +| stage_title | string | 階段進行中的標題,僅 `type=process` 時存在 | +| stage_finished_title | string | 階段完成後的標題,僅 `type=process` 時存在 | +| outputs | object | 附加在片段上的額外負載,通常不存在 | + +```json +{"event":"message","workflow_run_id":"745910371102313","data":{"text":"特斯拉","type":"answer","key":"n_llm_1:answer","started_at":1752048000}} +``` + +解析: + +- 只有 `type=answer` 的片段屬於用戶可見的回答,全部拼接後與 `workflow_finished.outputs.answer` 一致。 +- `type=think` 的片段是 Agent 的中間推理,可放入可摺疊的「思考」區域展示,也可忽略。 +- `type=process` 的片段描述階段進度,附帶 `stage` 系列字段用於分組。 + +## 思考階段 + +### thinking_started + +Agent 進入推理階段(分析問題、規劃工具調用)。在它與 `thinking_finished` 之間可能出現 `type=think` 的 `message` 事件和工具調用事件。 + +| 名稱 | 類型 | 說明 | +| ---------- | ----- | -------------------- | +| started_at | int64 | 開始時間(Unix 秒) | + +### thinking_finished + +推理階段結束,隨後是回答文本(`type=answer` 的 `message`)。 + +| 名稱 | 類型 | 說明 | +| ------------ | ----- | -------------------- | +| finished_at | int64 | 結束時間(Unix 秒) | +| elapsed_time | int32 | 推理耗時(秒) | + +## 工具調用 + +Agent 在生成回答的過程中會調用工具(行情、賬戶、聯網搜索等)。每次調用都由一對 started/finished 事件包裹——用 `tool_use_id` 配對。 + +這對事件覆蓋**所有普通工具調用**。只有兩種特殊調用改用各自的事件族上報:派生子智能體(`subagent_*`,見下文)和把另一個 Agent 作為工具調用(`agent_tool_*`,見下文)。如果你的 Agent 沒有使用這兩項能力,所有工具調用都只會以 `node_tool_use_started` / `node_tool_use_finished` 出現。 + +### node_tool_use_started + +一次工具調用已開始。 + +| 名稱 | 類型 | 說明 | +| -------------- | -------- | --------------------------------------------------------------- | +| tool_use_id | string | 本次調用的唯一 ID,用於與 finished 事件配對 | +| tool_name | string | 工具的本地化展示名(用於界面顯示) | +| tool_func_name | string | 與語言無關的穩定工具標識,按工具類型處理邏輯時用它 | +| tool_args | string | 調用參數(JSON 字符串) | +| tips | string | 可直接展示的進度文案(如「正在聯網搜索…」) | +| tip_chips | string[] | 與 `tips` 配套的短標籤,可能省略 | +| iteration | int | 輪次編號。同一輪(相同 `iteration`)的調用是並行執行的 | +| started_at | int64 | 開始時間(Unix 秒) | + +### node_tool_use_finished + +工具調用已結束。 + +| 名稱 | 類型 | 說明 | +| -------------- | -------- | ---------------------------------------- | +| tool_use_id | string | 與 started 事件的 `tool_use_id` 一致 | +| status | string | `succeeded` / `failed` | +| error | string | 失敗時的錯誤描述 | +| elapsed_time | number | 調用耗時(秒) | +| started_at | int64 | 開始時間(Unix 秒) | +| tool_name | string | 本地化展示名 | +| tool_func_name | string | 穩定工具標識 | +| tool_args | string | 調用參數(JSON 字符串) | +| tool_type | string | 工具類別 | +| tips | string | 進度文案 | +| tip_chips | string[] | 短標籤,可能省略 | +| iteration | int | 輪次編號 | +| is_thinking | bool | 為 `true` 表示調用發生在思考階段 | +| outputs | object | 過濾後的調用結果,見下 | + +`outputs` 只攜帶用於展示的字段: + +| 字段 | 說明 | +| ------------------------- | -------------------------------- | +| outputs.references | 工具結果引用的來源 | +| outputs.reference_domains | 引用來源的域名 | +| outputs.query | 工具執行的查詢 | +| outputs.text | 工具的原始響應文本 | +| outputs.tool_args | 解析後的請求參數 | +| outputs.data | 結構化結果,僅部分工具存在 | + +```json +{"event":"node_tool_use_finished","workflow_run_id":"745910371102313","data":{"tool_use_id":"call_abc123","status":"succeeded","elapsed_time":1.42,"tool_name":"聯網搜索","tool_func_name":"web_search","tool_args":"{\"query\":\"TSLA stock news\"}","tool_type":"builtin","tips":"已聯網搜索","iteration":1,"is_thinking":true,"outputs":{"query":"TSLA stock news","references":[{"index":1,"title":"...","url":"..."}]}}} +``` + +## 子智能體事件 + +Agent 派生子智能體處理子任務時,其生命週期使用獨立的事件族上報,而不是 `node_tool_use_*`。 + +### subagent_started + +| 名稱 | 類型 | 說明 | +| ----------- | ------ | ------------------------------------------ | +| node_id | string | 派生子智能體的節點 ID | +| tool_use_id | string | 本次派生的唯一 ID,與 finished 事件配對 | +| started_at | int64 | 開始時間(Unix 秒) | +| goal | string | 分配給子智能體的目標 | +| prompt | string | 交給子智能體的完整任務提示詞 | +| subagent_id | string | 子智能體標識,可能省略 | +| tools | array | 授予子智能體的工具列表,可能省略 | + +### subagent_progress + +子智能體每調用一次自己的工具就發送一次,用於在子智能體卡片內實時渲染時間線。 + +| 名稱 | 類型 | 說明 | +| -------------------- | ------ | ------------------------------------------------ | +| node_id | string | 派生子智能體的節點 ID | +| parent_tool_call_id | string | 所屬 `subagent_started` 事件的 `tool_use_id` | +| subagent_tool_name | string | 子智能體調用的工具名 | +| subagent_tool_args | string | 該調用的參數(JSON 字符串) | +| subagent_status | string | 該調用的狀態:`running` / `succeeded` / `failed` | +| subagent_duration_ms | int64 | 該調用耗時(**毫秒**) | +| subagent_iteration | int | 子智能體內部的輪次編號 | +| started_at | int64 | 開始時間(Unix 秒) | + +### subagent_finished + +| 名稱 | 類型 | 說明 | +| ------------ | ------ | ------------------------------------------------------------------------ | +| node_id | string | 派生子智能體的節點 ID | +| tool_use_id | string | 與 `subagent_started` 的 `tool_use_id` 一致 | +| status | string | `succeeded` / `failed` | +| started_at | int64 | 開始時間(Unix 秒) | +| elapsed_time | number | 子智能體總耗時(秒) | +| error | string | 失敗時的錯誤描述 | +| outputs | object | 子智能體結果:通常包含 `goal`、`result` 和 `subagent_tools`(其工具調用時間線) | + +## Agent 工具事件 + +Agent 把另一個 Agent 作為工具調用時,該內部運行使用 `agent_tool_*` 事件族上報,結構與子智能體事件相似。 + +### agent_tool_started + +| 名稱 | 類型 | 說明 | +| --------------- | -------- | --------------------------------------- | +| node_id | string | 調用方節點 ID | +| tool_use_id | string | 本次調用的唯一 ID,與 finished 事件配對 | +| agent_tool_name | string | 被調用 Agent 的標識 | +| title | string | 展示標題,可能省略 | +| started_at | int64 | 開始時間(Unix 秒) | +| tool_args | string | 調用參數(JSON 字符串) | +| tool_name | string | 本地化展示名 | +| tips | string | 進度文案,可能省略 | +| tip_chips | string[] | 短標籤,可能省略 | +| is_thinking | bool | 為 `true` 表示發生在思考階段 | + +### agent_tool_progress + +被委託 Agent 每進行一次內部工具調用就發送一次。 + +| 名稱 | 類型 | 說明 | +| ------------------- | ------ | ---------------------------------------------------- | +| node_id | string | 調用方節點 ID | +| parent_tool_call_id | string | 所屬 `agent_tool_started` 事件的 `tool_use_id` | +| agent_tool_name | string | 被調用 Agent 的標識 | +| inner_tool_name | string | 被委託 Agent 調用的內部工具名 | +| inner_tool_args | string | 該內部調用的參數(JSON 字符串) | +| status | string | 內部調用的狀態:`running` / `succeeded` / `failed` | +| duration_ms | int64 | 內部調用耗時(**毫秒**) | +| started_at | int64 | 開始時間(Unix 秒) | +| is_thinking | bool | 為 `true` 表示發生在思考階段 | + +### agent_tool_finished + +| 名稱 | 類型 | 說明 | +| --------------- | -------- | --------------------------------------------- | +| node_id | string | 調用方節點 ID | +| tool_use_id | string | 與 `agent_tool_started` 的 `tool_use_id` 一致 | +| agent_tool_name | string | 被調用 Agent 的標識 | +| status | string | `succeeded` / `failed` | +| started_at | int64 | 開始時間(Unix 秒) | +| elapsed_time | number | 總耗時(秒) | +| error | string | 失敗時的錯誤描述 | +| tool_args | string | 調用參數(JSON 字符串) | +| outputs | object | 被委託 Agent 的結果 | +| tool_type | string | 工具類別 | +| tips | string | 進度文案,可能省略 | +| tip_chips | string[] | 短標籤,可能省略 | +| is_thinking | bool | 為 `true` 表示發生在思考階段 | + +## 中斷 + +### human_interaction_required + +運行已暫停:Agent 需要你補充信息或確認。收集 `questions` 的答案後調用[繼續對話](/zh-HK/docs/ai/chat/continue)——答案以 `tool_call_id` 為鍵。 + +| 名稱 | 類型 | 說明 | +| -------------- | -------- | ----------------------------------------------------------- | +| node_id | string | 觸發中斷的節點 ID | +| tool_call_id | string | 本次詢問的 ID,繼續對話時作為 `answers_by_tool_call` 的外層鍵 | +| questions | object[] | 需要回答的問題 | +| ∟ question | string | 問題文本,繼續對話時作為 `answers_by_tool_call` 的內層鍵 | +| ∟ options | object[] | 選項,為空表示自由輸入 | +| ∟∟ description | string | 選項文本 | +| ∟ multi_select | boolean | 是否可多選 | +| message_id | int64 | 被暫停消息的 ID,用於繼續對話接口的 URL | +| chat_id | int64 | 所屬會話的 ID | + +```json +{"event":"human_interaction_required","workflow_run_id":"745910371102313","data":{"node_id":"n_ask_human","tool_call_id":"call_abc123","questions":[{"question":"你想查看哪個時間範圍?","options":[{"description":"近一週"},{"description":"近一月"}],"multi_select":false}],"message_id":43,"chat_id":1001}} +``` + +此事件之後流以 `chat_finished` 結束;被中斷的運行不會發送 `workflow_finished`。 + +## 輔助事件 + +以下事件均為信息性事件,最簡客戶端可全部忽略。 + +### query_masked + +用戶提問中的敏感內容在處理前被脫敏。展示時用 `masked_query` 替換原始提問。 + +| 名稱 | 類型 | 說明 | +| ------------ | ------ | -------------- | +| raw_query | string | 原始用戶提問 | +| masked_query | string | 脫敏後的提問 | + +### plan_changed + +Agent 創建或更新了任務計劃。 + +| 名稱 | 類型 | 說明 | +| ---------- | ------ | ------------------------ | +| node_id | string | 規劃節點的 ID | +| started_at | int64 | 變更時間(Unix 秒) | +| outputs | object | 當前計劃內容 | + +此事件額外攜帶一個頂層 `tool_name` 字段(與 `data` 同級),標識規劃工具。 + +### context_compress_started / context_compress_finished + +長對話會觸發上下文壓縮,這兩個事件包裹壓縮過程。與其他事件不同,這裡的時間戳是 RFC 3339 字符串。 + +`context_compress_started`: + +| 名稱 | 類型 | 說明 | +| ---------- | ------ | -------------------- | +| started_at | string | 開始時間(RFC 3339) | +| inputs | object | 壓縮輸入摘要 | + +`context_compress_finished`: + +| 名稱 | 類型 | 說明 | +| ---------- | ------ | -------------------- | +| created_at | string | 結束時間(RFC 3339) | +| inputs | object | 壓縮輸入摘要 | +| outputs | object | 壓縮結果摘要 |