Skip to main content
A session is one run of an agent on a task. It runs in its own sandbox, starts on the agent’s current version in the environment you choose, and keeps a transcript you can stream, read, and continue.
You need an agent and an environment. If the environment has a setup script, it must have passed a current setup run. Starting, messaging, moving, and stopping sessions needs the Developer or Admin role; the User role can list and read them, and can read a session’s version state. API calls use a key from API keys.

Start a session

Send the agent, the environment, and the task. Name the files you want back, so the agent saves them as deliverables.
  1. In the sidebar, click Sessions, then click Launch session.
  2. Under Configuration, select an Agent and an Environment.
  3. Under Task, write the Opening message: the task, the deliverables you want by name, and what done looks like.
  4. Optionally, choose vaults under Credentials, a mode under Team, and add Custom metadata.
  5. Click Launch session.
The session is accepted right away and starts in the background. The response is 202 Accepted:
Keep session_id. 202 means the session was accepted, not that it is running. status_path is relative to https://api.recursion.labelbox.com and already starts with /managed-agents, as does the Location response header. The Idempotency-Key header is required. Use a value that identifies the work, such as a job id, and send it again on every retry: the same request with the same key returns the same session instead of starting a second one.
Keys share one namespace across keyed mutations in your organization, so include the operation and work identity. Completed receipts last about 24 hours, pending claims can be reclaimed after about 1 hour, and deduplication is not guaranteed after expiry. The session id is derived deterministically from the durable receipt, so an exact replay returns the same session_id. See Idempotent mutations.

Watch it work

Stream the session’s events to follow along as the agent works. The stream replays what already happened, then stays open for new events, and closes when the session reaches a terminal status.
Open the session from Sessions. The transcript updates live, and the status badge shows the current state.
You see the agent’s steps as they happen. This output is abridged; each data line carries the full event.
Events lists every frame type and shows how to resume a dropped stream. To poll instead, read the session with view=summary and stop on any terminal status, not only completed, and also when the session needs you.
An interrupted or sleeping session stays active. An interrupted session waits for Resume or a new message. A sleeping session may also continue at its wake time. A loop that waits only for a terminal status keeps waiting through these pauses.

What success means

When the agent loop finishes, status becomes completed whether or not the task succeeded. Read the final message and open the files it saved to judge the work. To have the work checked against a rubric before the session is done, see Write outcome rubrics. When a session fails, failure holds phase, code, message, retryable, category, and at. category is transient (retry), caller_error (fix the request or setup), or internal. Deliverables appear in the session’s Files tab. Files the agent leaves elsewhere stay in /workspace for later turns, even after a stopped sandbox is released, and can be used when the workspace reopens successfully, but they aren’t captured as deliverables. Deleting the session removes access to its workspace. See Deliverables and artifacts and Download session deliverables. To give a session input files, attach them in Launch session, with resources at start, or in the session’s Files tab while it runs.
In Sessions, click a session. The Session tab shows its state, agent, environment, and Custom metadata. A session an automation started also shows Started by: the Automation, the Trigger that fired, and the Run, each linking back to the automation. See Automations.With the API, view=full (the default) returns the whole session, including the agent and model snapshots and the resolved configuration. view=summary omits agent_snapshot, model_snapshot, and config, which makes polling cheaper. Any other view value returns 400.

Continue the conversation

Send a follow-up to add to the task or ask for changes. A running session reads it at its next turn. An idle or finished root session picks the work up again, and applies a version move that is waiting before it does. The full send options, including the delivery states in the response, are in Events.
Open the session, type in Message the agent…, and click Send. While the agent is working the button reads Queue.
Only root sessions resume. A message to a subagent session in a terminal status returns 409 conflict; message the root session instead. To change direction immediately, use the same sendSessionEvents operation with interrupt: true. The console’s Interrupt & send action does this. The session starts a replacement turn while delegated work continues, and the agent can coordinate any changes that your instruction requires. See Interrupt and send with the same operation for REST, CLI, SDK, and MCP examples.

