Skip to content
GitHub Get Started
Agent

Agent Sessions

Sessions are the unit of interaction with an agent. Create one session per task, send prompts, and consume event history.

For SDK-based flows, sessions can be restored after runtime/session loss when persistence is enabled. See Session Restoration.

import { SandboxAgent } from "sandbox-agent";
const sdk = await SandboxAgent.connect({
baseUrl: "http://127.0.0.1:2468",
});
const session = await sdk.createSession({
agent: "codex",
cwd: "/",
});
console.log(session.id, session.agentSessionId);
const response = await session.prompt([
{ type: "text", text: "Summarize the repository structure." },
]);
console.log(response.stopReason);
const unsubscribe = session.onEvent((event) => {
console.log(event.eventIndex, event.sender, event.payload);
});
await session.prompt([
{ type: "text", text: "Explain the main entrypoints." },
]);
unsubscribe();

Each event’s payload contains a session update. The sessionUpdate field identifies the type.

agent_message_chunk

Streamed text or content from the agent’s response.

{
"sessionUpdate": "agent_message_chunk",
"content": { "type": "text", "text": "Here's how the repository is structured..." }
}
agent_thought_chunk

Internal reasoning from the agent (chain-of-thought / extended thinking).

{
"sessionUpdate": "agent_thought_chunk",
"content": { "type": "text", "text": "I should start by looking at the project structure..." }
}
user_message_chunk

Echo of the user’s prompt being processed.

{
"sessionUpdate": "user_message_chunk",
"content": { "type": "text", "text": "Summarize the repository structure." }
}
tool_call

The agent invoked a tool (file edit, terminal command, etc.).

{
"sessionUpdate": "tool_call",
"toolCallId": "tc_abc123",
"title": "Read file",
"status": "in_progress",
"rawInput": { "path": "/src/index.ts" }
}
tool_call_update

Progress or result update for an in-progress tool call.

{
"sessionUpdate": "tool_call_update",
"toolCallId": "tc_abc123",
"status": "completed",
"content": [{ "type": "text", "text": "import express from 'express';\n..." }]
}
plan

The agent’s execution plan for the current task.

{
"sessionUpdate": "plan",
"entries": [
{ "content": "Read the project structure", "status": "completed" },
{ "content": "Identify main entrypoints", "status": "in_progress" },
{ "content": "Write summary", "status": "pending" }
]
}
usage_update

Token usage metrics for the current turn.

{
"sessionUpdate": "usage_update"
}
session_info_update

Session metadata changed (e.g. agent-generated title).

{
"sessionUpdate": "session_info_update",
"title": "Repository structure analysis"
}
const page = await sdk.getEvents({
sessionId: session.id,
limit: 50,
});
for (const event of page.items) {
console.log(event.id, event.createdAt, event.sender);
}
const sessions = await sdk.listSessions({ limit: 20 });
for (const item of sessions.items) {
console.log(item.id, item.agent, item.createdAt);
}
if (sessions.items.length > 0) {
const loaded = await sdk.resumeSession(sessions.items[0]!.id);
await loaded.prompt([{ type: "text", text: "Continue." }]);
}

Set the model, mode, or thought level on a session at creation time or after:

// At creation time
const session = await sdk.createSession({
agent: "codex",
model: "gpt-5.3-codex",
mode: "auto",
thoughtLevel: "high",
});
// After creation
await session.setModel("gpt-5.2-codex");
await session.setMode("full-access");
await session.setThoughtLevel("medium");

Query available modes:

const modes = await session.getModes();
console.log(modes?.currentModeId, modes?.availableModes);

For config options beyond model, mode, and thought level, use getConfigOptions to discover what the agent supports and setConfigOption to set any option by ID:

const options = await session.getConfigOptions();
for (const opt of options) {
console.log(opt.id, opt.category, opt.type);
}
await session.setConfigOption("some-agent-option", "value");

For agents that request tool-use permissions, register a permission listener and reply with once, always, or reject:

const session = await sdk.createSession({
agent: "claude",
mode: "default",
});
session.onPermissionRequest((request) => {
console.log(request.toolCall.title, request.availableReplies);
void session.respondPermission(request.id, "once");
});
await session.prompt([
{ type: "text", text: "Create ./permission-example.txt with the text hello." },
]);

To auto-approve all permission requests, respond with "once" or "always" in your listener:

session.onPermissionRequest((request) => {
void session.respondPermission(request.id, "always");
});

See examples/permissions/src/index.ts for a complete permissions example that works with Claude and Codex.

await sdk.destroySession(session.id);