Skip to main content
Sessions

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": "客户支持会话",
  "metadata": {
    "source": "web",
    "biz_id": "ticket_123"
  },
  "config": {
    "environment_variables": {
      "API_KEY": "sk-xxx"
    }
  },
  "stats": {
    "active_seconds": 30,
    "duration_seconds": 3600
  },
  "usage": {
    "total_credits": 12.5
  },
  "archived_at": null,
  "created_at": "2026-06-22T10:00:00Z",
  "updated_at": "2026-06-22T11:00:00Z"
}
FieldTypeAlways returnedDescription
idstringYesSession ID with the sess_\ prefix.
typestringYesAlways\ "session".
identity_idstringYesForward Identity ID, representing the end-user identity that owns this Session.
templateobjectYesForward Template summary; for the fields, see Template summary.
source_typestringYesSession source: api, im, schedule, or batch.
statusstringYesSession runtime status: idle, running, rescheduling, canceling\ or\ terminated. The archived state is expressed through\ archived_at.
titlestringYesSession title.
metadataobjectNoCaller-defined business metadata.
configobjectNoSession configuration; may be omitted when not provided.
config.environment_variablesobjectNoSession-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.
statsobjectNoSession statistics; for the fields, see Session stats.
usageobjectNoUsage information; may be omitted when the related billing module is not enabled.
usage.total_creditsnumberNoCumulative Credit consumption and the recommended usage field. Returned only for newly created Sessions; historical Sessions may omit it.
archived_atstring | nullYesArchive time; null\ when not archived.
created_atstringYesCreation time, in RFC 3339 format.
updated_atstringYesLast update time, in RFC 3339 format.

Template summary

FieldTypeAlways returnedDescription
idstringYesForward Template ID.
typestringYesAlways\ "template".
namestringYesTemplate name.
modelstringYesThe model tier or model identifier used by the Template.
versionintegerYesTemplate version number.

Session stats

