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.
| 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. |
source_type | string | Yes | Session source: api, im, schedule, or batch. |
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. |
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. They are merged on top of the compiled Template + Identity Config result; Session-level values override base-layer values with the same key. |
resources | array | No | Mounted session resources. Currently contains only file resources added through Add a session resource; empty when none are mounted. |
stats | object | No | Session statistics; for the fields, see Session stats. |
usage | object | No | Usage information; omitted when no data is available. |
usage.model_credits | number | No | Credits consumed by the model. |
usage.sandbox_runtime_credits | number | No | Credits consumed by the Sandbox runtime. |
usage.total_credits | number | No | Cumulative Credit consumption returned by CAS. |
outcome_evaluations | array | Yes | Current evaluation state of the Outcome; an empty array when there is no Outcome. |
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 resource
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Session resource ID prefixed with sesr_. |
type | string | Yes | Resource type; currently always file. |
file_id | string | Yes | Mounted File ID. |
mount_path | string | Yes | Actual mount path in the Agent container. |
created_at | string | Yes | Creation time in RFC 3339 format. |
updated_at | string | Yes | Update time in RFC 3339 format. |
Session stats
When stats is returned, it includes the following fields. Durations are integer seconds; fractional values returned by CAS are truncated.
| Field | Type | Always returned | Description |
|---|---|---|---|
active_seconds | integer | Yes, when stats is returned | Active processing time, in seconds; usually 0 for a new Session. |
duration_seconds | integer | Yes, when stats is returned | Session duration, in seconds; usually 0 for a new Session. |
usage is independently optional. Fields are omitted when the data source does not return them, and explicit zero values are returned as 0.
Outcome evaluation
Each item in outcome_evaluations contains the following fields:
| Field | Type | Nullable | Description |
|---|---|---|---|
type | string | No | Evaluation type. |
outcome_id | string | No | Outcome ID. |
description | string | No | Outcome description. |
iteration | number | No | Current evaluation iteration. |
result | string | No | Evaluation result. |
explanation | string | Yes | Explanation of the result. |
completed_at | string | Yes | Completion time. |
Thread object
A Thread is an execution branch in the Session runtime. The list, get, and archive Thread endpoints return this object.
| Field | Type | Always returned | Description |
|---|---|---|---|
id | string | Yes | Thread ID with the sthr_ prefix. |
type | string | Yes | Always "session_thread". |
session_id | string | Yes | ID of the Session that owns the Thread. |
parent_thread_id | string | No | Parent Thread ID. Not returned for the coordinator Thread. |
template_id | string | No | Returned when the runtime Agent can be reliably mapped to a Forward Template in the parent Session. |
name | string | No | Public Thread name. |
role | string | Yes | Thread role: coordinator or child. |
status | string | Yes | Runtime status such as idle, running, rescheduling, or terminated. Normalized to archived when archived_at is set. |
stop_reason | object | No | Reason the Thread stopped. |
created_by_tool_use_id | string | No | Tool use ID that created a child Thread. |
stats | object | No | Thread runtime statistics. |
stats.active_seconds | integer | Yes, when stats is returned | Active processing time, in seconds. |
stats.duration_seconds | integer | Yes, when stats is returned | Thread duration, in seconds. |
stats.startup_seconds | integer | No | Thread startup time, in seconds. |
usage | object | No | Thread usage information. |
usage.total_credits | number | No | Cumulative Credit consumption of the Thread. |
archived_at | string | No | Archive time in RFC 3339 format. Omitted when not archived. |
created_at | string | No | Creation time in RFC 3339 format. |
updated_at | string | No | Last update time in RFC 3339 format. |
startup_seconds and total_credits are omitted, while explicit zero values are preserved. Threads do not return credits, model_credits, or sandbox_runtime_credits.
Thread responses do not expose the CAS Agent ID, Agent object, Agent Version, or Template Version.
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.
| 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. |
session_thread_id | string | No | Thread ID described by a Thread lifecycle Event. |
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. |
id, type, session_id, session_thread_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 |
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 | None |
session.status_idle | stop_reason |
session.status_terminated | None |
session.thread_created | session_thread_id |
session.thread_status_running | session_thread_id |
session.thread_status_idle | session_thread_id |
session.thread_status_rescheduled | session_thread_id |
session.thread_status_terminated | session_thread_id |
session.error | error |
session.updated | agent, metadata, title |
span.model_request_end | is_error, model_request_start_id, model_usage |
span.outcome_evaluation_start | iteration, outcome_id |
span.outcome_evaluation_ongoing | iteration, outcome_id |
span.outcome_evaluation_end | explanation, iteration, outcome_evaluation_start_id, outcome_id, result, usage |
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 content block array. Only text and image types are supported. |
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. |
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, 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.thread_created, session.thread_status_running, session.thread_status_idle, session.thread_status_rescheduled, session.thread_status_terminated, session.error, session.updated, span.model_request_end, span.outcome_evaluation_start, span.outcome_evaluation_ongoing, and span.outcome_evaluation_end.
Model usage events
After a model call completes, the event stream emits a span.model_request_end event with the usage for that call:
| Field | Type | Description |
|---|---|---|
is_error | boolean | Whether the model request ended with an error or cancellation. |
model_request_start_id | string | Event ID of the corresponding model request start event. |
model_usage | object | Usage object for this model call. |
model_usage.credits | number | Credits consumed by this model call. |
model_usage.credits is the incremental usage for one call, not the cumulative Session value. Consumers can deduplicate events by Event ID and add the value to their Session model usage record. The event stream does not provide cumulative Session usage. Read usage.total_credits from Get Session and use it to reconcile the accumulated event values.
event_start and event_delta are only returned when subscribing to SSE with event_deltas[].
Outcome evaluation events
The outcome evaluation process returns the following public events:
| Event type | Payload fields |
|---|---|
span.outcome_evaluation_start | iteration, outcome_id |
span.outcome_evaluation_ongoing | iteration, outcome_id |
span.outcome_evaluation_end | explanation, iteration, outcome_evaluation_start_id, outcome_id, result, usage |
Incremental streaming events
Event delta streaming
Event delta streaming is enabled by passing the event_deltas[] query parameter when subscribing to the Session Event Stream. It supports repeated parameters with the following allowed values:
event_deltas[] value | Description |
|---|---|
agent.message | Subscribe to incremental content of assistant text messages. |
agent.thinking | Subscribe to incremental content of thinking. This is a Beta feature and requires the X-Qoder-Beta: thinking-event-stream-delta-2026-07-20 request header. See Stream session events. |
| Event type | Key fields | Description |
|---|---|---|
event_start | event | Indicates a public event has started generating. event only retains id, type, name, mcp_server_name. |
event_delta | event_id, delta | An incremental fragment of a public event. event_id references the corresponding event. |
event_start.event fields:
| Field | Type | Description |
|---|---|---|
id | string | The Event ID of the corresponding event. |
type | string | The public Event type, currently agent.message or agent.thinking. |
name | string | Reserved field; not typically returned for current event_deltas[] selectors. |
mcp_server_name | string | Reserved field; not typically returned for current event_deltas[] selectors. |
event_delta.delta fields:
| Field | Type | Description |
|---|---|---|
type | string | Delta type, e.g. content_delta. |
index | integer | Content block index. |
content | object | Incremental content. Currently only exposes type and text. |
content.type | string | Content type, e.g. text or thinking. |
content.text | string | Incremental text fragment. |
event_start example:
event_delta example:
event_start/event_deltaare only returned when subscribing to SSE withevent_deltas[]; history queries do not return these events.- The final complete public event is still returned. Clients can use event delta frames for instant display, then use the final complete event as the persisted or display-calibrated result.
include_thinking=falsefiltersagent.thinkingevent start signals anddelta.content.type=thinkingfragments.include_tool_calls=falsedoes not affectevent_deltas[]currently supported types (agent.messageandagent.thinking), but still filters standard tool-use events and legacy tool input/output deltas.
Legacy incremental streaming data structures
For backward compatibility, the event stream and history queries may still return legacy incremental events. These events are controlled by the incremental_streaming_enabled field set when creating the Session. New integrations should not depend on them. The final complete agent.message is still returned.
The legacy top-level incremental event types are as follows:
| 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:
- Both the SSE
event:and the JSONdata.typeuse public Event types. agent.content_block_delta.indexis used to distinguish between multiple content blocks.processed_atmay be missing on incremental events; the client should treat it as an optional field.- After a network interruption, you can use
Last-Event-IDto 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.

