# 智能体系统流式事件协议：协议层规范（Draft v0）

> 本文档是协议层规范（Protocol Layer Spec），用于约束 Runtime / Server / UI / 网关 / 调试器之间如何**表达、转发、解释**事件。  
> 本文档旨在把“设计理念”落地为可执行的协议方案：包括架构视图、事件模型、统一信封、字段定义、事件类型与 payload 结构，以及可直接用于联调的 JSON 样例。  
> 注：协议以**流式**为默认运行方式；**非流式**为兼容特例，规则在对应章节说明。

---

## 目录

1. 总览：协议解决的核心问题  
2. 系统架构视图与数据路径（ASCII 图）  
3. 事件模型：三流（State / Data / Control）与 ReAct  
4. 统一事件信封（Envelope）与身份体系  
5. 时间序与续订：timestamp / since_timestamp / 幂等  
6. 嵌套调用：独立运行 + 事后挂载（修补规则）  
7. 事件类型定义与 payload 结构（详细）  
8. Start/Delta/End 的强约束与非流式合并规则  
9. 样例 JSON：从简单到复杂（含嵌套与并发）  
10. 兼容性与扩展规范

---

## 1. 总览：协议解决的核心问题

智能体系统的执行过程具有以下常态特征：

- 多轮 ReAct：思考（reasoning）↔ 输出（text）↔ 行动（action）↔ 观察（action.result）循环出现
- 并发扇出：同一轮思考可并发触发多个 action，事件交织、返回顺序不保证
- 深层嵌套：action 触发子 Agent/Tool 的完整生命周期与数据流
- 可中断与恢复：执行可被外力暂停、回滚、重试；中断通常涉及安全授权与审计
- 流式默认：系统主要为流式服务（delta 频繁出现）；非流式是兼容特例

本协议的目标是：在上述复杂条件下，保证观察侧（UI/调试器/存储）仍能获得：

- **统一的全局追踪域**（同一次顶层调用只有一个“全局根”）
- **清晰可重建的嵌套结构**（谁调用了谁，哪条事件属于哪次调用容器）
- **可重建的时间序**（乱序到达也能恢复真实发生顺序）
- **可判定的生命周期边界**（何时开始、何时结束、何时挂起）
- **可复核的权威结果**（end 类事件是权威最终态，不是可选项）

---

## 2. 系统架构视图与数据路径（ASCII 图）

### 2.1 组件关系图（生产、转发、消费）

```

+-------------------+        +-------------------+        +-------------------+
|     Executor      |        |     Forwarder      |        |      Observer     |
| (Agent/Tool/LLM)  |        | (Runtime/Gateway)  |        | (UI/Debugger/DB)  |
+---------+---------+        +---------+---------+        +---------+---------+
|                             |                             |
| 1) emit local events        |                             |
|    (self-root view)         |                             |
+---------------------------> |                             |
| 2) patch/attach events      |
|    (global-root view)       |
+---------------------------> |
|
| 3) render/store/replay
v
(filter/sort/group)

```

要点：

- Executor 输出的是“自洽的本地事件流”（可独立运行、可独立调试）
- Forwarder 负责把子事件“挂载到父上下文”，统一为观察侧可理解的全局结构
- Observer 只消费“全局视角一致”的事件，不需要猜测嵌套关系

---

### 2.2 三流与 ReAct 的时间线图

```text

时间 ───────────────────────────────────────────────────────────────────▶

State Flow:
run.lifecycle.created ───────── run.lifecycle.running* ───────── run.lifecycle.completed
(running可重复心跳)

Data Flow (ReAct in one run):
reasoning.start  reasoning.delta...  reasoning.end  text.start  text.delta... text.end
│
├─ action.start/end (A1 参数段：start, delta..., end)
│     └─ Child(A1) run.lifecycle.created ... completed
│           ├─ Child 内部数据流（text/reasoning/action...）
│           └─ Child content.agent.result.*（start, delta..., end）
│                 └─ action.result.*（start, delta..., end；由 Child agent.result 转换）
│
├─ action.start/end (A2 参数段：start, delta..., end)
│     └─ Child(A2) run.lifecycle.created ... completed
│           ├─ Child 内部数据流（text/reasoning/action...）
│           └─ Child content.agent.result.*（start, delta..., end）
│                 └─ action.result.*（start, delta..., end；由 Child agent.result 转换）
│
│        (A1/A2 并发交织，返回顺序不保证)
↓
下一轮 reasoning/text...

Control Flow:
(optional) control.interrupt / control.rollback / control.suggestions

```

要点：

- State 是骨架：定义生命周期边界与可判定性
- Data 是产出：以 delta 为主要载体，end 为权威最终态
- Control 是外力：改变执行路径（暂停/回滚/建议）

---

## 3. 事件模型：三流（State / Data / Control）与 ReAct

### 3.1 三流职责边界

- **State Flow**：定义 run 的生命周期、边界与状态迁移
- **Data Flow**：承载可展示、可解析、可用于下一步推理的内容增量与权威结果
- **Control Flow**：表达外力介入（中断/回滚/建议），改变或引导执行路径

### 3.2 ReAct 的协议化表达

ReAct 抽象为在同一个 run 的生命周期内出现多轮：

- `content.reasoning.*`：一轮反思/推理（可选展示策略，但协议允许表达）
- `content.text.*`：用户可见文本输出（流式 delta + 权威 end）
- `content.action.*`：本轮派生的行动（参数流式、可并发）
- 子行动触发的子流程在 `content.action.*` 之后进入其自身 `run.lifecycle.*`，并在其生命周期内产生内部数据流与最终交付流
- `content.action.result.*`：对子流程最终交付的标准化结果表达，位于子流程生命周期之内，供调用方作为“关注的结果”使用

