Agents APISessions
Manage sessions
Check a session's state, pause and resume it, find your sessions, and clean up.
Session state
const current = await sessions.get(session.id)
console.log(current.status, current.last_seq, current.error){
"id": "ags_4843742656c9cbc90685c6d2",
"object": "agent.session",
"status": "idle",
"agent": { "model": "bedrock/us.anthropic.claude-sonnet-5", "instructions": "Answer in one short sentence.", "permissions": null },
"environment": { "type": "none" },
"metadata": { "customer": "cus_123" },
"created_at": "2026-09-28T07:17:41.522000+00:00",
"updated_at": "2026-09-28T07:17:52.106000+00:00",
"paused_at": null,
"ended_at": null,
"instance_number": 1,
"instance_context": "new",
"last_seq": 8,
"error": null
}| Field | Meaning |
|---|---|
| status | Where the session is in its lifecycle (below). |
| last_seq | The newest event number. Pass it as after to read only what comes next. |
| error | { type, message } if something went wrong with the sandbox, otherwise null. |
| instance_number · instance_context | Whether the conversation was restored after a pause: instance_context is full, workspace_only or new. instance_number goes up by one each time the session resumes (see Pause and resume). |
| environment · metadata | The repositories it works on, and your own key/values. |
Statuses
| Status | Meaning |
|---|---|
| provisioning | A sandbox is starting. Messages sent now are delivered when it's ready. |
| idle | Ready and not working. A message starts a run. |
| running | Working on a run. A message steers it. |
| waiting | Blocked on an approval. |
| pausing · paused | The sandbox has been released. The conversation and files are kept, and a message resumes it. |
| stopping · stopped | Deleted, or paused for too long. Events and patches can still be read. |
| failed | Couldn't start. See error, and create a new session. |
Pause and resume
Sandboxes are temporary, but sessions aren't. A paused session keeps its conversation and files without holding a sandbox. The next message starts a new sandbox from where it left off, with repositories back at the commits they started from and the agent's changes on top.
await sessions.pause(session.id)
await sessions.wait(session.id, { until: ["paused"] })
// Later: a message resumes it. No need to call resume() first.
const { last_seq } = await sessions.get(session.id)
await sessions.message(session.id, "What word did I ask you to remember?")
for await (const event of sessions.events(session.id, { after: last_seq })) {
if (event.type === "text.ended") console.log(event.data?.text)
if (event.type === "run.completed" || event.type === "run.failed") break
}
const resumed = await sessions.get(session.id)
console.log(resumed.instance_number, resumed.instance_context)You asked me to remember the word "pelican".
2 fullThe session resumed (instance_number: 2) with the whole conversation restored (instance_context: "full"). With workspace_only, the files came back but the conversation starts over, so include the context the agent needs in your message. new means the session hasn't been resumed yet.
| Sessions pause or stop on their own | Default |
|---|---|
| Idle, with nothing to do → paused | 30 minutes |
| One sandbox running for a long time → paused | 4 hours |
| Paused and untouched → stopped | 7 days |
A session that's waiting for an approval is never paused for being idle. These are the defaults; your administrator may set others. If a sandbox disappears unexpectedly, the session moves to paused with an error, and the next message resumes it with its files.
Find your sessions
Sessions are listed newest first, 20 per page by default and up to 100. Use metadata to tie them to your own records. You only ever see sessions you created, in the organization you're working in.
const page = await sessions.list({ limit: 20 })
const mine = page.data.filter((s) => s.metadata?.customer === "cus_123")
console.log(mine.map((s) => `${s.id} ${s.status}`))When has_more is true, pass next_after as after for the next page.
Delete a session
Deleting stops the session for good and releases its sandbox. A final patch is saved first, and events and patches stay readable afterwards.
const stopped = await sessions.delete(session.id)
console.log(stopped.status)finally block, as every example on these pages does.Retry safely
Pass an idempotency key when creating sessions from code that may run twice, such as a queue worker or a webhook handler. A second call with the same key returns the first session instead of starting another. The same key with different settings raises conflict.
const settings = {
agent: { model: "bedrock/us.anthropic.claude-sonnet-5" },
input: `Summarize ticket ${ticket} in one line.`,
idempotencyKey: `summarize-${ticket}`,
}
const first = await sessions.create(settings)
const retry = await sessions.create(settings) // e.g. your job queue ran twice
console.log(first.id === retry.id) // true: one session, not two- When there's no capacity, creating or resuming fails with
runner_unavailable. Retry after a short wait, with the same key. - Your organization may cap active sessions. Past the cap, creation fails with
session_limit_reached.