Skip to main content
Manage Sessions

Start a session

A Session combines an Agent (configuration) and an Environment (infrastructure) into a stateful execution context. You send messages to a Session, and it returns a stream of events.

Session lifecycle

  1. Create → idleA new Session enters the idle state, waiting for input.
  2. idle → processingAfter you send a user.message event, the status changes to processing.
  3. processing → idleWhen the current turn completes, the Session returns to the idle state, ready for the next turn.
  4. processing → canceling → idleWhen you cancel a running Session, its status transitions to canceling before returning to idle. The Session remains available for use.
  5. archived (terminal state)The archived status is a terminal state. An archived Session cannot be restored.
A Session is a state machine with the following core statuses:
StatusDescriptionTransitions to
idleIdle, waiting for a user message.processing
processingProcessing; the Agent is running.canceling, idle
cancelingCancellation requested; waiting for the running task to stop.idle
archivedArchived.— (terminal state)

Fields

ParameterTypeDescription
idstringSystem-generated, with a sess_ prefix.
typestringFixed value: "session".
agentstring/objectThe bound Agent. Use a string (Agent ID) for the latest version, or an object {id,version} to lock to a specific version. Only this field is accepted in a creation request. The response always returns a complete snapshot of the Agent object.
agent_idstringThe ID of the bound Agent. This field is returned only in the response and is retained for backward compatibility.
environment_idstringThe ID of the bound Environment.
statusstringThe current status: idle, processing, or canceling.
turn_statusstringThe status of the current turn: idle, running, or canceling.
titlestringThe title of the Session. Defaults to "".
memory_store_idsarrayA list of associated Memory Store IDs. Defaults to [].
vault_idsarrayA list of associated Vault IDs. Defaults to [].
resourcesarrayResources, such as files, attached to the Session. Defaults to [].
created_atstringThe time when the Session was created.
updated_atstringThe time when the Session was last updated.
The REST API response does not include token usage data (usage). It only appears in the session.status_idle Server-Sent Events (SSE) event at the end of each turn.

Create a session

To create a Session, specify an agent and an environment_id.

Use an Agent ID (string)

Binds the Session to the latest version of the Agent.
# Create a Session using an Agent ID
curl -s -X POST https://api.qoder.com.cn/api/v1/cloud/sessions \
  -H "Authorization: Bearer $QODER_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": "agent_019e5ce0bf307a1a8f952eb814aea3d5",
    "environment_id": "env_019e44eb66bb748cabcd1489f6fa4428"
  }' | jq .

Use an Agent object (specify version)

Binds the Session to a specific version of the Agent for consistent behavior.
# Create a Session by specifying an Agent version
curl -s -X POST https://api.qoder.com.cn/api/v1/cloud/sessions \
  -H "Authorization: Bearer $QODER_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "agent": {
      "id": "agent_019e5ce0bf307a1a8f952eb814aea3d5",
      "version": 2
    },
    "environment_id": "env_019e44eb66bb748cabcd1489f6fa4428"
  }' | jq .

A successful request returns a 201 Created response:
{
  "id": "sess_019e5ce0bf9074b69c3481e93771a522",
  "agent": {
    "created_at": "2026-05-18T10:00:00Z",
    "default_environment": "",
    "description": "",
    "id": "agent_019e5ce0bf307a1a8f952eb814aea3d5",
    "instructions": "You are a code review expert.",
    "mcp_servers": [],
    "model": "ultimate",
    "name": "code-reviewer",
    "system": "You are a code review expert.",
    "tools": [
      {
        "type": "agent_toolset_20260401",
        "enabled_tools": ["Bash", "Read", "Write"]
      }
    ],
    "type": "agent",
    "updated_at": "2026-05-18T10:00:00Z",
    "version": 2
  },
  "agent_id": "agent_019e5ce0bf307a1a8f952eb814aea3d5",
  "environment_id": "env_019e44eb66bb748cabcd1489f6fa4428",
  "status": "idle",
  "title": "",
  "turn_status": "idle",
  "memory_store_ids": [],
  "resources": [],
  "vault_ids": [],
  "type": "session",
  "created_at": "2026-05-18T12:00:00Z",
  "updated_at": "2026-05-18T12:00:00Z"
}