此外：

- `content.agent.result.*`：**当前执行者**的最终交付物/返回值数据流（区别于中间 text）
- 对于调用方而言，子流程的多数过程事件（子生命周期心跳、内部 delta、工具细节等）仅用于上层视图与审计；可用于下一步推理的权威输入以 `content.action.result.end` 为准

各部分细节如下：

```text
时间线  ─────────────────────────────────────────────────────────────────────────▶

Parent（调用者，同一 run_id 内）:
  run.lifecycle.created                [created 必带 executor_metadata / user_metadata]
  run.lifecycle.running×N              [running 可重复发送，不可替代 created]

  content.text.* / content.reasoning.delta      （ReAct 可多轮；同轮携带 meta.turn_id）
      │
      ├─ content.action.start                 (payload.action_id = call_001, meta.turn_id=turn_001)
      ├─ content.action.delta×N               (part=intent/args/reasoning; key_path 可选)
      ├─ content.action.end                   (full_arguments 权威参数)
      │
      │    子流程生命周期窗口（被调用者：独立运行；对外发布时 Forwarder 修补挂载）
      │    ┌────────────────────────────────────────────────────────────────────┐
      │    │ Child: run.lifecycle.created                                        │
      │    │ Child: run.lifecycle.running×N                                      │
      │    │ Child: content.text.* / content.reasoning.delta / ...               │
      │    │                                                                    │
      │    │ Child: content.agent.result.start  (mode/json_schema 可选：交付物类型)│
      │    │ Child: content.agent.result.delta×N (part/delta/key_path：结构化增量)│
      │    │ Child: content.agent.result.end    (full_result 权威交付；mode 可补齐)│
      │    │                                                                    │
      │    │ Child: run.lifecycle.completed|failed|cancelled                     │
      │    └────────────────────────────────────────────────────────────────────┘
      │
      │    Forwarder/调用侧折叠转换（仅对“调用方关注输入”负责）:
      │      Child.agent.result.end.payload.full_result
      │         └── convert/extract ──▶ Parent.action.result.end.payload.full_result
      │
      ├─ content.action.result.start (可选：status/mode/json_schema；建议带 action_id)
      ├─ content.action.result.delta×N (part/delta/key_path；建议与子流程语义对齐)
      └─ content.action.result.end   (full_result 权威结果；调用方稳定输入口径)

  （进入下一轮或结束）
  run.lifecycle.completed|failed|cancelled
```

---

## 4. 统一事件信封（Envelope）与身份体系

### 4.1 Envelope 总体结构（顶层字段）

所有事件共享统一信封。字段分为四类：

1) 身份与排序：`type`, `timestamp`  
2) 追踪与嵌套：`trace_id`, `trace_path`  
3) 运行单元：`run_id`, `run_path` 
4) 执行主体与上下文：`worker_id`, `executor_*`, `user_*`, `action_id`  
5) 载荷：`payload`

#### 4.1.1 Envelope JSON 模板

```json
{
  "type": "content.text.delta",
  "timestamp": 1734900000123.456,
  "trace_id": "R-uuid",
  "trace_path": ["C1-uuid", "G1-uuid"],
  "run_id": "run-uuid",
  "run_path": ["run-uuid", "retry-run-uuid"],
  "worker_id": "hostA:0",
  "executor_id": "AGENT:writer@proj_001",
  "executor_type": "AGENT",
  "executor_path": ["AGENT:root@proj_001", "AGENT:writer@proj_001"],
  "action_id": "react-turn-uuid",
  "user_metadata": {
    "id": "user_001",
    "firstname" :"明照",
    "lastname":"张",
    "username" :"zhangmingzhao",
    "email":"zmz@gamil.com",
    "avatar_uri":"/pic/pic123.jpg"
  },
  "payload": {}
}
```

---

### 4.2 字段定义（详细）

> 约定：
>
> * **必填**：Producer 必须提供；Forwarder 不得删除
> * **条件必填**：在特定事件或场景必须提供
> * **可选**：可省略，消费者需容错
> * 所有 ID 推荐 UUID（字符串），但协议不强制格式，只强制稳定性与唯一性

#### 4.2.1 字段说明表

| 字段                  | 类型       | 必填 | 说明                                          |
| ------------------- | -------- | -: | ------------------------------------------- |
| `type`              | string   |  是 | 事件类型，采用命名空间（见第 7 章）                         |
| `timestamp`         | number   |  是 | UTC epoch 毫秒（允许小数）；排序与续订主键                  |
| `trace_id`          | string   |  是 | **全局根追踪 ID**（观察侧统一视角）                       |
| `trace_path`        | string[] |  否 | 嵌套路径：从根到当前事件所属子 trace 的链（不含根）               |
| `run_id`            | string   |  是 | 当前运行单元 ID，一次执行尝试的生命周期载体                     |
| `run_path`          | string[] |  否 | 重试/恢复链：同一逻辑执行在多次 run 的递归序列                  |
| `worker_id`         | string   |  是 | 产生日志/事件的运行节点标识（如 `host:rank`）               |
| `executor_id`       | string   |  是 | 执行者唯一标识（建议 `TYPE:name@project`）             |
| `executor_type`     | string   |  否 | 执行者类型：AGENT / TOOL / LLM / ...              |
| `executor_path`     | string[] |  否 | 调用链（从根执行者到当前执行者）；由 Forwarder 拼接维护           |
| `react_id`         | string   |  否 | ReAct 轮次 ID：把本轮 reasoning/text 与派生 actions 关联 |
| `action_id`         | string   |  否 | 每条派生 action id  |
| `user_metadata`      | object   | 条件 | 在 run.lifecycle.created 必须携带（用于权限/审计/归属）  字段包含 id/firstname/lastname/username/email/avatar_uri   |
| `executor_metadata` | object   | 条件 | 在 run.lifecycle.created 必须携带（用于 UI 展示与存储解析）, "name"/`id`/`avatar_uri` |
| `payload`           | object   |  是 | 事件载荷，结构由 `type` 决定                          |

