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. |
stats | object | No | Session statistics; for the fields, see Session stats. |
usage | object | No | Usage information; may be omitted when the related billing module is not enabled. |
usage.total_credits | number | No | Cumulative Credit consumption and the recommended usage field. Returned only for newly created Sessions; historical Sessions may omit it. |
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. |
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. |
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. |
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 |
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, and span.model_request_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[].
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. |
| 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.