> ## 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 data structures

> Reference for the Session and Event data structures used by the Forward Session API.

## Session object

This object is returned by the endpoints that create, get, list, update, and archive a 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": true,
  "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"
}
```

| Field                           | Type           | Always returned | Description                                                                                                                                            |
| ------------------------------- | -------------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `id`                            | string         | Yes             | Session ID with the `sess_`\ prefix.                                                                                                                   |
| `type`                          | string         | Yes             | Always\ `"session"`.                                                                                                                                   |
| `identity_id`                   | string         | Yes             | Forward Identity ID, representing the end-user identity that owns this Session.                                                                        |
| `template`                      | object         | Yes             | Forward Template summary; for the fields, see [Template summary](#template-summary).                                                                   |
| `source_type`                   | string         | Yes             | Session source: `api`, `im`\ or\ `schedule`.                                                                                                           |
| `status`                        | string         | Yes             | Session runtime status: `idle`, `running`, `rescheduling`, `canceling`\ or\ `terminated`. The archived state is expressed through\ `archived_at`.      |
| `title`                         | string         | Yes             | Session title.                                                                                                                                         |
| `incremental_streaming_enabled` | boolean        | Yes             | Whether incremental streaming events are enabled for this Session. Defaults to\ `false`\ if omitted at creation, and cannot be changed after creation. |
| `metadata`                      | object         | No              | Caller-defined business metadata.                                                                                                                      |
| `config`                        | object         | No              | Session configuration; may be omitted when not provided.                                                                                               |
| `config.environment_variables`  | object         | No              | Session-level environment variables, as key-value pairs.                                                                                               |
| `stats`                         | object         | No              | Session statistics; for the fields, see [Session stats](#session-stats).                                                                               |
| `usage`                         | object         | No              | Usage information; may be omitted when the related billing module is not enabled.                                                                      |
| `usage.credits`                 | number         | No              | Credit consumption.                                                                                                                                    |
| `archived_at`                   | string \| null | Yes             | Archive time; `null`\ when not archived.                                                                                                               |
| `created_at`                    | string         | Yes             | Creation time, in RFC 3339 format.                                                                                                                     |
| `updated_at`                    | string         | Yes             | Last update time, in RFC 3339 format.                                                                                                                  |

## Template summary

| Field     | Type    | Always returned | Description                                              |
| --------- | ------- | --------------- | -------------------------------------------------------- |
| `id`      | string  | Yes             | Forward Template ID.                                     |
| `type`    | string  | Yes             | Always\ `"template"`.                                    |
| `name`    | string  | Yes             | Template name.                                           |
| `model`   | string  | Yes             | The model tier or model identifier used by the Template. |
| `version` | integer | Yes             | Template version number.                                 |

## Session stats

| Field              | Type    | Always returned | Description                                                          |
| ------------------ | ------- | --------------- | -------------------------------------------------------------------- |
| `active_seconds`   | integer | No              | Active processing time, in seconds; usually\ `0`\ for a new Session. |
| `duration_seconds` | integer | No              | Session duration, in seconds; usually\ `0`\ for a new Session.       |

## Event object

The Events returned by the endpoints are JSON objects that vary by `type`. Every returned Event includes the common fields, while different event types carry different payload fields.

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

| Field          | Type   | Always returned | Description                                                                                                                         |
| -------------- | ------ | --------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `id`           | string | Yes             | Event ID with the `evt_`\ prefix.                                                                                                   |
| `type`         | string | Yes             | Event type.                                                                                                                         |
| `session_id`   | string | Yes             | The ID of the Session this Event belongs to.                                                                                        |
| `processed_at` | string | No              | The time the event was processed, in RFC 3339 format. Some agent-generated events or incremental events may not include this field. |

The payload fields allowed for each event type are listed below. The table does not repeat the common fields `id`, `type`, `session_id`, and `processed_at`.

| Event type                  | Allowed fields                                             |
| --------------------------- | ---------------------------------------------------------- |
| `user.message`              | `content`                                                  |
| `user.interrupt`            | None                                                       |
| `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`            | None                                                       |
| `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`                                               |
| `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`    | None                                                       |
| `session.status_idle`       | `stop_reason`                                              |
| `session.status_terminated` | None                                                       |
| `session.error`             | `error`                                                    |
| `session.updated`           | `agent`, `metadata`, `title`                               |

## Event types the client can send

`POST /api/v1/forward/sessions/{session_id}/events` accepts only the following event types.

| Type                      | Required fields         | Description                                                                                                                              |
| ------------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| `user.message`            | `content`               | User message. `content`\ must be a non-empty array of content blocks and supports block types such as\ `text`, `image`, and\ `document`. |
| `user.interrupt`          | None                    | Request to interrupt the current processing.                                                                                             |
| `user.tool_confirmation`  | `tool_use_id`, `result` | Tool-call confirmation. `result`\ is\ `allow`\ or\ `deny`; when denying, you may pass\ `deny_message`.                                   |
| `user.tool_result`        | `tool_use_id`           | Returns a built-in tool result; `content`\ and\ `is_error`\ are optional.                                                                |
| `user.custom_tool_result` | `custom_tool_use_id`    | Returns a client-defined custom tool result; `content`\ and\ `is_error`\ are optional.                                                   |
| `user.define_outcome`     | `description`, `rubric` | Defines the expected outcome and grading criteria; `max_iterations`\ is optional.                                                        |

`system.message` is a public Event type, but it is not open as a Forward client write event.

## Public event types

When querying history and subscribing to the SSE event stream, you may receive the following public event types:

`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`, `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`, and `session.updated`.

## Incremental streaming events

Whether incremental streaming events are exposed is controlled by the `incremental_streaming_enabled` field set when creating the Session, not by the request parameters of history queries or SSE subscriptions:

* `true`: The event stream returns assistant output fragments before the final complete `agent.message`; history queries also return the same batch of incremental events.

* `false` or omitted: Normal mode is kept, returning only complete public events and no incremental events.

When incremental streaming is enabled, the final complete `agent.message` is still returned. The client can use incremental events for instant display, then use the final `agent.message` as the persisted or display-calibrated result.

There are only the following 6 top-level incremental event types:

| Event type                  | Key fields                             | Description                                                                                       |
| --------------------------- | -------------------------------------- | ------------------------------------------------------------------------------------------------- |
| `agent.message_start`       | `message_id`, `message`                | Starts an assistant message.                                                                      |
| `agent.content_block_start` | `message_id`, `index`, `content_block` | Starts a content block, such as text, thinking, or tool use.                                      |
| `agent.content_block_delta` | `message_id`, `index`, `delta`         | Carries an incremental fragment for the content block at\ `index`.                                |
| `agent.content_block_stop`  | `message_id`, `index`                  | Ends the content block at\ `index`.                                                               |
| `agent.message_delta`       | `message_id`, `delta`, `usage`         | Carries a message-level increment, such as\ `stop_reason`, `stop_sequence`, or usage information. |
| `agent.message_stop`        | `message_id`                           | Ends an assistant message.                                                                        |

`text_delta`, `thinking_delta`, `signature_delta`, `input_json_delta`, and `tool_output_delta` are not top-level Event types; they only appear as `agent.content_block_delta.delta.type`.

| `delta.type`        | Field          | Description                                                                                                        |
| ------------------- | -------------- | ------------------------------------------------------------------------------------------------------------------ |
| `text_delta`        | `text`         | A text output fragment; the client can append\ `delta.text`\ to reconstruct the text.                              |
| `thinking_delta`    | `thinking`     | A thinking fragment when the model or provider outputs thinking.                                                   |
| `signature_delta`   | `signature`    | A signature fragment of the thinking block, surfaced when present.                                                 |
| `input_json_delta`  | `partial_json` | A JSON fragment of the tool input parameters.                                                                      |
| `tool_output_delta` | varies         | Reserved for future streaming of tool output; currently the complete\ `agent.tool_result`\ still takes precedence. |

`agent.content_block_delta` example:

```
1{2  "id": "evt_delta_xxx",3  "type": "agent.content_block_delta",4  "session_id": "sess_xxx",5  "message_id": "msg_xxx",6  "index": 0,7  "delta": {8    "type": "text_delta",9    "text": "这是"10  },11  "processed_at": "2026-06-22T11:00:01Z"12}
```

Incremental event parsing conventions:

* Both the SSE `event:` and the JSON `data.type` use public Event types.

* `agent.content_block_delta.index` is used to distinguish between multiple content blocks.

* `processed_at` may be missing on incremental events; the client should treat it as an optional field.

* After a network interruption, you can use `Last-Event-ID` to carry the last received Event ID when reconnecting.

* When `include_thinking=false`, `thinking_delta`, `signature_delta`, and recognizable thinking content block start/stop events are filtered out.

* When `include_tool_calls=false`, `input_json_delta`, `tool_output_delta`, and recognizable tool content block start/stop events are filtered out.