#### 4.2.2 关于 `trace_id` 与 `trace_path` 的语义

* `trace_id` 永远指向**同一次顶层调用的根**
* `trace_path` 用于表达嵌套结构：它记录“事件属于哪个子执行域”

例如：

* 根执行者事件：`trace_id = R`, `trace_path = [] 或省略`
* 子执行者事件（经挂载后发布）：`trace_id = R`, `trace_path = [C1]`
* 孙子执行者事件：`trace_id = R`, `trace_path = [C1, G1]`

---

## 5. 时间序与续订：timestamp / since_timestamp / 幂等

### 5.1 排序规则

Observer 必须以 `(timestamp)` 作为主要排序键。到达顺序无语义。

如需同一毫秒内稳定排序，可增加工程层次的 tie-breaker（ 本地自增序列），但协议层不强制；协议层要求 Producer 尽量避免大量等值 timestamp。

### 5.2 断线续订（建议 API 语义）

客户端维护 `last_seen_timestamp`，重连后请求：

* `since_timestamp = last_seen_timestamp`

服务端过滤：

* 仅返回 `timestamp > since_timestamp` 的事件
* 断线续订解决的是“网络中断/客户端重连”导致的连接断开，不改变执行语义。
* 若执行进入 `run.lifecycle.suspended`，本次推送流通常会结束；后续的 `run.lifecycle.resuming` 会出现在**新建的事件流**中（见 7.1.3）。

### 5.3 幂等处理建议（Observer）

Observer 建议对“权威 end 事件”做幂等：同一容器（同一聚合键）重复收到 end 时应覆盖而非叠加。

---

## 6. 嵌套调用：独立运行 + 事后挂载（修补规则）

### 6.1 独立运行（Producer 规则）

任何被调用的子执行者（Child）必须：

* 自己生成本地 `trace_id = C`
* 本地 `trace_path` 为空（省略或 `[]`）
* 本地 `executor_path = [child_executor_id]`
* 不依赖父上下文注入字段（即使父方传递，也应忽略）

这样 Child 的事件流在脱离父执行时仍可完整解释。

### 6.2 事后挂载（Forwarder 修补规则）

Forwarder 对外发布子事件时必须对每条子事件做如下修补：

1. `trace_id`：覆盖为根 `R`
2. `trace_path`：拼接为 ` [trace_id] + trace_path`
3. `executor_path`：拼接为 `[ local_executor_id ] + executor_path`
4. `react_id`：若该 child 属于某轮 ReAct 派生的 action 的运行记录，则注入对应 `react_id`（必须稳定绑定，禁止“当前 react_id”这类不稳定推断）
5. `action_id`：对于每个 action 由调用方会触发一个 action id，与实际展开的子流程一般处于一对一关系（action 可能触发重试，action可能需要保留授权信息，action 可以反复执行得到不同结果，不同时间得到不同结果），子流程不知道自己所属 action id ，需要调用方在消息流中注入。 react_id 与 action_id 有一对多关系，一次 react流程，可能触发多个action
5. 将子流程的 `content.agent.result.*` 映射为调用方关注的 `content.action.result.*`（见第 7.5 章），并保证该映射事件出现在子流程生命周期范围内

### 6.3 挂载示意图

```
Child local event (before patch):
  trace_id = C1
  trace_path = []
  executor_path = [Tool:search]

Published event (after patch):
  trace_id = R
  trace_path = [C1]
  executor_path = [Agent:root, Tool:search]
```

---

## 7. 事件类型定义与 payload 结构（详细）

> 命名约定：
>
> * `run.lifecycle.*`：状态流
> * `content.*`：数据流
> * `control.*`：控制流
>   所有数据流事件强制遵循 **Start / Delta / End** 模式（第 8 章），其中 **End 是权威最终态**。

### 7.1 State Flow：`run.lifecycle.*`

用于表达 run 的生命周期边界与状态迁移。

#### 7.1.1 事件枚举

* `run.lifecycle.created`（开始标记，强制出现）
* `run.lifecycle.running`（存在态心跳，可重复，可省略）
* `run.lifecycle.suspended`（挂起，等待外部输入）
* `run.lifecycle.resuming`（恢复开始标记）
* `run.lifecycle.completed`（成功终止标记）
* `run.lifecycle.failed`（失败终止标记）
* `run.lifecycle.cancelled`（取消终止标记）

关于“断流边界”的约定：

* `run.lifecycle.created` 是本次流的开始标记。
* `run.lifecycle.completed/failed/cancelled` 是本次流的终止标记。
* `run.lifecycle.suspended` 表示执行进入等待态，**本次流通常在此处结束**；后续恢复应通过新建事件流发送 `run.lifecycle.resuming`。

#### 7.1.2 payload 结构

**`run.lifecycle.created` payload**

| 字段             | 类型     | 必填 | 说明              |
| -------------- | ------ | -: | --------------- |
| `input_data`        | object |  是 | 输入摘要（可用于 UI/审计） |


此外，**created 信封中必须携带**：

