Shared Session, resource, event, and thread structures.
Session object
Returned by create, get, list, update, and archive endpoints.
| Field | Type | Description |
|---|---|---|
id | string | Session ID with the sess_ prefix |
type | string | Always "session" |
agent | object | Agent snapshot used by this Session. See Session embedded agent for the field shape |
environment_id | string | Environment ID used by this Session |
status | string | Session lifecycle status: rescheduling, running, idle, or terminated. The canceling value in a Cancel endpoint response is a fixed acknowledgement value, not a persisted Session object status |
title | string | null | Session title |
metadata | object | Session metadata |
environment_variables | object | Session-level environment variables exported into the agent runtime as a map of string keys to string values ({"NAME":"value"}). Empty Sessions return {}. See Create a Session |
resources | array of Session resource | File, GitHub, generic Git, or Memory Store resources attached to the Session |
vault_ids | array of string | Vault IDs attached to the Session |
deployment_id | string | null | Deployment ID when the Session was created by a Deployment, otherwise null |
outcome_evaluations | array | Outcome evaluation results. New Sessions return [] |
stats | Session stats | Session statistics |
usage | Session usage | Cumulative model, sandbox runtime, and total credits snapshot. Omitted when usage data is unavailable |
archived_at | string | null | Archive time, or null when not archived |
created_at | string | Creation time |
updated_at | string | Last update time |
agent_id, turn_status, or memory_store_ids.
Agent reference
agent in create requests can be either a string Agent ID or this object:
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Agent ID with the agent_ prefix |
type | string | Yes (object form only) | Must be the literal "agent". Missing or other values return 400 when the object form is used. The bare-string form (passing the Agent ID directly) skips this check |
version | integer | No | Agent version to snapshot. Omit or pass 0 to use the latest active version |
Session embedded agent
The agent returned inside a Session object is the Agent snapshot pinned to the Session, but several Agent fields are stripped before they are exposed:
Publishing newer source Agent configuration does not replace this snapshot. Submitting agent fields through Update a session can change supported runtime fields locally for the Session without advancing its embedded agent.version; the linked guide also explains Skill version behavior.
created_at,updated_at— never included on the embedded Agent.archived,archived_at— never included; the Session preserves access to the snapshot regardless of the source Agent's archive state.metadata— Agent-level metadata is stripped; only Session-levelmetadatais exposed.instructions— replaced bysystem.
agent.multiagent.agents[] response structure and Session Thread object for the Agent structure returned in each thread.
agent.model.effective_context_window
Sessions return an additional response-only effective_context_window (int64, in tokens) inside agent.model. It is the runtime-resolved context window the Session will use for this Agent (after applying environment-level overrides). Absent or non-positive values are omitted; clients should treat the field as informational.
Session resource
resources[] is a union distinguished by type.
File resource
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Response only | Resource ID |
type | string | Yes | "file" |
file_id | string | Yes | File ID with the file_ prefix. The file must be ready |
mount_path | string | No | Mount path in the container. Defaults to /mnt/session/uploads/<file_id> when omitted |
created_at | string | Response only | Resource creation time |
updated_at | string | Response only | Resource update time |
GitHub repository resource
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Response only | Resource ID |
type | string | Yes | "github_repository" |
url | string | Yes | Repository URL |
authorization_token | string | No (write only) | GitHub token used to access a private repository or push. It is not returned in responses |
mount_path | string | No | Clone target path in the container. Defaults from the repository name when omitted |
checkout | object | No | Git checkout target, for example {"type":"branch","name":"main"} |
created_at | string | Response only | Resource creation time |
updated_at | string | Response only | Resource update time |
Generic Git repository resource
Use this resource for GitLab, Gitee, Bitbucket, and other HTTP(S) Git providers.
| Field | Type | Required | Description |
|---|---|---|---|
id | string | Response only | Resource ID |
type | string | Yes | "git_repository" |
url | string | Yes | HTTP(S) clone URL. Public repositories need no username; authenticated repositories include it, e.g. https://username@gitlab.com/group/repo.git |
password | string | No (write only) | Required together with a username for private repositories or push. Use the account password or the Access Token/PAT required by the provider. It is not returned in responses |
mount_path | string | No | Clone target inside the container; derived from repository name when omitted |
checkout | object | No | Git checkout target, e.g. {"type":"branch","name":"main"} |
created_at | string | Response only | Resource creation time |
updated_at | string | Response only | Resource update time |
Memory Store resource
| Field | Type | Required | Description |
|---|---|---|---|
type | string | Yes | "memory_store" |
memory_store_id | string | Yes | Memory Store ID with the memstore_ prefix |
access | string | null | No | Optional access mode. Allowed values: "read_write", "read_only". Empty string or omitted means default (no override) |
instructions | string | null | No | Optional instructions stored on the Session resource. Maximum 4096 characters |
name | string | null | Response only | Current Memory Store name when available |
description | string | Response only | Current Memory Store description when available |
mount_path | string | null | Response only | Current implementation returns null unless an existing resource snapshot contains a value |
id, created_at, or updated_at fields.
Session stats
| Field | Type | Description |
|---|---|---|
active_seconds | number | Active processing time in seconds. New Sessions start at 0 |
duration_seconds | number | Session duration in seconds. New Sessions start at 0 |
Session usage
usage is the cumulative snapshot for a Session:
| Field | Type | Description |
|---|---|---|
model_credits | number | Credits accumulated from recorded model calls in the Session |
sandbox_runtime_credits | number | Credits accumulated from billable cloud sandbox runtime used by the Session |
total_credits | number | Total credits accumulated across all usage components |
usage field. Each credits value is floored rather than rounded to at most 2 decimal places; for example, 7.6681 is returned as 7.66. JSON numbers do not preserve trailing zeroes, so 1.20 may be serialized as 1.2. Treat all three fields as one snapshot: overwrite local values by Session ID instead of adding them again on every query.
Multiagent roster element
In a Session response, ordinary Agent and self entries in agent.multiagent.agents[] return the corresponding Agent definitions with the fields below, excluding their own multiagent field.
Advisor entries return only type and model, for example {"type":"advisor","model":"ultimate"}. See Advisor object.
| Field | Type | Description |
|---|---|---|
type | string | "agent" for a sibling Agent reference, or "self" for the coordinator itself |
id | string | Agent ID. Present for type = "agent"; mirrors the coordinator's own ID when type = "self" |
version | integer | The child Agent version used by this Session. Present for type = "agent". For example, if the child is configured as "latest" and v3 is the latest version when the Session is created, this field returns 3; the Session keeps using v3 |
name | string | Hydrated Agent name |
description | string | null | Hydrated Agent description |
system | string | Hydrated Agent system prompt (replaces instructions) |
model | string | object | Same shape as on the embedded Agent, including effective_context_window when set |
| Other Agent fields | varies | Tools, MCP servers, skills, and other Agent fields, with the same field stripping rules as the embedded Agent |
Event object
Events returned by send, list, and stream endpoints are event-specific JSON objects. Public event responses expose only the documented public fields for each event type.
| Field | Type | Description |
|---|---|---|
id | string | Event ID with the evt_ prefix |
type | string | Event type |
processed_at | string | Present when the event has been processed. Many agent-generated events omit this field. |
type, an event may also include fields such as content, input, name, tool_use_id, mcp_tool_use_id, custom_tool_use_id, result, deny_message, rubric, outcome_id, session_thread_id, stop_reason, error, usage, or model_usage.
Client event request types
POST /api/v1/cloud/sessions/{session_id}/events accepts exactly these client-sent event types:
| Type | Required fields | Notes |
|---|---|---|
user.message | content | content must be a non-empty array of content blocks |
user.interrupt | none | session_thread_id is optional and is echoed as null when omitted |
user.tool_confirmation | tool_use_id, result | result must be allow or deny; deny_message is optional |
user.tool_result | tool_use_id | Use this to return a built-in tool result from a self-hosted worker. content is optional; when present, it must be an array of content blocks. is_error is optional |
user.custom_tool_result | custom_tool_use_id | content is optional; when present, it must be an array of content blocks. is_error is optional |
user.define_outcome | description, rubric | rubric is an object such as {"type":"text","content":"..."} or {"type":"file","file_id":"file_..."}; max_iterations is optional |
system.message | content | content must be a non-empty array of text content blocks; the event must follow a user/tool result event |
Message content blocks
events[].type identifies the event, content[].type identifies the content block, and an image's source.type identifies its source.
| Event | Accepted content[].type | content requirements |
|---|---|---|
user.message | text, image | Required, non-empty array; text and images may be mixed |
system.message | text | Required, non-empty array |
user.tool_result, user.custom_tool_result | text, image, document, search_result | Optional; when supplied, must be an array, which may be empty |
User messages
All fields below are required. Use only the fields for the selected block type.
content[].type | Fields | Description |
|---|---|---|
text | type, text | text must be a non-empty, non-whitespace string |
image | type, source | source is one of the three formats below |
source fields are strings:
source.type | Required fields | Description |
|---|---|---|
base64 | type, media_type, data | media_type is image/png, image/jpeg, image/webp, or image/gif; data is raw Base64, with optional trailing = padding and no Data URL prefix |
url | type, url | External HTTPS image URL readable by the model service; private, loopback, and other restricted destinations are rejected |
file | type, file_id | Image File ID from Upload file, readable by the current identity with status ready; supports PNG, JPEG, WebP, and GIF |
- Each
user.messageaccepts at most 100 image blocks. Use a Session model that supports image input. - Each Base64 value is limited to 10 MiB (10,485,760 bytes) of encoded text, with width and height each at most 8000 pixels. Use a File source when the encoded length exceeds the limit.
- Base64 and File images may be resized or compressed; URL images are fetched by the downstream model service.
User message examples
Each example is a single event object to place in the events array.
Text:
Public event types
List and stream endpoints can expose these event types:
user.message, user.interrupt, user.tool_confirmation, user.custom_tool_result, user.define_outcome, user.tool_result, system.message, agent.artifact_delivered, agent.custom_tool_use, agent.mcp_tool_result, agent.mcp_tool_use, agent.message, agent.thinking, agent.thread_context_compacted, agent.thread_message_received, agent.thread_message_sent, agent.tool_result, agent.tool_use, session.deleted, session.error, session.status_idle, session.status_rescheduled, session.status_running, session.status_terminated, session.thread_created, session.thread_status_idle, session.thread_status_rescheduled, session.thread_status_running, session.thread_status_terminated, session.updated, session.usage, span.model_request_start, span.model_request_end, span.outcome_evaluation_start, span.outcome_evaluation_ongoing, and span.outcome_evaluation_end.
agent.thread_context_compacted event
Emitted after context compaction. When the upstream provider returns billable credits, usage.credits reports the credits consumed by the compaction call; otherwise, usage is omitted. The same amount is already included in the Session's usage.model_credits, so clients must not add it again. Token counts are not exposed.
agent.artifact_delivered event
agent.artifact_delivered indicates that the Agent has successfully delivered an artifact file. Each successfully delivered file produces one event; delivering multiple files produces multiple events. This server-generated event is available through event list and stream endpoints and cannot be submitted through the send events endpoint.
| Field | Type | Description |
|---|---|---|
id | string | Event ID with the evt_ prefix |
type | string | Always agent.artifact_delivered |
file_id | string | File ID of the delivered file, with the file_ prefix |
original_filename | string | Original filename of the delivered file |
size | integer (int64) | File size in bytes |
content_type | string | File MIME type, such as application/pdf |
processed_at | string | Optional event processing timestamp in RFC 3339 format |
file_id to get the file details. If the file's downloadable field is true, call Download file content (GET /api/v1/cloud/files/{file_id}/content) to obtain a temporary download URL, then request that URL to download the file. The event itself contains neither file content nor a download URL.
session.updated event
A successful Session update emits session.updated. The event always contains id, type, and processed_at. Depending on the request, it can additionally contain these fields:
| Field | Type | Description |
|---|---|---|
title | string | null | Included when the request supplied title |
metadata | object | Included when the resulting metadata object is non-empty and the request supplied metadata |
agent | object | Updated embedded runtime snapshot, included after runtime configuration is changed through Update a session |
environment_variables emits only the fixed fields. Environment-variable names and values are never included in this event.
session.error event
session.error reports an error during Session execution. The event contains id, type, processed_at, and error.
The error object has these fields:
| Field | Type | Description |
|---|---|---|
type | string | Error category. Clients should handle unknown_error and future types |
message | string | Human-readable error description |
retry_status | object | Retry state. Its type is retrying, exhausted, or terminal |
qoder_error_code | string | Optional diagnostic code. Clients must not use it to decide whether to retry |
retry_status.type has these meanings:
| Value | Description |
|---|---|
retrying | The service is retrying automatically; the client should continue waiting |
exhausted | The retry count or recovery window has been exhausted, or a non-retryable error failed immediately. No further automatic recovery is scheduled for this turn. Wait for subsequent status events before deciding whether to send a new message |
terminal | The error is not recoverable and will not be retried automatically. Use subsequent Session/Thread status events to determine the final state |
Advisor events
Advisor lifecycle events have agent_name: "qoder.advisor". Use session_thread_id to identify each consultation.
| Event | Where to read it | Key fields |
|---|---|---|
agent.thread_message_received | Main thread event stream | from_session_thread_id identifies the consultation thread, from_agent_name is qoder.advisor, and content contains the advice |
agent.thread_message_sent | Advisor Thread event stream | to_session_thread_id and to_agent_name identify the main thread; content contains the advice |
session.error | Advisor Thread event stream | error contains the cause and retry status; see session.error event |
session.thread_status_idle | Session event stream | stop_reason.type is end_turn when the consultation ends (including interruption), or retries_exhausted on failure. See the thread's session.error for the cause |
Event delta stream frames
A buffered event is a complete public Event object emitted after generation finishes and recorded in Session event history. It is the authoritative result.
event_start and event_delta are stream-only SSE payloads used for incremental output. They are not public Event objects and do not appear in event list/history responses. Their JSON payloads have no top-level id or processed_at; the SSE id: field carries the ID of the event being streamed and can be used with Last-Event-ID.
Event start frame
An event_start frame identifies the public event whose incremental output has begun.
| Field | Type | Description |
|---|---|---|
type | string | Always "event_start" |
event | object | Streamed event reference |
event object has these fields:
| Field | Type | Description |
|---|---|---|
id | string | Event ID with the evt_ prefix. The SSE id:, related deltas, and buffered event use this same ID. |
type | string | "agent.message" or "agent.thinking" |
agent.message start is followed by text event_delta frames. An agent.thinking start is start-only: no delta follows, and the buffered agent.thinking event with the same ID marks the end of that thinking phase when one is emitted.
Event delta frame
An event_delta frame appends text to an incrementally streamed agent.message.
| Field | Type | Description |
|---|---|---|
type | string | Always "event_delta" |
event_id | string | ID from the matching event_start.event.id and SSE id: field |
delta | object | Content delta |
delta object has these fields:
| Field | Type | Description |
|---|---|---|
type | string | Always "content_delta" |
index | integer | Zero-based index of the content block being updated |
content | object | Text fragment with type: "text" and a text string |
Model request span events
span.model_request_start marks the beginning of one model request.
| Field | Type | Description |
|---|---|---|
id | string | Event ID with the evt_ prefix |
processed_at | string | RFC 3339 timestamp |
type | string | Always "span.model_request_start" |
span.model_request_end marks completion of that model request and includes model_usage when credits are available for the call. model_usage.credits is floored to at most 2 decimal places.
| Field | Type | Description |
|---|---|---|
id | string | Event ID with the evt_ prefix |
is_error | boolean | Whether the model request ended with an error or cancellation |
model_request_start_id | string | ID of the corresponding span.model_request_start event |
model_usage | object | Optional usage for this model call. Omitted when credits are unavailable |
processed_at | string | RFC 3339 timestamp |
type | string | Always "span.model_request_end" |
model_usage contains only:
| Field | Type | Description |
|---|---|---|
credits | number | Credits consumed by this model call. The value may be 0 and is floored to at most 2 decimal places |
Session Thread object
In managed-agent scenarios, each thread within a Session is represented by this structure.
| Field | Type | Description |
|---|---|---|
id | string | Thread ID with the sthr_ prefix |
type | string | Always "session_thread" |
session_id | string | Owning Session ID |
parent_thread_id | string | null | Parent thread ID. null for the coordinator thread |
agent | object | An ordinary thread uses the Session embedded agent shape with multiagent removed; an Advisor Thread uses {"type":"advisor","model":"..."} |
status | string | Thread lifecycle status: running, idle, rescheduling, or terminated |
stats | object | null | Thread statistics. Current implementation returns null |
archived_at | string | null | Archive time, or null when not archived |
created_at | string | Creation time |
updated_at | string | Last update time |
agent_id, agent_version, name, role, stop_reason, created_by_tool_use_id, or usage.
Session budget
Set a total credit limit with budget: {"type":"limit","max_credit_cost":"100.00"}. The only supported type is currently limit. max_credit_cost is a positive decimal string with up to 12 integer digits and 2 fractional digits. Sessions have no limit by default. When updating a Session, omit budget to keep the current limit or pass null to remove it.
The budget is calculated precisely from the cumulative usage.total_credits. This value includes all threads, Advisors, Graders, context compaction, and sandbox runtime. CAS checks the limit when it receives a new user message. If a running turn crosses the limit, it continues to completion; CAS rejects the next user message.
After the Session rejects a new message because it reached the budget limit, raise the limit above the consumed credits or remove it, then send the user message again. Updating the budget does not resume the Session automatically. A new limit at or below the consumed credits returns 400. Archived or terminated Sessions cannot be updated.
session.usage event
Before each public session.status_idle, the stream emits session.usage when usage data is available. Alongside the standard event fields, it contains top-level model_credits, sandbox_runtime_credits, and total_credits.
These values are cumulative. Replace the previous snapshot instead of adding snapshots together. The stream does not emit usage events while a turn is running. Sandbox charges settled after the current idle event are not included in that session.usage snapshot. After settlement, they are available through GET Session and are included in the snapshot emitted before the next idle event.