Interrupt and resume

Interrupt stops the session without adding a new instruction. It cancels the current model call, gives a running tool a short grace period to stop, and stops delegated work. The session stays active, with execution_state: idle and stop_reason: interrupted. Accepted queued messages remain saved. Helper reports, timers, and board updates do not resume it. In the console, click Interrupt below the latest event. Once the session stops, click Resume, or send a new message. Resume continues without adding another message.
resumeSession returns resumed and deliveryState. A stored delivery state means the resume was accepted but starting work was not confirmed; keep observing the session. An interrupt acknowledges durable acceptance before all in-flight work has settled. Keep observing the session until it is idle. Resume and a new message still apply the session’s normal permissions, budget, and credit checks.

Send an image

To show the agent a screenshot or chart, attach it to a message. The model sees the image when its model accepts images. In the session’s message box, click Attach image, choose the image, write your message, and click Send. To use an image from your library, click Attach from Files. Send PNG, JPEG, or WebP; the type is detected from the bytes. An image the session’s image limits refuse returns 400 with the reason. See Limits.

Set a budget

A budget is the most a session may spend, counting its subagents. It covers model requests, tools and sandbox compute, at the price your credits pay. When the session reaches it, the session pauses before its next model request. It goes idle with stop_reason: budget_reached, keeping its work and sandbox. The request in flight when the budget is crossed completes and is charged, so the spend can end slightly over the budget.
Budgets are rolling out. Until they are on for your organization, Launch session has no Budget section, and the API refuses budget and the budget endpoints with 400.
Launch session sets a $10 budget by default. Open Budget to pick $5, $25, $50, No limit, or another amount. It shows about how long the budget lasts at the agent’s typical cost. The session header shows what the session has spent of its budget.
When the session first reaches 90% of its budget, its agents are told to wrap up, so they can finish cleanly instead of pausing mid-task. The session and each of its subagents get the notice once, with their next model request. Outcome graders aren’t told. Each notice is a user message in that session’s events, so you see it in event lists and the stream. You didn’t send it: its content.metadata.session_budget_nearly_reached holds budget_usd and warn_at_percent. The root session also records one session_status event with event_status: "warning" and content.metadata.code: "session_budget_nearly_reached", with budget_usd, spent_usd, and message beside the code. The event stream sends it as session.status. After you raise the budget, the warning comes again at 90% of the new amount. A session started without a budget through the API has none, unless its agent sets multiagent.limits.max_tree_cost_usd. Then the agent’s cap is the session’s budget. To take that default, leave budget out of the request; it is an object, so the API does not accept null for it. A budget can be lower than the agent’s cap, never higher. A session that reached its agent’s cap can’t be raised past it: start a new session to continue the work. To continue a paused session, raise its budget. It continues on its own as soon as the new budget is saved, and the agent is asked to continue the subagents that paused. In the console, click Raise to … and continue under the last event. With the API:
The response is the new budget. It must be more than the session has already spent. Send DELETE to the same path to remove the budget, unless the agent sets a cap. While a session is at its budget, a message that would start a new turn returns 403 session_start_not_admitted with details.reason: "budget_reached". Interrupts still work. A full read of the root session returns budget.maxCostUsd, budget.spentUsd, and, when the agent sets a cap, budget.agentCapUsd. A session bound to a Slack thread (budget.continuesOnRaise: false) is continued by the next reply in its Slack thread instead.

Move a session to another version

A session runs the agent version it started on until you move it. Move it to give work in progress new instructions, tools, skills, or access without starting over: the transcript, sandbox, and files stay.
  1. Open the session. When its agent has a newer version, a notice under the header names both, for example “This session runs Version 2 of backend-fixer. The agent is now on Version 3”.
  2. Click Use Version 3.
  3. Read the comparison of the two versions, then click Use Version 3 to confirm.