* `executor_metadata`（条件必填）
* `user_metadata`（条件必填） id/firstname/lastname/username/email/avatar_uri

**`run.lifecycle.running` payload**

无

**`run.lifecycle.suspended` payload**

| 字段         | 类型     | 必填 | 说明                 |
| ---------- | ------ | -: | ------------------ |
| `reason`   | string |  是 | 挂起原因摘要             |
| `awaiting` | object |  否 | 等待的输入形式（确认/文本/文件等） |

**`run.lifecycle.resuming` payload**

| 字段               | 类型     | 必填 | 说明              |
| ---------------- | ------ | -: | --------------- |
| `resume_context` | object |  是 | 恢复上下文（断点/输入/策略） |

**终止事件（completed/failed/cancelled）payload**

| 字段        | 类型     | 必填 | 说明              |
| --------- | ------ | -: | --------------- |
| `output` | object |  条件 | 附带一份权威结果，做状态审计  |
| `error`   | object | 条件 | failed 必须携带错误信息 |
| `usage`   | object | 条件 | 资源消耗统计，包含：<br>- `promptToken` (Int?)<br>- `completionToken` (Int?)<br>- `reasoningToken` (Int?) (Reasoning/Thinking Tokens)<br>- `tokenCost` (Int?) (Total Tokens)<br>- `moneyCost` (Float?)<br>- `timeCost` (Float?) (Seconds) |

#### 7.1.3 挂起 / 恢复流程示意图（suspended / resuming）

> 目标：让观察侧能够把“等待用户输入/授权”的停顿显式建模为状态流的一部分。
>
> 重要约定（按你们当前的流程）：
> - **一旦进入 suspended，执行会挂起且通常会断流**（本次流结束）。
> - **恢复/重启属于新建的一段流**（新的订阅会话/新的推送通道），但仍可沿同一 `trace_id` 继续展示；`run_id` 往往会变化，用 `run_path` 串起“同一逻辑执行”的多次运行链。

```text
时间 ───────────────────────────────────────────────────────────────────▶

流 A（挂起前，正常推送的事件流）:

  run.lifecycle.created
    │  (开始执行；created 的信封必须携带 executor_metadata / user_metadata)
    │
    ├─ run.lifecycle.running*                      （可选心跳）
    │
    ├─ …（任意 data flow：text/reasoning/action/...）
    │
    ├─ control.interrupt                           （可选：请求确认/授权/补充输入；携带 resume_token）
    │
    └─ run.lifecycle.suspended                     （必须：reason；可选：awaiting）
           └─ awaiting 示例：{ "kind": "approval" | "form" | "text", "fields": [...] }

    —— 断流/挂起：执行进入等待态，本次事件流结束 ——


流 B（恢复后，重启/重新订阅产生的新事件流）:

  run.lifecycle.resuming                           （必须：resume_context；不需要 input_data）
    ├─ resume_context.breakpoint_trace_id          （断点位置 trace_id）
    ├─ resume_context.breakpoint_type              （message/action/tool_call）
    └─ resume_context.conversation_id?             （可选）

  run.lifecycle.running*                           （可选心跳）
  …（继续 data flow）
  run.lifecycle.completed | failed | cancelled

备注：
- 同一条执行链可能出现多次 suspended/resuming（多轮交互），每次挂起都可能结束当前流。
- 若恢复/重启产生新的 run_id（推荐），用 run_path 表达运行链关系：旧 run_id 作为 run_path 前缀，新 run_id 追加在末尾。
- 观察侧可结合 since_timestamp 做断线续订与去重；但语义边界仍以 lifecycle 事件为准。
```

---

### 7.2 Data Flow：`content.reasoning.*`（ReAct：思考流）

> 用于表达“推理/反思”过程。是否展示由产品策略决定，但协议允许完整表达与回放。

#### 7.2.1 事件枚举

* `content.reasoning.start`
* `content.reasoning.delta`
* `content.reasoning.end`（权威最终态，强制）

#### 7.2.2 payload 结构

**start**

| 字段       | 类型     | 必填 | 说明                         |
| -------- | ------ | -: | -------------------------- |
| `format` | string |  否 | `plain` / `markdown` / ... |

**delta**

| 字段      | 类型     | 必填 | 说明     |
| ------- | ------ | -: | ------ |
| `delta` | string |  是 | 思考增量片段 |

**end（权威复核）**

| 字段          | 类型     | 必填 | 说明                |
| ----------- | ------ | -: | ----------------- |
| `full_text` | string |  是 | 权威最终文本，用于复核/纠偏/回放 |

---

### 7.3 Data Flow：`content.text.*`（ReAct：可见文本流）

用于用户可见文本输出（对话文本）。

#### 7.3.1 事件枚举

* `content.text.start`
* `content.text.delta`
* `content.text.end`（权威最终态，强制）

#### 7.3.2 payload 结构

同 reasoning，但语义为“可见文本”。

* start: `payload.format` 必填

| 字段       | 类型     | 必填 | 说明                         |
| -------- | ------ | -: | -------------------------- |
| `format` | string |  否 | `plain` / `markdown` / ... |

* delta：`payload.delta` 必填
* end：`payload.full_text` 必填（权威复核结果，不可选）

---

### 7.4 Data Flow：`content.action.*`（ReAct：行动参数流）

用于表达“调用了什么行动（工具/子 agent/外部 API）以及参数是什么”，并支持参数流式生成。
在观察侧视角中，`content.action.*` 用于打开一个“行动容器”，其后应紧跟该行动触发的子流程生命周期与内部事件（经挂载后发布），以便上层视图呈现完整的调用过程。