FieldTypeAlways returnedDescription
active_secondsintegerNoActive processing time, in seconds; usually\ 0\ for a new Session.
duration_secondsintegerNoSession 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.
{
  "id": "sthr_child_xxx",
  "type": "session_thread",
  "session_id": "sess_xxx",
  "parent_thread_id": "sthr_coordinator_xxx",
  "template_id": "tmpl_worker",
  "name": "research",
  "role": "child",
  "status": "idle",
  "stop_reason": { "type": "end_turn" },
  "created_by_tool_use_id": "toolu_xxx",
  "created_at": "2026-06-22T11:00:00Z",
  "updated_at": "2026-06-22T11:05:00Z"
}
FieldTypeAlways returnedDescription
idstringYesThread ID with the sthr_ prefix.
typestringYesAlways "session_thread".
session_idstringYesID of the Session that owns the Thread.
parent_thread_idstringNoParent Thread ID. Not returned for the coordinator Thread.
template_idstringNoReturned when the runtime Agent can be reliably mapped to a Forward Template in the parent Session.
namestringNoPublic Thread name.
rolestringYesThread role: coordinator or child.
statusstringYesRuntime status such as idle, running, rescheduling, or terminated. Normalized to archived when archived_at is set.
stop_reasonobjectNoReason the Thread stopped.
created_by_tool_use_idstringNoTool use ID that created a child Thread.
archived_atstringNoArchive time in RFC 3339 format. Omitted when not archived.
created_atstringNoCreation time in RFC 3339 format.
updated_atstringNoLast update time in RFC 3339 format.
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.
{
  "id": "evt_xxx",
  "type": "agent.message",
  "session_id": "sess_xxx",
  "content": [
    {
      "type": "text",
      "text": "这是分析结果。"
    }
  ],
  "processed_at": "2026-06-22T11:00:03Z"
}
FieldTypeAlways returnedDescription
idstringYesEvent ID with the evt_\ prefix.
typestringYesEvent type.
session_idstringYesThe ID of the Session this Event belongs to.
session_thread_idstringNoThread ID described by a Thread lifecycle Event.
processed_atstringNoThe 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, session_thread_id, and processed_at.
Event typeAllowed fields
user.messagecontent
user.interruptNone
user.tool_confirmationtool_use_id, result, deny_message
user.tool_resulttool_use_id, content, is_error
user.custom_tool_resultcustom_tool_use_id, content, is_error
user.define_outcomedescription, rubric, outcome_id, max_iterations
agent.messagecontent
agent.thinkingthinking, text
agent.message_startmessage_id, message
agent.content_block_startmessage_id, index, content_block
agent.content_block_deltamessage_id, index, delta
agent.content_block_stopmessage_id, index
agent.message_deltamessage_id, delta, usage
agent.message_stopmessage_id
event_startevent
event_deltaevent_id, delta
agent.tool_usename, input, evaluated_permission
agent.tool_resulttool_use_id, content, is_error
agent.custom_tool_usename, input
agent.mcp_tool_usemcp_server_name, name, input, evaluated_permission
agent.mcp_tool_resultmcp_tool_use_id, content, is_error
agent.artifact_deliveredfile_id, original_filename, size, content_type
session.status_runningNone
session.status_idlestop_reason
session.status_terminatedNone
session.thread_createdsession_thread_id
session.thread_status_runningsession_thread_id
session.thread_status_idlesession_thread_id
session.thread_status_rescheduledsession_thread_id
session.thread_status_terminatedsession_thread_id
session.errorerror
session.updatedagent, metadata, title
span.model_request_endis_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.
TypeRequired fieldsDescription
user.messagecontentUser message. content must be a non-empty content block array. Only text and image types are supported.
user.interruptNoneRequest to interrupt the current processing.
user.tool_confirmationtool_use_id, resultTool-call confirmation. result\ is\ allow\ or\ deny; when denying, you may pass\ deny_message.
user.tool_resulttool_use_idReturns a built-in tool result; content\ and\ is_error\ are optional.
user.custom_tool_resultcustom_tool_use_idReturns a client-defined custom tool result; content\ and\ is_error\ are optional.
user.define_outcomedescription, rubricDefines 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:
{
  "id": "evt_xxx",
  "type": "span.model_request_end",
  "is_error": false,
  "model_request_start_id": "evt_yyy",
  "model_usage": {
    "credits": 0.42
  },
  "processed_at": "2026-06-22T11:00:01Z"
}
FieldTypeDescription
is_errorbooleanWhether the model request ended with an error or cancellation.
model_request_start_idstringEvent ID of the corresponding model request start event.
model_usageobjectUsage object for this model call.
model_usage.creditsnumberCredits 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[] valueDescription
agent.messageSubscribe to incremental content of assistant text messages.
agent.thinkingSubscribe to incremental content of thinking.
When enabled, the SSE stream may additionally return two top-level Event types:
Event typeKey fieldsDescription
event_starteventIndicates a public event has started generating. event only retains id, type, name, mcp_server_name.
event_deltaevent_id, deltaAn incremental fragment of a public event. event_id references the corresponding event.
event_start.event fields:
FieldTypeDescription
idstringThe Event ID of the corresponding event.
typestringThe public Event type, currently agent.message or agent.thinking.
namestringReserved field; not typically returned for current event_deltas[] selectors.
mcp_server_namestringReserved field; not typically returned for current event_deltas[] selectors.
event_delta.delta fields:
FieldTypeDescription
typestringDelta type, e.g. content_delta.
indexintegerContent block index.
contentobjectIncremental content. Currently only exposes type and text.
content.typestringContent type, e.g. text or thinking.
content.textstringIncremental text fragment.
event_start example:
{
  "id": "evt_xxx",
  "type": "event_start",
  "session_id": "sess_xxx",
  "event": {
    "id": "evt_xxx",
    "type": "agent.message"
  }
}
event_delta example:
{
  "id": "evt_xxx",
  "type": "event_delta",
  "session_id": "sess_xxx",
  "event_id": "evt_xxx",
  "delta": {
    "type": "content_delta",
    "index": 0,
    "content": {
      "type": "text",
      "text": "这是"
    }
  }
}
Event delta streaming conventions:
  • event_start / event_delta are only returned when subscribing to SSE with event_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=false filters agent.thinking event start signals and delta.content.type=thinking fragments.
  • include_tool_calls=false does not affect event_deltas[] currently supported types (agent.message and agent.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 typeKey fieldsDescription
agent.message_startmessage_id, messageStarts an assistant message.
agent.content_block_startmessage_id, index, content_blockStarts a content block, such as text, thinking, or tool use.
agent.content_block_deltamessage_id, index, deltaCarries an incremental fragment for the content block at\ index.
agent.content_block_stopmessage_id, indexEnds the content block at\ index.
agent.message_deltamessage_id, delta, usageCarries a message-level increment, such as\ stop_reason, stop_sequence, or usage information.
agent.message_stopmessage_idEnds 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.typeFieldDescription
text_deltatextA text output fragment; the client can append\ delta.text\ to reconstruct the text.
thinking_deltathinkingA thinking fragment when the model or provider outputs thinking.
signature_deltasignatureA signature fragment of the thinking block, surfaced when present.
input_json_deltapartial_jsonA JSON fragment of the tool input parameters.
tool_output_deltavariesReserved for future streaming of tool output; currently the complete\ agent.tool_result\ still takes precedence.
agent.content_block_delta example:
{
  "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"
}
Legacy 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.