The notice changes to “Moving to Version 3” and says when the move applies. Click Withdraw to cancel a move that hasn’t applied yet. If the move is refused, the notice says why and offers Try again.To move several sessions at once, open the agent and choose the Sessions tab. Select the sessions marked Older version, click Use Version 3, and confirm. To move every live session of an agent, use Move all of an agent’s sessions.The console moves a session to its agent’s latest version. To move to any other version, including an older one, use the API.
The request is asynchronous. It records the version to move to and answers at once, whatever the session is doing: the response is 200 with state: pending, and pending is your receipt. It doesn’t interrupt the session, wake it, or start any work. The move applies on its own as soon as it can: right away for a session at rest, and before the next model call for a working one. See When the move applies.
To also replace an active outcome’s grading criteria, send replaceActiveOutcome: true in the same body:
This explicitly reapplies that version’s defaultRubric, including to a caller-defined active outcome or a session already running that version. The target version must have a nonempty default rubric. The replacement keeps the objective and pass limit, retains the old outcome and its grading history with result interrupted, and creates one active replacement. It is bound to the active outcome observed by the request: an outcome you define later is not replaced by that older request. It waits for an evaluation in progress; an outcome that finishes during that wait stays terminal. See Outcomes after a move below. The response is a receipt for requested work. Read listSessionOutcomes after the session’s next model operation to verify the active rubric; a version move alone does not prove the outcome replacement has applied. The version must belong to the session’s agent, and it can be older or newer than the one the session runs. The request needs no Idempotency-Key:
  • Repeating a move with the same outcome policy that is pending, or that the session already applied, changes nothing. You get the current state back.
  • Repeating a move after it failed asks again.
  • The later of two different requests wins.
  • Sending the version the session runs now withdraws a pending move, unless you set replaceActiveOutcome: true to request an outcome refresh on that version.
This operation’s fields are camelCase. The session itself still reports its version as agent_version_id.
  • Root sessions that run an agent. That includes sessions you start in the console or through the API, and sessions an automation or Slack starts. A subagent session follows its root, so move the root. Sessions the service runs itself, such as the session analyst, stay on the version they started with, and so do pull request review sessions.
  • Live sessions, and finished ones that can continue. A session that a follow-up message can start again can be moved. A session that is still stopping, or that can no longer continue, can’t.
  • To any version of the same agent. A version of another agent returns 404 not_found.
  • With create and update access. A move can give the session the vaults a new session on that version would receive, so it needs both, and reading the state needs read access. The Developer and Admin roles have all three; the User role can read the state and can’t move a session. See Organizations and roles.
  • Through the API or the MCP server. An agent that calls the API through the Recursion MCP server can move a session with replaceSessionAgentVersion and read its state with getSessionAgentVersion, with the same access as the API key it uses.

Check the move

getSessionAgentVersion returns the version the session runs, the move that is waiting, the agent’s latest version, and how far each agent in the session’s tree has followed. The state changes as the session works, so read it again instead of keeping a copy. A subagent session, or a session that wasn’t started from an agent, answers 409 conflict. In the console, the transcript shows “Now on Version 3” once the session has moved, and the Session tab of the details panel shows the version in the Agent version row. For a session with subagents or teammates, Agent version by member on the same tab lists how far each one has followed.
After the session has moved, the read shows the new version and nothing waiting:
Version adoption and outcome replacement have separate receipts. A same-version refresh can report pending while its version ID stays unchanged. Outcome replacement may still be waiting after a request reaches current, including while grading is in flight. Read listSessionOutcomes to verify the active criteria.
On the root, adoption follows state: pending while a move waits, and failed after a refused one.

When the move applies