`content.action.*`类型下 外部信封需要挂载： `action_id`，`ReAct_id`  string    是   关联的 action 容器 ID。

#### 7.4.1 事件枚举

* `content.action.start`（容器打开/参数开始）
* `content.action.delta`（参数增量；强烈建议存在）
* `content.action.end`（权威最终参数；强制）

#### 7.4.2 payload 结构

**start**

| 字段                 | 类型     | 必填 | 说明                                  |
| ------------------ | ------ | -: | ----------------------------------- |
| `name`             | string |  是 | 行动名（建议稳定可定位，如 `tool_name@project`）  |
| `intent`             | string |  否 | 行动意图，可能预置，也可能在delta中流式生成  |
| `call_type`        | string |  否 | `TOOL` / `AGENT` / `LLM` / `CHARACTER` / `API` |
| `arguments_schema` | string |  否 | 参数格式              |

信封须携带： `action_id`，`ReAct_id`  string    是   关联的 action 容器 ID。

**delta（重要：流式下的核心载体）**

| 字段      | 类型            | 必填 | 说明                             |
| ------- | ------------- | -: | ------------------------------ |
| `delta` | string |  是 | 参数增量片段（格式取决于 arguments_format） |
| `part`      | string   |  是 | `intent` / `args`          |

信封须携带： `action_id`，`ReAct_id`  string    是   关联的 action 容器 ID。

**end（权威最终参数）**

| 字段          | 类型            | 必填 | 说明                 |
| ----------- | ------------- | -: | ------------------ |
| `arguments` | object |  是 | 权威最终参数（用于复核、审计、重放） |
| `intent`    | string        |  否 | 执行意图描述                       |


信封须携带： `action_id`，`ReAct_id`  string    是   关联的 action 容器 ID。

#### 7.4.3 关于“动作容器的稳定键”

* 并发 action 场景下，Observer 必须有稳定键把事件聚到正确的 action 卡片
* 推荐稳定键为：该 action 派生的**直接子执行域 ID**
* 工程上表现为：该 action 相关事件统一携带同一个 `trace_path[0]`（挂载后）

因此，Forwarder/Runtime 在可能情况下应做到：

* 在 `content.action.start` 时就能确定子执行域标识，并让它在对外事件中体现为 `trace_path[0]`
* 若当下无法确定，必须在后续第一条子执行域生命周期事件到达时建立映射，并保证观察侧能完成归属（工程层可通过“待绑定容器”实现）

---

### 7.5 Data Flow：`content.action.result.*`（ReAct：行动结果流）

该流是 ReAct 的“观察输入”。它表达“某次行动对应的子流程最终交付”，并对调用方提供统一的结果接口。
在事件序列上，该结果流应位于该子流程的生命周期范围内；其核心来源是子流程的 `content.agent.result.*`，由 Forwarder 转换生成并向上发布。调用方关注的权威输入以 `content.action.result.end` 为准，子流程的其他过程事件主要用于上层视图与审计。

#### 7.5.1 事件枚举

* `content.action.result.start`
* `content.action.result.delta`
* `content.action.result.end`（权威最终结果；强制）

#### 7.5.2 payload 结构

**start**


| 字段            | 类型     | 必填 | 说明                                                              |
| ------------- | ------ | -: | --------------------------------------------------------------- |
| `record_id`      | string |  是 |  执行动作对应的记录id（本质上是动作执行时对应的子trace id）                |
| `status`      | string |  否 | `success` / `error`（可用于 UI 提前渲染状态）。                 |
| `mode`        | string |  否 | 交付物类型声明，例如 `json` / `text` / `binary`。                          |
| `json_schema` | object |  否 | 当 `mode=json` 时用于声明 schema（若有）。                                 |



**delta（重要：可能是流式结果）**
                                           |


| 字段          | 类型       | 必填 | 说明                                                             |
| ----------- | -------- | -: | -------------------------------------------------------------- |
| `part`      | string   |  是 | `reasoning` / `title` / `summary` / `output` / `error`。          |
| `delta`     | string   |  是 | 对应 `part` 的增量片段。                                               |
| `key_path`  | string[] |  否 | 结构化结果的字段路径（当 `mode=json` 且需增量落点时使用），如 `["items","0","title"]`。 |


**end（权威最终结果）**

| 字段                 | 类型     | 必填 | 说明                                                                     |
| ------------------ | ------ | -: | ---------------------------------------------------------------------- |
| `status`      | string |  否 | `success` / `error`（可用于 UI 提前渲染状态）。                 |
| `full_result`      | any    |  是 | **权威最终结果**（调用方关注的稳定输入口径）。     `summary`/`title`/`error`/ `thought`/`output`                                    |
| `usage`            | object |  否 | 消耗统计（同 run.lifecycle.completed.usage）。 |
| `mode`             | string |  否 | `json` / `text` / `binary`；建议与 `result.start` 一致；若未发送 start，可在 end 补齐。 |
| `json_schema`      | object |  否 | 当 `mode=json` 时用于声明 schema（若有）。                                        |
| `images` / `files` | any    |  否 | 可选引用（图片/文件句柄或引用信息）。                                                    |

#### 7.5.3 从子流程 `content.agent.result.*` 的转换规则（Forwarder）

* 子流程 `content.agent.result.start` → `content.action.result.start`
* 子流程 `content.agent.result.delta` → `content.action.result.delta`（若存在）
* 子流程 `content.agent.result.end` → `content.action.result.end`（必须）
* 转换后的事件应保持与该行动容器一致的聚合锚点（同一 `trace_path[0]`、同一 `action_id`），以便调用方与观察侧稳定归属