In production, specify a version to prevent unexpected behavior changes from Agent updates.

Agent field format

FormatExampleBehavior
string"agent_019e5ce0bf307a1a8f952eb814aea3d5"Uses the latest version of the Agent.
object{"id": "agent_019e5ce0bf307a1a8f952eb814aea3d5", "version": 2}Locks the Session to the specified version.

State transitions

Event request body format

The request body for POST /sessions/{id}/events must be an object containing an events array. Each event in the array includes a content field, which is an array of content blocks.
ParameterTypeRequiredDescription
eventsarrayYesAn array of events. A single request can contain one or more events.
events[].typestringYesThe event type, such as user.message.
events[].contentarrayYesAn array of content blocks.
events[].content[].typestringYesThe content block type, such as text.
events[].content[].textstringYesThe text content.

idle → processing

When you send a user.message event to a Session, its status changes from idle to processing.
# Send a message to trigger processing
curl -s -X POST "https://api.qoder.com.cn/api/v1/cloud/sessions/sess_019e5ce0bf9074b69c3481e93771a522/events" \
  -H "Authorization: Bearer $QODER_PAT" \
  -H "Content-Type: application/json" \
  -d '{
    "events": [{
      "type": "user.message",
      "content": [{"type": "text", "text": "Analyze the code complexity of all Python files in the current directory."}]
    }]
  }' | jq .

processing → idle

When processing completes, the Session automatically returns to idle. You receive a session.status_idle event through the event stream.

Cancel a session

You can interrupt a running Session.
# Cancel a Session
curl -s -X POST "https://api.qoder.com.cn/api/v1/cloud/sessions/sess_019e5ce0bf9074b69c3481e93771a522/cancel" \
  -H "Authorization: Bearer $QODER_PAT"

A cancel request only interrupts execution if the Session is in theprocessingstatus. The status first transitions to canceling and then back to idle once the interruption is complete. The Session can be reused; simply send the next user.message to continue. Attempting to cancel a Session that is already idle has no effect. It returns a 200 OK response without changing the idle status.

Retrieve sessions

# Retrieve a single Session
curl -s "https://api.qoder.com.cn/api/v1/cloud/sessions/sess_019e5ce0bf9074b69c3481e93771a522" \
  -H "Authorization: Bearer $QODER_PAT"

# List all Sessions (with pagination)
curl -s "https://api.qoder.com.cn/api/v1/cloud/sessions?limit=10" \
  -H "Authorization: Bearer $QODER_PAT"

Example paginated response:
{
  "data": [
    {
      "id": "sess_019e5ce0bf9074b69c3481e93771a522",
      "type": "session",
      "agent_id": "agent_019e5ce0bf307a1a8f952eb814aea3d5",
      "environment_id": "env_019e44eb66bb748cabcd1489f6fa4428",
      "status": "idle",
      "turn_status": "idle",
      "title": "",
      "memory_store_ids": [],
      "vault_ids": [],
      "resources": [],
      "created_at": "2026-05-18T12:00:00Z",
      "updated_at": "2026-05-18T12:30:00Z"
    }
  ],
  "first_id": "sess_019e5ce0bf9074b69c3481e93771a522",
  "last_id": "sess_019e5ce0bf9074b69c3481e93771a522",
  "has_more": false
}

Token usage