A move never cuts into a model call. A working session finishes the call it is making and the tool calls that came from it, then changes version before its next model call. A session at rest changes version in the background within seconds, and stays at rest.
  • A working session moves before its next model call. A move requested during its last model call applies as soon as the turn ends.
  • A sleeping session moves right away, in the background, and keeps sleeping. Its scheduled wake doesn’t change.
  • A session that finished its turn, or is waiting for your next message, moves right away and keeps waiting.
  • A session waiting on a tool call’s result, such as an approval, moves before its next model call, once the result arrives. Its tools don’t change under a call that is still open.
  • A session whose subagents or teammates are still working moves once they are done, or before its own next model call if that comes first. They share its sandbox and access, which don’t change under them.
  • A cancelled, failed or completed session moves when you send its next message.
  • A session retrying a failing model call doesn’t change model between retries of the same call. A move to a version with a different model applies before the session’s next model call, once the retried call succeeds or you send the session a message. A move that keeps the model can apply at the next retry.
A session that moves while at rest gets everything a working session would: its instructions, model, tools, skills, grants and the notice to the agent are in place before its next turn. Two things wait for that turn:
  • A new model’s summary of the earlier conversation is written before the new model’s first call, so nothing calls a model while the session sleeps.
  • Skill files are copied into the sandbox the next time it’s used, so nothing reaches the sandbox before the move is committed.
Without replaceActiveOutcome, moving a session to the version it already runs changes nothing: it doesn’t resolve skills or list MCP tools again.

What changes and what stays

The agent receives one notice about the move, a message event with role: system that you can read in the session’s events. It names what changed: that its instructions were replaced, whether the model changed, and the skills, tools, MCP servers, integrations, credentials, and roster agents that were added or removed. It lists names only, never secret values. A skill that kept its name and changed its content is listed as updated, and the agent activates it again before relying on it. A session that hasn’t done any work yet gets no notice, because it simply starts on the new version. When the new version uses a different model, the earlier conversation is summarized for the new model before the session continues. A message the earlier model hadn’t read yet stays as you wrote it, and the original events stay in the log.
A move carries the new version’s default credential changes onto the session:
  • Vaults and credentials the new version adds are added.
  • Vaults and credentials the new version removes are removed.
  • What the person who launched the session changed is kept. A vault they added stays, and a credential they unchecked stays out.
Two cases differ:
  • A session whose trigger set its own credentials keeps them. When Slack or an automation started the session with its own grant, including an empty one, the move leaves that grant alone. The record of the move and the agent’s notice both say that the version’s defaults changed and the session kept its own.
  • A session granted whole vaults gains an added vault whole. A session started with vault_ids and no credential_refs holds every credential in each vault, so it receives every credential in a vault the new version adds, including any added to that vault later.
A vault or credential the new version names that no longer exists is skipped, and the session’s events record a warning.When each kind of credential takes effect:
Removing an environment-variable secret from a version doesn’t take it out of a sandbox that is already running. To revoke it, rotate the secret at its provider. See Rotate a credential.
When the new version changes the agent’s defaultRubric, a session graded against the old default follows it. This happens before the session’s next model call, also for a session that moved at rest:
  • An outcome the session took from the old default is replaced. It ends with result interrupted, and a new outcome with the new version’s rubric takes its place, with the same objective. When the new version has no default rubric, the old outcome ends and nothing replaces it.
  • A session that has never had an outcome gets the new default, as a new session on that version with the same opening message would. A session started with skip_default_outcome stays ungraded.
  • An outcome you defined stays by default. That includes an outcome sent at start and one you set later with defineSessionOutcome. Set replaceActiveOutcome: true to replace an active one with the target version’s default rubric, even when the session already runs that version. This preserves its objective and pass limit. A target with no usable default rubric rejects an explicit replacement request with 400 invalid_request.
  • Replacement preserves history and one active outcome. The old outcome ends with result interrupted, keeping its criteria and grading history, and the new outcome becomes active in the same transition.
  • A graded outcome stays. An outcome that has finished is never changed. One that a grader is checking right now is left until that check ends, and is replaced afterwards if it is still open.