---

### 7.6 Data Flow：`content.agent.result.*`（当前执行者的返回数据流）

与 `content.action.result.*` 的区别：

* `action.result` 表达“某次行动对应的子流程最终交付”（供调用方使用）
* `agent.result` 表达“当前执行者自身的最终交付物/返回值”

#### 7.6.1 事件枚举

* `content.agent.result.start`
* `content.agent.result.delta`
* `content.agent.result.end`（权威最终交付；强制）

### 7.6.2 payload 字段

**`content.agent.result.start.payload`：**



| 字段            | 类型     | 必填 | 说明                                     |
| ------------- | ------ | -: | -------------------------------------- |
| `mode`        | string |  否 | 交付物类型声明，例如 `json` / `text` / `binary`。 |
| `json_schema` | object |  否 | 当 `mode=json` 时用于声明 schema（若有）。        |

> 说明：`mode/json_schema` 是**“交付物类型指明”**的关键元信息；观察侧可据此选择解析/渲染策略（结构化表格、代码块、二进制下载等）。

**`content.agent.result.delta.payload`：**

| 字段         | 类型       | 必填 | 说明                                                                          |
| ---------- | -------- | -: | --------------------------------------------------------------------------- |
| `part`     | string   |  是 | 增量片段所属语义段；实现侧常用 `output` / `reasoning` / `error` / `title` / `summary` 等（若已有固定枚举，以实现为准）。 |
| `delta`    | string   |  是 | 对应 `part` 的增量内容。                                                            |
| `key_path` | string[] |  否 | 结构化结果的字段路径（当 `mode=json` 且需增量落点时使用）。                                        |

**`content.agent.result.end.payload`（权威最终结果 end；建议必填）**：

| 字段            | 类型     | 必填 | 说明                                                                     |
| ------------- | ------ | -: | ---------------------------------------------------------------------- |
| `status`      | string |  否 | `success` / `error`（可用于 UI 提前渲染状态）。                 |
| `full_result` | any    |  是 | **权威最终结果**（建议必填）。       `summary`/`title`/`error`/ `thought`/`output`                                                |
| `mode`        | string |  否 | `json` / `text` / `binary`；建议与 `result.start` 一致；若未发送 start，可在 end 补齐。 |
| `json_schema` | object |  否 | 当 `mode=json` 时用于声明 schema（若有）。                                        |
| `images` / `files` | any    |  否 | 可选引用（图片/文件句柄或引用信息）。                                                    |


**上游折叠规则：**

* 当该 run 是某个 `content.action.*` 容器的子流程时，转发侧应将 `content.agent.result.end.payload.full_result` 折叠为父流程的 `content.action.result.end.payload.full_result`，以形成调用方关注的稳定输入口径。


---

### 7.7 Control Flow：`control.*`（中断/回滚/建议）

#### 7.7.1 `control.interrupt`

用于请求外部输入/确认，通常与安全授权、审计相关。

强调“可交互恢复”。Producer/Forwarder 发出 interrupt 后，观察侧（UI/调用方）应基于 `resume_token` 在用户完成确认/补充输入后触发恢复；恢复后的事件通常会在**新建的事件流**中继续推送（见 7.1.3）。

**payload**

| 字段               | 类型     | 必填 | 说明                      |
| ---------------- | ------ | -: | ----------------------- |
| `interrupt_id`   | string |  是 | 中断事件 ID（用于去重、审计与交互回填）。 |
| `type`           | string |  是 | 中断类型：`approval`（需要确认/授权） / `input_request`（需要补充输入）。 |
| `reason`         | string |  是 | 中断原因（面向人可读摘要）。 |
| `action_id`      | string |  否 | 关联到具体行动容器（用于精确授权/确认）。 |
| `action_name`    | string |  否 | 行动名称（用于 UI 展示）。 |
| `action_parameters` | object |  否 | 行动参数（用于 UI 展示与用户确认）。 |
| `required`       | string |  否 | 交互约束（自由文本或标识符），提示必填要求。 |
| `expected_fields`| string[] |  否 | 期望用户补充的字段名列表（用于表单型输入）。 |
| `timeout_seconds`| number |  否 | 等待超时时间（秒）。 |
| `data`           | any    |  否 | 扩展数据（实现侧自定义，用于 UI/业务上下文）。 |
| `resume_token`   | string |  是 | 恢复令牌（观察侧在恢复请求中必须带回）。 |

#### 7.7.2 `control.rollback`

请求观察侧逻辑回退到某个时间点（展示截断与回放语义）。

**payload**

| 字段                 | 类型     | 必填 | 说明                    |
| ------------------ | ------ | -: | --------------------- |
| `target_timestamp` | number |  是 | 回滚目标：观察侧应丢弃此时间之后的展示状态 |
| `reason`           | string |  是 | 回滚原因                  |

#### 7.7.3 `control.suggestions`

给出下一步操作建议（重试/换模型/继续等）。

**payload**

| 字段               | 类型     | 必填 | 说明                                        |
| ---------------- | ------ | -: | ----------------------------------------- |
| `suggestions`          | array  |  是 | 建议列表                                      |
| `suggestions[].type`   | string |  是 | `retry` / `resume` / `switch_model` / ... |
| `suggestions[].label`  | string |  是 | 展示文案                                      |
| `suggestions[].params` | object |  否 | 建议所需参数                                    |

---

## 8. Start / Delta / End 的强约束与非流式合并规则

### 8.1 强约束（所有数据流通用）

对以下所有数据流，必须满足：