Per-turn token usage is not returned through the REST API. Instead, listen for the session.status_idle SSE event at the end of each turn. Its usage field contains the token counts for that turn.
ParameterDescription
usage.input_tokensThe number of input tokens consumed in this turn.
usage.output_tokensThe number of output tokens generated in this turn.
usage.cache_read_input_tokensThe number of input tokens served from the cache.
usage.cache_creation_input_tokensThe number of input tokens written to the cache.
Example session.status_idle SSE payload:
{
  "type": "session.status_idle",
  "usage": {
    "input_tokens": 3840,
    "output_tokens": 2156,
    "cache_read_input_tokens": 0,
    "cache_creation_input_tokens": 0
  }
}

Session and Agent version binding

A Session snapshots the Agent configuration at creation time.
  • Use the string format "agent": "agent_xxx" to bind to the latest version of the Agent at the time of creation.
  • Use the object format "agent": {"id": "agent_xxx", "version": N} to bind to a specific version.
  • After a Session is created, modifying the Agent does not affect that Session.
  • To use a new version of an Agent, you must create a new Session.

Session A — Bound to Agent v1

Created before the update. Session A continues to use the v1 configuration even after the Agent is updated to v2.

Session B — Bound to Agent v2

Created after the update. It uses the new v2 configuration.

Multi-turn conversation

Sessions support multi-turn conversation. After sending a message, wait for the session.status_idle event before sending the next message.
#!/bin/bash
# Multi-turn conversation example
BASE_URL="https://api.qoder.com.cn/api/v1/cloud"
SESSION_ID="sess_019e5ce0bf9074b69c3481e93771a522"
HEADERS=(
  -H "Authorization: Bearer $QODER_PAT"
)

# Turn 1: Make the initial request
curl -s -X POST "$BASE_URL/sessions/$SESSION_ID/events" \
  "${HEADERS[@]}" \
  -H "Content-Type: application/json" \
  -d '{"events": [{"type": "user.message", "content": [{"type": "text", "text": "Create a Python Flask project scaffold."}]}]}'

# Wait for processing to complete... (poll or listen for SSE)
sleep 30

# Turn 2: Add a follow-up requirement
curl -s -X POST "$BASE_URL/sessions/$SESSION_ID/events" \
  "${HEADERS[@]}" \
  -H "Content-Type: application/json" \
  -d '{"events": [{"type": "user.message", "content": [{"type": "text", "text": "Add unit tests and a CI configuration to the project."}]}]}'

Common errors when sending events to a Session:
HTTPTypeTrigger condition
409conflict_errorSending a message to a Session in the processing status. You must first cancel the current turn or wait for the status to become idle.
404not_found_errorThe Session does not exist or has been deleted.
Example 409 error response:
{
  "type": "error",
  "error": {
    "type": "conflict_error",
    "message": "Session is currently processing a turn. Cancel the current turn or wait for completion."
  }
}

Best practices

  1. Version locking — In production environments, always create Sessions by using the {"id": ..., "version": ...} format.
  2. Timely cancellation — Cancel unneeded Sessions to release resources.
  3. Monitor usage — Regularly check the usage field to avoid unexpected costs.
  4. Tag with metadata — Use the metadata field to record business context, such as task IDs or trigger sources.

FAQ

Q: Do Sessions have a timeout mechanism? A: An idle Session is retained for a period of time. Sessions inactive for an extended period may be automatically archived. Create Sessions on demand and cancel them after tasks complete. Q: What happens if I send a message to a Session that is in the processing status? A: The API returns an HTTP 409 conflict_error. Cancel the current turn or wait for the Session to return to idle before sending a new message. Q: What is the maximum number of turns a Session supports? A: No hard limit, but the model's context window size imposes a practical limit. As the conversation grows, earlier content may be truncated. Q: How do I get the complete conversation history of a Session? A: Call the GET /sessions/{id}/events operation to retrieve all events for the Session, including user messages and Agent responses. Q: Can a canceled Session be reused? A: Yes. After you cancel a Session, its status automatically transitions from canceling back to idle, and the Session remains available. You can send the next user.message to continue the conversation. Only the archived status is a terminal state. An archived Session cannot be restored.

Next steps

Tutorials
API Reference