An outcome counts as taken from the default when it has no rubric file or evaluator of its own and the session took it from the agent at start. On a session started before the platform recorded where an outcome came from, it counts when its rubric is exactly the old default and its objective is the opening message.
Every open thread in the session’s tree follows the move before its own next model call, after its parent has followed. A thread that is running finishes its current model call first, and one that isn’t running follows when it is next given work. Each receives its own notice.A thread whose parent is closed, or whose parent couldn’t adopt, also keeps the configuration it has. members reports it as retained.Team mode and seats are fixed when the session starts. A move never adds seats or removes a teammate, and the board keeps its tasks, claims, and notes. Seats can shrink: when the new version’s max_concurrent_threads is lower than the team size, the team fills only that many seats from then on, and teammates already working stay.

If a move fails

A move that can’t be applied never stops the session. The session keeps the version it has and keeps working, state becomes failed, and lastFailure gives a code and one fixed sentence in message. Fix the cause and send the request again.
The list can grow, so accept codes that aren’t in it.
A temporary problem doesn’t fail a move at once. The session tries again before its next model calls, and after three attempts records temporarily_unavailable. An MCP server that is new in the version and can’t be reached, or that refuses its token, doesn’t fail the move either: the session moves without that server’s tools and records a warning, as it does at start. Each move is recorded in the session’s events as a session_status event: A thread’s events carry applyId in place of requestId.
  • Team mode and seats are fixed at start. A move doesn’t turn team mode on or off, and seats can shrink but never grow.
  • A running sandbox keeps its environment variables. Environment-variable secrets, and the network destinations a sandbox may reach for granted integrations, are set when a sandbox is created. A move changes them on the session’s next sandbox.
  • A thread adopts after its parent. A thread whose parent hasn’t followed yet waits for it.
  • A session doesn’t change model between retries of one model call. While a session retries a failing model call, a move to a version with a different model waits for its next model call, which comes once the retried call succeeds or you send a message.
  • Moving to the current version normally does nothing. Without replaceActiveOutcome, it isn’t a way to load a newer skill version or list an MCP server’s tools again. With that option, it can refresh an active outcome on the version the session already runs.
  • The environment never changes. To use another environment, start a new session.

Move all of an agent’s sessions

After you publish a new version, you can move every live session of the agent to it with one request. Each session moves exactly as moving one session does, and the request runs in the background, so it works the same for five sessions or thousands. Start the upgrade with startAgentSessionUpgrade. Its JSON body is optional, and it needs an Idempotency-Key:
To refresh active outcomes as well, add Content-Type: application/json and this body to that request:
The option also reaches sessions already running the target version. It has the same safe replacement behavior as the single-session operation: a nonempty target default rubric is required, grading in progress is allowed to finish, and terminal outcomes are retained. Omitting the body, or setting the option to false, keeps the usual inherited-default policy. The response is 202 at once, with a Location header that points to the upgrade:
  • The target is the agent’s latest version when the request is accepted. A version you publish while the upgrade runs isn’t picked up; start another upgrade after this one finishes.
  • Every live root session of the agent is asked: active, queued, idle, and awaiting input. Sessions that can’t move are counted as skipped and left as they are. Which sessions those are is in Which sessions you can move.
  • One upgrade runs per agent at a time. Starting another with the same outcome policy while one runs returns the running upgrade and starts nothing. A different replaceActiveOutcome policy returns 409 conflict; wait for the running upgrade to finish before asking for the new policy. Upgrades of different agents run side by side.
  • Replays return the original response. The same Idempotency-Key on the same request returns the first 202 again, with Idempotency-Replayed: true.
  • It needs create and update access, like moving one session. An agent of another organization, or one that doesn’t exist, returns 404 not_found, and an agent with no version returns 409 conflict.

Follow the upgrade

Read the upgrade with getAgentSessionUpgrade until state is no longer running:
completed means every session has been asked, not that every session has moved or its outcome has been replaced. Each session applies its move as a single move does: sessions at rest move right away without waking, and working sessions before their next model call. Each reports its own progress on getSessionAgentVersion. The read returns the agent’s newest upgrade, and 404 not_found when the agent has none or the last one is past retention.