* `content.reasoning.*`
* `content.text.*`
* `content.action.*`
* `content.action.result.*`
* `content.agent.result.*`

强约束如下：

1. **End 必须出现，且是权威最终态**

   * end 不可省略
   * end 的 full 字段（`full_text` / `arguments` / `full_result`）用于复核与纠偏，是协议语义的一部分，不是“可选的最终汇总”

2. **Delta 是流式下的核心载体**

   * 协议以流式为默认：大多数场景应出现多个 delta
   * 消费者必须支持基于 delta 的实时渲染与增量聚合
   * end 用于收敛与复核，不应替代 delta 的实时价值

3. **Start 是开始标记**

   * 用于界定一个内容段/参数段/结果段的开始
   * 便于 UI 建立容器与状态（如“开始生成文本”“开始生成参数”“开始产生结果”）

### 8.2 非流式兼容：start 与 end 可合并

当执行者处于非流式模式（一次性返回，不产生中间增量）时：

* 允许把 `*.start` 与 `*.end` 合并为单条 `*.end`
* 但 **end 仍必须存在**，且必须包含权威最终字段
* delta 在非流式模式下可以为 0 次（这是兼容特例）

建议工程约定：

* `streaming=true` 为默认
* `streaming=false` 时允许只发 end

---

## 9. 样例 JSON：从简单到复杂

> 说明：以下样例省略部分可选字段以突出关键结构。生产系统可携带更完整的 `executor_metadata` 与 `user_metadata`。

### 9.1 简单：流式 text 输出（单执行者）

**start → delta×N → end（权威）**

```json
[
  {
    "type": "run.lifecycle.created",
    "timestamp": 1734900000000.100,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "payload": { "input_data": { "prompt": "写一段简介" } },
    "react_id":"react_round1",
    "user_metadata": {"id":"user_001","firstname" :"明照","lastname":"张","username" :"zhangmingzhao","email":"zmz@gamil.com","avatar_uri":"/pic/pic123.jpg"},
    "executor_metadata": { "name": "Root Agent", "version": "v1" }
  },
  {
    "type": "content.text.start",
    "timestamp": 1734900000001.000,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "react_id":"react_round1",
    "payload": { "format": "plain" }
  },
  {
    "type": "content.text.delta",
    "timestamp": 1734900000001.200,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "react_id":"react_round1",
    "payload": { "delta": "这是" }
  },
  {
    "type": "content.text.delta",
    "timestamp": 1734900000001.400,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "react_id":"react_round1",
    "payload": { "delta": "一段简介。" }
  },
  {
    "type": "content.text.end",
    "timestamp": 1734900000001.900,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "react_id":"react_round1",
    "payload": { "full_text": "这是一段简介。" }
  },
  {
    "type": "run.lifecycle.completed",
    "timestamp": 1734900000002.000,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "react_id":"react_round1",
    "payload": { "summary": { "status": "ok" } }
  }
]
```

---

### 9.2 非流式：start 与 end 合并（兼容特例）

```json
[
  {
    "type": "content.text.end",
    "timestamp": 1734900000100.000,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "react_id":"react_round1",
    "payload": { "full_text": "一次性返回的文本。" }
  }
]
```

---

### 9.3 ReAct：一轮 reasoning，并发两个 action（含子流程 lifecycle、子 agent.result 与 action.result 转换）

> 关键观察点：
>
> * 同一轮 `ReAct_id = T1`
> * 并发两个 action：容器键分别落到 `action_id = C1` 与 `C2`
> * `content.action.end` 是权威最终参数
> * 子流程在 `content.action.*` 之后进入其 `run.lifecycle.*`
> * 子流程的 `content.agent.result.*` 产生后，转换生成 `content.action.result.*`，其中 `content.action.result.end` 为调用方关注的权威输入
> * 子流程的其他过程事件用于上层视图与审计

```json
[
  {
    "type": "content.agent.result.start",
    "timestamp": 1700000001490.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000020",
    "run_id": "00000000-0000-0000-0000-000000000120",
    "executor_id": "TOOL:search@proj_001",
    "action_id": "call_001",
    "payload": {
      "mode": "json",
      "json_schema": { "type": "object", "properties": { "items": { "type": "array" } } }
    }
  },
  {
    "type": "content.agent.result.delta",
    "timestamp": 1700000001495.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000020",
    "run_id": "00000000-0000-0000-0000-000000000120",
    "executor_id": "TOOL:search@proj_001",
    "action_id": "call_001",
    "payload": {
      "part": "output",
      "delta": "a",
      "key_path": ["items",0]
    }
  },
  {
    "type": "content.agent.result.delta",
    "timestamp": 1700000001496.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000020",
    "run_id": "00000000-0000-0000-0000-000000000120",
    "executor_id": "TOOL:search@proj_001",
    "action_id": "call_001",
    "payload": {
      "part": "output",
      "delta": "b",
      "key_path": ["items",1]
    }
  },
  {
    "type": "content.agent.result.end",
    "timestamp": 1700000001500.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000020",
    "run_id": "00000000-0000-0000-0000-000000000120",
    "executor_id": "TOOL:search@proj_001",
    "action_id": "call_001",
    "payload": {
      "mode": "json",
      "json_schema": { "type": "object", "properties": { "items": { "type": "array" } } },
      "full_result": { "items": ["a", "b"] }
    }
  },

  {
    "type": "content.action.result.start",
    "timestamp": 1700000001506.0,
    "worker_id": "hostA:0",
    "trace_id": "00000000-0000-0000-0000-000000000010",
    "run_id": "00000000-0000-0000-0000-000000000102",
    "executor_id": "AGENT:assistant@proj_001",
    "action_id": "call_001",
    "react_id":"react_round2",
    "payload": {
      "status": "running",
      "mode": "json",
      "json_schema": { "type": "object", "properties": { "items": { "type": "array" } } }
    }
  },
  {
    "type": "content.action.result.delta",
    "timestamp": 1700000001508.0,
    "worker_id": "hostA:0",
    "trace_id": "00000000-0000-0000-0000-000000000010",
    "run_id": "00000000-0000-0000-0000-000000000102",
    "executor_id": "AGENT:assistant@proj_001",
    "react_id":"react_round2",
    "action_id": "call_001",
    "payload": {
      "part": "output",
      "delta": "a",
      "key_path": ["items",0]
    }
  },
  {
    "type": "content.action.result.delta",
    "timestamp": 1700000001509.0,
    "worker_id": "hostA:0",
    "trace_id": "00000000-0000-0000-0000-000000000010",
    "run_id": "00000000-0000-0000-0000-000000000102",
    "executor_id": "AGENT:assistant@proj_001",
    "react_id":"react_round2",
    "action_id": "call_001",
    "payload": {
      "part": "output",
      "delta": "b",
      "key_path": ["items",1]
    }
  },
  {
    "type": "content.action.result.end",
    "timestamp": 1700000001510.0,
    "worker_id": "hostA:0",
    "trace_id": "00000000-0000-0000-0000-000000000010",
    "run_id": "00000000-0000-0000-0000-000000000102",
    "executor_id": "AGENT:assistant@proj_001",
    "react_id":"react_round2",
    "action_id": "call_001",
    "payload": {
      "mode": "json",
      "json_schema": { "type": "object", "properties": { "items": { "type": "array" } } },
      "full_result": { "items": ["a", "b"] }
    }
  }
]
```

