Skip to main content
A session is a durable conversation with a deployed agent. Each turn appends input and streamed runtime events to the session, allowing clients to resume a conversation without rebuilding its history locally. The events are listed on Session events. A session keeps the deployment it was created on, chosen by the platform from the alias it was addressed to. Advancing Development or promoting to Production changes which deployment new sessions get; turns sent to an existing session keep running the code it started with, including its declared tools and memory resources. To run new code, start a new session. Memory documents are not pinned: they belong to the project and environment, so a new session bound to the same document reads what the old one saved.

Agent playground

Open a project in the dashboard and choose Agent playground. Select the agent and environment independently, then create a new session or resume a previous playground session. Playground sessions stay in the playground list. Sessions started through an API appear under Sessions, where their durable turn history can be inspected. See Playground and debugging for target selection and the debug inspector.

Finding sessions

Give a session labels when you create it, such as the ticket, repository or user it works for, and list sessions by project, environment, agent, deployment, status, creation or update time and label instead of keeping your own index of session ids. The list returns rows with the session’s status, its current turn activity and its latest result, and never the prompts or messages; open a session for its turns and events. The query, the row shape and the label bounds are on the API reference. When one session stands for one record in your application, give it that record’s id as its externalReference at creation. The reference is stored as given, returned on the session and its lifecycle events, and is an exact list filter: after a lost create response, retry with the same request key first, then GET /sessions?externalReference=<ref> finds the session however many unrelated sessions have been created since. Retrying the key with a different reference is refused, so a record cannot be attached to the wrong session. Bounds and semantics are on the API reference. The list is paged: at most 100 rows per request, 50 by default, newest created first. Follow nextCursor with the same filters until it is null; every session matching the filters appears exactly once, however many were created in the same instant. The TypeScript client does this for you with sessions.iterate(filters).

Execution, labels and results

These describe different parts of a session: A report does not finish a turn, and each report replaces the whole result. Later work can run, fail or be cancelled while an earlier result remains. For a review queue, check current activity, the last settled turn’s status, and whether result.turnId matches that turn before treating the report as ready. Your application decides what the reported data means.

Questions

A turn can end by asking. When the agent calls the ask tool, the turn completes with outcome: "question" and the session’s question is set:
options is empty for a free-text question. question is null when nothing is open, and it is independent of result: a session can hold a result and an open question at the same time. A consumer that only knows completed turns still reads an asking turn correctly, because its status is completed. Answer by sending a turn that names the question with answers:
The agent reads the reply as useInput().answer. Naming a question that is not the open one is refused with 409 question_stale; read the session again and answer its current question. While a question is open, a turn sent without answers does not run on its own. It is held, and delivered with the answer, in order, as steering, so the turn that interprets the answer sees every constraint written in the meantime. steering carries a bounded number of held inputs, up to 64 KiB; the rest run as ordinary turns after the answer, in order. The API answers a held input with 202 { status: "held", questionId } and no turnId; see Turns. A turn already queued behind the asking turn settles as cancelled with reason held and keeps its turn id. Held inputs are in the event log as message.held, then message.delivered or message.discarded. One question is open at a time. The answering turn may ask again, which opens a new question. A question closes without an answer with question.closed { reason }: Interrupting a turn does not close a question. In Linear, messages typed while the agent works usually arrive after the answer; see Ask before acting.

Durability and recovery

Closing the browser or redeploying your application does not discard work the API has accepted. Reopen the session and resume reading its durable event log. If a submission’s response was lost, retry with the same request key and body; see Starting work from an application. Durable history does not make every command resumable. A lost computer can leave a command’s outcome unknown; OpenComputer does not automatically replay that command or roll back its effects. The turn can continue with a tool error or fail. Inspect the recorded outcome and verify external effects before asking the agent to retry. Interrupt stops the current turn while keeping the session available for more work. End closes the session and revokes its memory writes. Neither operation undoes completed writes; their different acknowledgement and cleanup guarantees are described in the API reference.

CLI

Start a session against the development agent:
The session command always uses the current project’s bound Development deployment. It does not select between local and remote runtimes. Projects with multiple agents may select another member of the bound project. The environment remains Development:
Add --verbose to stream non-message lifecycle, runtime, tool, egress, usage, and turn events. Assistant message text continues to stream normally:
Or manage the durable session lifecycle explicitly:
list shows the newest sessions first, one page at a time; narrow it with exact filters and continue from the cursor the previous page printed. With --json the page is printed as { sessions, nextCursor } for scripts:
--agent takes the agent’s id, --limit is 1 to 100, and --cursor continues only with the filters that produced it. Bind memory documents when creating a session; add --create-document to create the ones that do not exist yet:
Follow the durable event log directly. With --json, each event is one NDJSON record suitable for a coding agent or log processor:
Project scripts resolve the opencomputer binary from the installed @opencomputer/cli package. For a one-off invocation outside those scripts, select the scoped package explicitly:
Use --keep on supported commands when the session should remain active after the command exits.

Workspace files

Files an agent writes under /workspace (reports, captures, screenshots, tool output) can be listed and downloaded with session files. Newly written files appear gradually and may take a few moments to finish syncing. Refresh or list the workspace again if a file has just been created. Downloads never pass through the model or the session transcript: OpenComputer authorizes the exact versioned workspace object for a short-lived direct download through its file-delivery edge. The CLI streams that object to disk, checks its byte count, and computes SHA-256 locally before the file is saved.
cp is an alias for download. Workspace paths may be written relative to /workspace or with the /workspace/ prefix; paths that leave the workspace are refused before any request is made. Each download is written to a temporary file and renamed into place only after the expected byte count is received; SHA-256 is reported from the completed local file. An interrupted transfer never leaves a partial file behind. The versioned S3-backed workspace remains the source of the file in the CLI, the session page’s Files tab, and the playground debug inspector.

From an application

Applications create sessions with the management API: POST /api/managed-agents/sessions with an API key, then turns and the event log under that session. The TypeScript client wraps those routes; its sessions.startOnDocument creates a memory document and a session bound to it in one call. In the browser, the useAgent hook attaches to a session your server created and renders its messages.

Input sources

Inside an agent, useInput().source identifies how the current work arrived. This lets the same agent distinguish direct work from delegated subagent work without defining another session type.