Stop an upgrade

cancelAgentSessionUpgrade stops the agent’s running upgrade before it asks any more sessions:
The response is the upgrade, as the read returns it. state becomes cancelled once the batch of sessions in progress finishes. Sessions already asked keep their move; to undo one, move that session back to the version it ran. With no upgrade running for the agent, the request returns 409 conflict. All three operations are also tools of the Recursion MCP server: an agent can start, follow and stop an upgrade with the same access as the API key it uses.

Stop or delete a session

Cancel answers { "cancelled": true } and delete { "deleted": true }. You can cancel any session that is not completed, failed, or already cancelled, including an idle one. The cancel response is the same when the session was already finished, so it is safe to repeat. Sandbox teardown can finish shortly after the response.

Find sessions

listSessions returns sessions in your organization, most recently updated first. Filter by status, kind, agent, agent tags, or your metadata.
In the sidebar, click Sessions. The Status, Agent, Agent tags, and Metadata filters cover every session. The search box matches id, agent, state, or metadata on the page shown; paste a full session id to find a session on any page. Click the ID, Status, Created, or Last activity header to sort the whole list, not just the page shown.
root_only=true returns one row per run, without the subagent sessions under it. List rows are summaries: they leave out snapshots, config is empty, and token totals aren’t included. Each row carries the session tree’s costUsd and costState (see Usage and cost).
A page token is valid for one hour and only with the same filters and limit. Changing either returns 400 invalid_request; start again without a token. Because the list is ordered by last update, a session that changes while you page can appear twice or be skipped. Deduplicate by session_id, or filter on a value that does not change.

How a session runs

Two fields describe a session. status says whether it’s still live. While it’s active, execution_state says what the agent loop is doing. When the loop isn’t running, stop_reason says why.
provisioning, queued, running, and idle are execution states of a session whose status is active. completed, failed, and cancelled are terminal statuses: the session does not change on its own after reaching one. A follow-up message to a root session in a terminal status starts it again from provisioning, or from queued when the agent is at its cap. After a cancel, the session gets a new sandbox. After a completed or failed run, the sandbox is reused when possible.Agents already know when their previous run was cut short and when a resumed run starts on a new sandbox. A run is cut short when it fails partway through, is cancelled, or stops unexpectedly. The session’s events then hold a message with role system, which you didn’t send. It says how the run ended, including the error. A run that failed before its first step, such as during setup, gets no such message.When a root session is stopped for review and no subagent is working, its sandbox is stopped with /workspace preserved, and restored from /workspace before the agent’s next tool call; processes it started are gone. A session whose setup ran on its own compute keeps its sandbox until the environment’s idle stop.

What can go wrong

The most common problems:
  • The session stays queued. The agent is at maxConcurrentSessions, or a slot freed while your tenant was out of credit. A queued session starts only when a slot is free and credit is available. Wait, cancel other sessions, raise the agent limit, or add credits.
  • 422 environment_not_verified on start. The environment’s setup script has not passed a current setup run. Run environment setup, then start again. See Environments.
  • A version move stays pending. A move applies before the session’s next model call, and a finished or sleeping session makes none until it gets a message or wakes. Send a message. See When the move applies.
  • status: completed but the task is not done. The loop finishing does not mean the task succeeded. Read the final message, then send a follow-up with what is missing.
Every error is a flat object with required code and message fields and optional details, which can include field, requestId, and retryable. See Errors.
Limits on metadata, referenced sessions, concurrency, and provisioning are in Limits.

Next steps

Events

Stream, send, and read every kind of session event.

Session operations

Search metadata, inspect compute, ask the analyst, and read the tree.

Files

Give a session input files and download its outputs.

Deliverables and artifacts

Ask for deliverables and see how they’re kept.