##### “delta 的细节 体现 `key_path` 的“字段落点”价值。

```json
[
  {
    "type": "content.agent.result.start",
    "timestamp": 1700000001600.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000021",
    "run_id": "00000000-0000-0000-0000-000000000121",
    "executor_id": "TOOL:extractor@proj_001",
    "payload": { 
        "mode": "json", 
        "json_schema": { 
          "type": "object", 
          "properties": { 
            "company":  { 
              "type": "object", 
              "properties": {
                "name":{"type":"string"},
                "employee_count":{"type":"int"},
              }
            } 
          }
        }
      }
  },
  {
    "type": "content.agent.result.delta",
    "timestamp": 1700000001605.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000021",
    "run_id": "00000000-0000-0000-0000-000000000121",
    "executor_id": "TOOL:extractor@proj_001",
    "payload": {
      "part": "output",
      "delta": "\"ACME\"",
      "key_path": ["company", "name"]
    }
  },
  {
    "type": "content.agent.result.delta",
    "timestamp": 1700000001610.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000021",
    "run_id": "00000000-0000-0000-0000-000000000121",
    "executor_id": "TOOL:extractor@proj_001",
    "payload": {
      "part": "output",
      "delta": "42",
      "key_path": ["company", "employee_count"]
    }
  },
  {
    "type": "content.agent.result.end",
    "timestamp": 1700000001620.0,
    "worker_id": "hostB:0",
    "trace_id": "00000000-0000-0000-0000-000000000021",
    "run_id": "00000000-0000-0000-0000-000000000121",
    "executor_id": "TOOL:extractor@proj_001",
    "payload": {
      "mode": "json",
      "full_result": { "company": { "name": "ACME", "employee_count": 42 } }
    }
  }
]
```

---

### 9.4 当前执行者最终交付：`content.agent.result.*`（权威 end）

```json
[
  {
    "type": "content.agent.result.start",
    "timestamp": 1734900002000.000,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "payload": { "meta": { "kind": "final_answer" } }
  },
  {
    "type": "content.agent.result.delta",
    "timestamp": 1734900002000.200,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "payload": { "delta": "北京今天25度晴天，空气质量良" }
  },
  {
    "type": "content.agent.result.delta",
    "timestamp": 1734900002000.200,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "payload": { "delta": "（AQI 80）。" }
  },
  {
    "type": "content.agent.result.end",
    "timestamp": 1734900002000.800,
    "trace_id": "R",
    "run_id": "R1",
    "worker_id": "hostA:0",
    "executor_id": "AGENT:root@proj",
    "executor_type": "AGENT",
    "payload": { "full_result": "北京今天25度晴天，空气质量良（AQI 80）。" }
  }
]
```

---

## 10. 兼容性与扩展规范

1. 向后兼容：新增字段不得破坏旧消费者；旧消费者应忽略未知字段
2. 命名空间稳定：新增事件类型必须归入 `run.lifecycle` / `content` / `control`
3. 权威 end 不变：任何新增数据流类型必须提供 end（权威最终态）
4. 流式优先：若定义 delta，则应假设其在主路径中大量出现，消费者必须高效处理
5. 嵌套规则不变：执行者独立运行；挂载在 Forwarder 完成；观察侧视角一致

---

# 附录 A：建议的“最小可落地实现”路线（工程建议）

虽然本文档是协议层，但为便于落地，可按以下路径逐步实施：

1. 先实现 `run.lifecycle.*` + `content.text.*`（含 start/delta/end 与权威 end）
2. 再实现 `content.action.*` + 子流程 `run.lifecycle.*` + 子流程 `content.agent.result.*` + 转换生成 `content.action.result.*`
3. 再实现并发容器归属（trace_path 与 executor_path 修补）
4. 最后实现 `control.*`（interrupt / rollback / suggestions），并与授权系统联动