Start a session
A Session is one stateful Agent execution. It uses an Agent and Environment and preserves its messages, Events, and current state. You send messages to the Session, and it returns a stream of Events.
Session lifecycle
- Create → CREATING A new Session enters the
CREATINGstate while AstraBox prepares or assigns its runtime. - CREATING → READY The Session is ready for input.
- READY → BUSY After you send a message, the status changes to
BUSY. - BUSY → READY When the current turn completes, the Session returns to
the
READYstate, ready for the next turn. It can reportBACKGROUND_RUNNINGwhile child tasks remain active. - BUSY → INTERRUPTING → READY When you interrupt a running Session, its
status transitions to
INTERRUPTINGbefore returning toREADY. The Session remains available for use. - RECOVERY_REQUIRED or TERMINATED The conversation remains stored, but its runtime must be recovered or recreated before more work can run.
- DELETED (terminal state) A deleted Session cannot be restored.
A Session is a state machine with the following core statuses:
| Status | Description | Transitions to |
|---|---|---|
CREATING | Preparing or assigning the runtime. | READY, TERMINATED |
READY | Ready for a user message. | BUSY, TERMINATED, RECOVERY_REQUIRED, DELETED |
BACKGROUND_RUNNING | Ready for foreground input while child tasks remain active. | READY, BUSY, TERMINATED, RECOVERY_REQUIRED, DELETED |
BUSY | The Agent is processing the foreground turn. | INTERRUPTING, READY, RECOVERY_REQUIRED, TERMINATED |
INTERRUPTING | Interruption requested; waiting for the running turn to stop. | READY, RECOVERY_REQUIRED |
RECOVERY_REQUIRED | Stored history is available, but the runtime requires recovery. | READY, CREATING, TERMINATED, DELETED |
TERMINATED | The runtime is offline. | CREATING, DELETED |
DELETED | Deleted. | — (terminal state) |
Fields
| Parameter | Type | Description |
|---|---|---|
session_id | string | System-generated Session ID. |
agent_id | string | The ID of the Agent that started the Session. |
state | string | The current Session status. |
title | string/null | The title of the Session. |
model_name | string/null | The model reported for the current runtime. |
permission_mode | string/null | The permission mode selected for the Agent program, when supported. |
current_turn_id | string/null | The active turn ID. |
last_turn_status | string/null | The status of the most recent turn. |
created_at | string/null | The time when the Session was created. |
updated_at | string/null | The time when the Session was last updated. |
Session list responses contain a summary. GET /api/v1/sessions/{session_id} returns the complete current details.
Create a session
A Session starts from an Agent. The Environment is already selected by that Agent.
From the console
- Open Agents in the AstraBox console.
- Choose an Agent.
- Select Start conversation.
The new Session opens when its runtime is ready.
Use an Agent ID
For an integration, send the Agent ID in the request path:
# Create a Session using an Agent ID
curl --silent --show-error --request POST \
"$SERVICE_URL/api/v1/agents/$AGENT_ID/conversations" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: create-code-review-session' \
--data '{}'
A successful request returns the Session ID:
{
"code": "OK",
"message": "success",
"data": {
"session_id": "SESSION_ID",
"agent_id": "AGENT_ID",
"deployment_name": "code-reviewer"
}
}
The Idempotency-Key header is optional. Reusing the same key for the same
user and Agent returns the same Session instead of creating a duplicate.
Agent field format
| Format | Example | Behavior |
|---|---|---|
| Request path | /agents/AGENT_ID/conversations | Creates a Session for that Agent ID. |
AstraBox does not accept an Agent object or Agent version when creating a Session. The Session records the Agent identity and resolves its configuration when a runtime is prepared.
State transitions
Turn request body format
The request body for POST /sessions/{id}/ai-stream contains one user message
and returns that turn as an AI SDK UI Message Stream v1 event stream.
| Parameter | Type | Required | Description |
|---|---|---|---|
content | string | Yes | The user message. |
client_message_id | string | No | A caller-generated idempotency key for the message. |
permission_mode | string | No | A permission mode supported by the Session's Agent program. |
READY → BUSY
When you send a message to a Session, its status changes from READY to BUSY.
A Session in BACKGROUND_RUNNING can also accept a new foreground turn.
# Send a message and stream the response
curl --no-buffer --silent --show-error --request POST \
"$SERVICE_URL/api/v1/sessions/$SESSION_ID/ai-stream" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{
"content": "Analyze the code complexity of all Python files in the current directory.",
"client_message_id": "analysis-1"
}'
BUSY → READY
When processing completes, the Session automatically returns to READY. It
reports BACKGROUND_RUNNING instead if child tasks are still active. The
stream ends with data: [DONE] after the foreground turn reaches a terminal
result.
Interrupt a session
You can interrupt a running Session.
# Interrupt a Session
curl --silent --show-error --request POST \
"$SERVICE_URL/api/v1/sessions/$SESSION_ID/interrupt" \
--header "Authorization: Bearer $ACCESS_TOKEN"
An interrupt stops the active turn, not the Session or its saved history. After the turn settles, you can send the next message to continue.
Retrieve sessions
# Retrieve a single Session
curl --silent --show-error \
"$SERVICE_URL/api/v1/sessions/$SESSION_ID" \
--header "Authorization: Bearer $ACCESS_TOKEN"
# List all Sessions (with pagination)
curl --silent --show-error \
"$SERVICE_URL/api/v1/sessions?page=1&limit=10" \
--header "Authorization: Bearer $ACCESS_TOKEN"
Example paginated response:
{
"code": "OK",
"message": "success",
"data": {
"sessions": [
{
"session_id": "SESSION_ID",
"agent_id": "AGENT_ID",
"state": "READY",
"title": "code-reviewer",
"created_at": "2026-05-18T12:00:00Z",
"updated_at": "2026-05-18T12:30:00Z"
}
],
"has_more": false,
"next_cursor": null
}
}
Model usage
When the Agent program reports token usage or model cost for a completed turn, the console shows those values with the turn result. Billing and quotas remain with the model service configured for your deployment.
Session and Agent version binding
A Session records the Agent identity; it does not snapshot or lock an Agent version.
- AstraBox resolves the current Agent and Environment when it first prepares a runtime for the Session.
- Saving an Agent or Environment does not reconfigure an active task or running runtime in place.
- If AstraBox later recreates the runtime, the same Session can use the current saved Agent and Environment configuration.
- The Agent
versionfield detects concurrent updates. It is not a selectable configuration version for a Session.
Multi-turn conversation
Sessions support multi-turn conversation. After the foreground turn completes, send the next message to the same Session.
BASE_URL="$SERVICE_URL/api/v1"
# Turn 1: Make the initial request
curl --no-buffer --silent --show-error --request POST \
"$BASE_URL/sessions/$SESSION_ID/ai-stream" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{"content":"Create a Python Flask project scaffold.","client_message_id":"turn-1"}'
# Turn 2: Add a follow-up requirement
curl --no-buffer --silent --show-error --request POST \
"$BASE_URL/sessions/$SESSION_ID/ai-stream" \
--header "Authorization: Bearer $ACCESS_TOKEN" \
--header 'Content-Type: application/json' \
--data '{"content":"Add unit tests and a CI configuration to the project.","client_message_id":"turn-2"}'
Share a Session
Open the Session and select Share to create a read-only link. Choose an expiry time and whether viewers may download workspace files. The link itself grants read access, so send it only to intended viewers and revoke it when it is no longer needed. Viewers cannot send messages or change the Session.
Status-related error codes
Common errors when sending input to a Session:
| HTTP | Code | Trigger condition |
|---|---|---|
| 409 | SESSION_BUSY | The Session already has an active turn, is still stopping, or is completing recovery. |
| 404 | SESSION_NOT_FOUND | The Session does not exist, has been deleted, or is not visible to the caller. |
| 400 | INVALID_REQUEST | Required input is missing, or a pending interaction must be answered first. |
Example 409 error response:
{
"code": "SESSION_BUSY",
"message": "session already has an active turn",
"data": null,
"error": {
"code": "SESSION_BUSY",
"status_code": 409,
"category": "state",
"retryable": true,
"owner": "session",
"user_message": "session already has an active turn"
}
}
Best practices
- Use idempotency keys — Give each Session creation request a stable
Idempotency-Keyand each message a stableclient_message_id. - Interrupt when needed — Interrupt a turn that should no longer run; archive a Session when you no longer need it in the console.
- Keep the stream cursor — Save the latest event
seqand reconnect withafter_seqafter a network interruption. - Restore from Session state — Read the Session and its saved messages when an integration reconnects.
FAQ
Q: Do Sessions have a timeout mechanism?
A: A Session does not have a fixed product timeout. Runtime lifetime follows the Environment and deployment settings. If its sandbox is reclaimed, the saved Session remains available and a later turn can create or assign another runtime.
Q: What happens if I send a message to a Session that is in the BUSY status?
A: POST /sessions/{id}/ai-stream returns HTTP 409 SESSION_BUSY. Wait for the
foreground turn to settle or interrupt it. Integrations that submit input and
consume output separately can use POST /sessions/{id}/turn-inputs; whether
input can join an active turn follows the selected Agent program.
Q: What is the maximum number of turns a Session supports?
A: There is no hard limit, but the selected model and Agent program determine how conversation context is managed.
Q: How do I get the complete conversation history of a Session?
A: Call GET /sessions/{id}/messages and page backwards with before. During
an active turn, the first page also includes messages that are still being
generated.
Q: Can an interrupted Session be reused?
A: Yes. After you interrupt a Session and the active turn settles, send the next message to continue. Interrupting a turn does not delete the Session.
Next steps
- Overview — Learn about the AstraBox architecture.
- Quickstart — Walk through a complete end-to-end example.
- Define an Agent — Learn more about Agent configuration.
- Environments — Customize your runtime Environment.