> ## Documentation Index
> Fetch the complete documentation index at: https://docs.qoder.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Session & Event 数据结构

> 适用于 Forward Session API 的 Session 与 Event 相关数据结构说明。

## Session 对象

创建、获取、列出、更新和归档 Session 的接口都会返回该对象。

```
{
  "id": "sess_xxx",
  "type": "session",
  "identity_id": "idn_xxx",
  "template": {
    "id": "tmpl_support",
    "type": "template",
    "name": "客服助手",
    "model": "ultimate",
    "version": 3
  },
  "source_type": "api",
  "status": "idle",
  "title": "客户支持会话",
  "incremental_streaming_enabled": false,
  "metadata": {
    "source": "web",
    "biz_id": "ticket_123"
  },
  "config": {
    "environment_variables": {
      "API_KEY": "sk-xxx"
    }
  },
  "stats": {
    "active_seconds": 30,
    "duration_seconds": 3600
  },
  "usage": {
    "credits": 12.5
  },
  "archived_at": null,
  "created_at": "2026-06-22T10:00:00Z",
  "updated_at": "2026-06-22T11:00:00Z"
}
```

| 字段                              | 类型             | 必返 | 说明                                                                                                            |
| ------------------------------- | -------------- | -- | ------------------------------------------------------------------------------------------------------------- |
| `id`                            | string         | 是  | `sess_`\ 前缀的 Session ID。                                                                                      |
| `type`                          | string         | 是  | 固定为\ `"session"`。                                                                                             |
| `identity_id`                   | string         | 是  | Forward Identity ID，表示该 Session 归属的终端用户身份。                                                                    |
| `template`                      | object         | 是  | Forward Template 摘要，字段见 [Template 摘要](#template-摘要)。                                                          |
| `source_type`                   | string         | 是  | Session 来源：`api`、`im`\ 或\ `schedule`。                                                                         |
| `status`                        | string         | 是  | Session 运行状态：`idle`、`running`、`rescheduling`、`canceling`\ 或\ `terminated`。归档状态通过\ `archived_at`\ 表达。          |
| `title`                         | string         | 是  | Session 标题。                                                                                                   |
| `incremental_streaming_enabled` | boolean        | 是  | 是否为该 Session 开启旧版增量流式事件。创建时省略则为\ `false`，创建后不支持修改。该能力兼容保留，不推荐新接入使用；新接入建议通过订阅事件流接口的 `event_deltas[]` 使用流式增量事件。 |
| `metadata`                      | object         | 否  | 调用方业务元数据。                                                                                                     |
| `config`                        | object         | 否  | Session 配置；未传入时可能省略。                                                                                          |
| `config.environment_variables`  | object         | 否  | 会话级环境变量，key-value 形式。                                                                                         |
| `stats`                         | object         | 否  | Session 统计信息，字段见 [Session stats](#session-stats)。                                                             |
| `usage`                         | object         | 否  | 用量信息；相关计费模块未启用时可能省略。                                                                                          |
| `usage.credits`                 | number         | 否  | Credit 消耗。                                                                                                    |
| `archived_at`                   | string \| null | 是  | 归档时间，未归档时为\ `null`。                                                                                           |
| `created_at`                    | string         | 是  | 创建时间，RFC 3339 格式。                                                                                             |
| `updated_at`                    | string         | 是  | 最近更新时间，RFC 3339 格式。                                                                                           |

## Template 摘要

| 字段        | 类型      | 必返 | 说明                     |
| --------- | ------- | -- | ---------------------- |
| `id`      | string  | 是  | Forward Template ID。   |
| `type`    | string  | 是  | 固定为\ `"template"`。     |
| `name`    | string  | 是  | Template 名称。           |
| `model`   | string  | 是  | Template 使用的模型档位或模型标识。 |
| `version` | integer | 是  | Template 版本号。          |

## Session stats

| 字段                 | 类型      | 必返 | 说明                                   |
| ------------------ | ------- | -- | ------------------------------------ |
| `active_seconds`   | integer | 否  | 活跃处理时长，单位秒；新 Session 通常为\ `0`。       |
| `duration_seconds` | integer | 否  | Session 持续时长，单位秒；新 Session 通常为\ `0`。 |

## Event 对象

接口返回的 Event 是按 `type` 变化的 JSON 对象。所有返回 Event 都包含通用字段，不同事件类型会携带不同的 payload 字段。

```
{
  "id": "evt_xxx",
  "type": "agent.message",
  "session_id": "sess_xxx",
  "content": [
    {
      "type": "text",
      "text": "这是分析结果。"
    }
  ],
  "processed_at": "2026-06-22T11:00:03Z"
}
```

| 字段             | 类型     | 必返 | 说明                                               |
| -------------- | ------ | -- | ------------------------------------------------ |
| `id`           | string | 是  | `evt_`\ 前缀的 Event ID。                            |
| `type`         | string | 是  | Event 类型。                                        |
| `session_id`   | string | 是  | Event 所属 Session ID。                             |
| `processed_at` | string | 否  | 事件被处理的时间，RFC 3339 格式。部分 agent 生成事件或增量事件可能不包含该字段。 |

按事件类型允许出现的 payload 字段如下。表中不重复列出通用字段 `id`、`type`、`session_id` 和 `processed_at`。

| Event 类型                    | 允许字段                                                    |
| --------------------------- | ------------------------------------------------------- |
| `user.message`              | `content`                                               |
| `user.interrupt`            | 无                                                       |
| `user.tool_confirmation`    | `tool_use_id`、`result`、`deny_message`                   |
| `user.tool_result`          | `tool_use_id`、`content`、`is_error`                      |
| `user.custom_tool_result`   | `custom_tool_use_id`、`content`、`is_error`               |
| `user.define_outcome`       | `description`、`rubric`、`outcome_id`、`max_iterations`    |
| `system.message`            | `content`                                               |
| `agent.message`             | `content`                                               |
| `agent.thinking`            | `thinking`、`text`                                       |
| `agent.message_start`       | `message_id`、`message`                                  |
| `agent.content_block_start` | `message_id`、`index`、`content_block`                    |
| `agent.content_block_delta` | `message_id`、`index`、`delta`                            |
| `agent.content_block_stop`  | `message_id`、`index`                                    |
| `agent.message_delta`       | `message_id`、`delta`、`usage`                            |
| `agent.message_stop`        | `message_id`                                            |
| `event_start`               | `event`                                                 |
| `event_delta`               | `event_id`、`delta`                                      |
| `agent.tool_use`            | `name`、`input`、`evaluated_permission`                   |
| `agent.tool_result`         | `tool_use_id`、`content`、`is_error`                      |
| `agent.custom_tool_use`     | `name`、`input`                                          |
| `agent.mcp_tool_use`        | `mcp_server_name`、`name`、`input`、`evaluated_permission` |
| `agent.mcp_tool_result`     | `mcp_tool_use_id`、`content`、`is_error`                  |
| `agent.artifact_delivered`  | `file_id`、`original_filename`、`size`、`content_type`     |
| `session.status_running`    | 无                                                       |
| `session.status_idle`       | `stop_reason`                                           |
| `session.status_terminated` | 无                                                       |
| `session.error`             | `error`                                                 |
| `session.updated`           | `agent`、`metadata`、`title`                              |

## 客户端可发送事件类型

`POST /api/v1/forward/sessions/{session_id}/events` 只接受以下事件类型。

| 类型                        | 必填字段                   | 说明                                                                          |
| ------------------------- | ---------------------- | --------------------------------------------------------------------------- |
| `user.message`            | `content`              | 用户消息。`content`\ 必须是非空 content block 数组，支持\ `text`、`image`、`document`\ 等块类型。 |
| `user.interrupt`          | 无                      | 请求中断当前处理。                                                                   |
| `user.tool_confirmation`  | `tool_use_id`、`result` | 工具调用确认。`result`\ 为\ `allow`\ 或\ `deny`；拒绝时可传\ `deny_message`。               |
| `user.tool_result`        | `tool_use_id`          | 返回内置工具结果；`content`\ 和\ `is_error`\ 可选。                                      |
| `user.custom_tool_result` | `custom_tool_use_id`   | 返回客户端自定义工具结果；`content`\ 和\ `is_error`\ 可选。                                  |
| `user.define_outcome`     | `description`、`rubric` | 定义期望结果和评判标准；`max_iterations`\ 可选。                                           |

`system.message` 是公开 Event 类型，但不作为 Forward 客户端写入事件开放。

## 公开事件类型

查询历史和订阅 SSE 事件流时，可能收到以下公开事件类型；其中 `event_start` 和 `event_delta` 仅在订阅 SSE 且传入 `event_deltas[]` 时可能返回：

`user.message`、`user.interrupt`、`user.tool_confirmation`、`user.tool_result`、`user.custom_tool_result`、`user.define_outcome`、`system.message`、`agent.message`、`agent.thinking`、`agent.message_start`、`agent.content_block_start`、`agent.content_block_delta`、`agent.content_block_stop`、`agent.message_delta`、`agent.message_stop`、`event_start`、`event_delta`、`agent.tool_use`、`agent.tool_result`、`agent.custom_tool_use`、`agent.mcp_tool_use`、`agent.mcp_tool_result`、`agent.artifact_delivered`、`session.status_running`、`session.status_idle`、`session.status_terminated`、`session.error` 和 `session.updated`。

## 增量流式事件

Forward 当前支持两套增量流式事件：

* 推荐新接入使用流式增量事件：在订阅 Session Event Stream 时传入 `event_deltas[]`。
* 旧版增量流式事件由创建 Session 时的 `incremental_streaming_enabled` 控制，能力仍然保留但不推荐新接入使用。

### 流式增量事件

流式增量事件通过订阅 Session Event Stream 接口的 `event_deltas[]` 查询参数开启。支持重复传参，允许值如下：

| `event_deltas[]` 取值 | 说明                      |
| ------------------- | ----------------------- |
| `agent.message`     | 订阅 assistant 文本消息的增量内容。 |
| `agent.thinking`    | 订阅 thinking 的增量内容。      |

开启后，SSE 事件流中可能额外返回以下两类顶层 Event：

| Event 类型      | 关键字段               | 说明                                                              |
| ------------- | ------------------ | --------------------------------------------------------------- |
| `event_start` | `event`            | 表示某个公开事件开始生成。`event` 中只保留 `id`、`type`、`name`、`mcp_server_name`。 |
| `event_delta` | `event_id`、`delta` | 表示某个公开事件的增量片段。`event_id` 指向对应的事件。                               |

`event_start.event` 字段：

| 字段                | 类型     | 说明                                                       |
| ----------------- | ------ | -------------------------------------------------------- |
| `id`              | string | 对应事件的 Event ID。                                          |
| `type`            | string | 对应事件的公开 Event 类型，当前为 `agent.message` 或 `agent.thinking`。 |
| `name`            | string | 预留字段；当前 `event_deltas[]` 不支持工具调用类 selector，通常不会返回。       |
| `mcp_server_name` | string | 预留字段；当前 `event_deltas[]` 不支持 MCP 工具调用类 selector，通常不会返回。  |

`event_delta.delta` 字段：

| 字段             | 类型      | 说明                           |
| -------------- | ------- | ---------------------------- |
| `type`         | string  | 增量类型，例如 `content_delta`。     |
| `index`        | integer | content block 下标。            |
| `content`      | object  | 增量内容。当前只透出 `type` 和 `text`。  |
| `content.type` | string  | 内容类型，例如 `text` 或 `thinking`。 |
| `content.text` | string  | 本次增量文本片段。                    |

`event_start` 示例：

```json theme={null}
{
  "id": "evt_xxx",
  "type": "event_start",
  "session_id": "sess_xxx",
  "event": {
    "id": "evt_xxx",
    "type": "agent.message"
  }
}
```

`event_delta` 示例：

```json theme={null}
{
  "id": "evt_xxx",
  "type": "event_delta",
  "session_id": "sess_xxx",
  "event_id": "evt_xxx",
  "delta": {
    "type": "content_delta",
    "index": 0,
    "content": {
      "type": "text",
      "text": "这是"
    }
  }
}
```

流式增量事件解析约定：

* 只有订阅 SSE 事件流且传入 `event_deltas[]` 时，才会返回 `event_start` / `event_delta`；历史查询不返回这类流式增量事件。
* 最终完整公开事件仍会返回。客户端可使用流式增量事件做即时展示，再以最终完整事件作为持久化或展示校准结果。
* `include_thinking=false` 时，会过滤 `agent.thinking` 事件开始信号和 `delta.content.type=thinking` 的增量片段。
* `include_tool_calls=false` 不影响 `event_deltas[]` 当前支持的 `agent.message` 和 `agent.thinking` 流式增量事件，但仍会过滤普通工具调用事件和旧版工具输入/输出 delta。
* 若 Session 创建时设置了 `incremental_streaming_enabled=true`，该 Session 使用旧版流式能力，订阅接口中的 `event_deltas[]` 不会启用流式增量事件。

### 旧版增量流式事件

旧版增量流式事件由创建 Session 时的 `incremental_streaming_enabled` 字段控制，不通过查询历史或订阅 SSE 的请求参数控制。该能力仍然保留用于兼容既有客户端，但不推荐新接入使用：

* `true`：事件流会在最终完整 `agent.message` 之前返回 assistant 输出片段；历史查询也会返回同一批增量事件。
* `false` 或省略：保持普通模式，只返回完整公开事件，不返回增量事件。

开启旧版增量流式后，最终完整的 `agent.message` 仍会返回。客户端可使用增量事件做即时展示，再以最终 `agent.message` 作为持久化或展示校准结果。

旧版顶层增量事件类型只有以下 6 种：

| 事件类型                        | 关键字段                                 | 说明                                                       |
| --------------------------- | ------------------------------------ | -------------------------------------------------------- |
| `agent.message_start`       | `message_id`、`message`               | 开始一条 assistant message。                                  |
| `agent.content_block_start` | `message_id`、`index`、`content_block` | 开始一个 content block，例如 text、thinking 或 tool use。          |
| `agent.content_block_delta` | `message_id`、`index`、`delta`         | 承载\ `index`\ 对应 content block 的增量片段。                     |
| `agent.content_block_stop`  | `message_id`、`index`                 | 结束\ `index`\ 对应 content block。                           |
| `agent.message_delta`       | `message_id`、`delta`、`usage`         | 承载 message 级增量，例如\ `stop_reason`、`stop_sequence`\ 或用量信息。 |
| `agent.message_stop`        | `message_id`                         | 结束一条 assistant message。                                  |

`text_delta`、`thinking_delta`、`signature_delta`、`input_json_delta` 和 `tool_output_delta` 不是顶层 Event 类型，只会作为 `agent.content_block_delta.delta.type` 出现。

| `delta.type`        | 字段             | 说明                                            |
| ------------------- | -------------- | --------------------------------------------- |
| `text_delta`        | `text`         | 文本输出片段，客户端可追加\ `delta.text`\ 重建文本。            |
| `thinking_delta`    | `thinking`     | 模型或 provider 输出 thinking 时的思考片段。              |
| `signature_delta`   | `signature`    | thinking block 的签名片段，存在时透出。                   |
| `input_json_delta`  | `partial_json` | 工具入参 JSON 片段。                                 |
| `tool_output_delta` | varies         | 预留给未来的工具输出流式；当前仍以完整\ `agent.tool_result`\ 为准。 |

`agent.content_block_delta` 示例：

```json theme={null}
{
  "id": "evt_delta_xxx",
  "type": "agent.content_block_delta",
  "session_id": "sess_xxx",
  "message_id": "msg_xxx",
  "index": 0,
  "delta": {
    "type": "text_delta",
    "text": "这是"
  },
  "processed_at": "2026-06-22T11:00:01Z"
}
```

旧版增量事件解析约定：

* SSE `event:` 与 JSON `data.type` 都使用公开 Event 类型。
* `agent.content_block_delta.index` 用于区分多个 content block。
* `processed_at` 在增量事件上可能缺失，客户端应按可选字段处理。
* 网络中断后可使用 `Last-Event-ID` 携带最后收到的 Event ID 重连。
* `include_thinking=false` 时，会过滤 `thinking_delta`、`signature_delta` 及可识别的 thinking content block start/stop 事件。
* `include_tool_calls=false` 时，会过滤 `input_json_delta`、`tool_output_delta` 及可识别的 tool content block start/stop 事件。
