Skip to main content
@opencomputer/sdk/agents is the TypeScript client for the management API: create sessions, send turns, read the event log, list and label sessions, and manage a project’s memory, webhooks, event subscriptions and GitHub repositories. Use it in your application’s server; use @opencomputer/react in the browser and @opencomputer/agent to define agent behavior. The client uses web-standard APIs and runs on Cloudflare Workers without Node compatibility, Vercel functions, Deno and Node. The package root, @opencomputer/sdk, provides the separate sandbox client.
Use it from trusted server code. The key belongs to an organization and reaches every project, agent and session in it; it must not reach a browser. Authenticate your users and check their access before forwarding requests.
This client requires SDK 2.0 or later. Version 2 removes the older session client and moves startSessionOnDocument, memory types and event-subscription types to @opencomputer/sdk/agents. See the migration notes for changed imports and errors. Applications using the older session API should remain on SDK 1.1.1 until migrated.

new OpenComputer(options)

Methods accept an AbortSignal in their options; startOnDocument takes signal in its params. Return shapes are listed below. Paged session lists return { sessions, nextCursor }; repository lists return { repositories, nextCursor }. Event reads return an array.

Errors

HTTP failures throw OpenComputerError with code, status and message. code is the API’s stable code when the body carried one (idempotency_conflict, session_ended, insufficient_credits, session_publication_unconfirmed); when the body had only text, it is derived from the status: unauthorized, forbidden, not_found, conflict, rate_limited, unavailable for 5xx, request_failed otherwise. A 429 also carries retryAfter in seconds, and an error the API tied to a session carries sessionId. Network failures, response-body read failures and cancellation propagate the underlying error, such as TypeError or AbortError. They do not prove that a write was rejected. A request can commit before its response is lost. The client does not retry automatically. Keep the same parameters and key for a submission’s retries; use a new key only for new work. Use bounded backoff and an AbortSignal, and retain the submission if the retry budget expires. Aborting the HTTP request does not cancel admitted work. A successful create or label update confirms publication to the list. See the Management API for each operation’s errors and guarantees. The client does not follow redirects. The API key is sent to baseUrl and to no other origin: a redirect answer fails the call with code redirected and the redirect’s status, and nothing is sent to the address it named. Check baseUrl when you see it. Two codes come from the client rather than the API:

Validation

The client checks response envelopes and selected fields before returning; unknown fields pass through. Application-owned values such as session.result.data and turn payloads still need your application schema. Event reads check seq, type and that data is an object. They do not validate each known event type’s payload; identity and timestamp fields are checked only when present. The exported event types describe the API contract, not complete runtime validation. Validate event data before using it where its contents affect application correctness or access.

Sessions

create takes agentId, deploymentId, environment, memory, source, labels and externalReference as documented. turns.send takes input, idempotencyKey, mode, payload and answers, the id of the open question the input answers; both create and turns.send send the key as the Idempotency-Key header. The receipt carries the turn’s persisted status: queued or running for a new turn, and for a repeated key the existing turn’s status, completed, failed or cancelled once it has settled, with duplicate: true. The client maps nothing, so a retry after a lost reply learns what became of the turn. An input sent while a question is open, without answers, runs no turn: its receipt is { status: "held", questionId, duplicate } with no turnId ("discarded" once a stop ended the question). list takes the exact filters of GET /sessions: project or projectId, environment, agent or agentId, status, deploymentId, externalReference, createdAfter, createdBefore, updatedAfter, labels (up to three, sent as label.<key>=<value>), plus cursor and limit (1 to 100, default 50). iterate takes the same query and requests the next page whenever the previous one is consumed, stopping when nextCursor is null; it reads live rows, so a session created while you iterate may or may not be seen.

Create and submit

Create the session, then send its first turn. Address the agent by its environment alias and retain both keys and the inputs. Retrying either call then returns the same session or turn, even if the agent is redeployed between attempts: the platform records the deployment the session started on. Pinning a deploymentId is an advanced option, not part of this flow.
Send follow-ups to the same session with a fresh key per submission. To display work in a browser, attach the React hook through your authenticated application routes.

Read progress and results

Read events from sequence 0, then request only events after the last sequence processed:
Each read returns up to 500 events. Continue immediately while catching up; when a read is empty, wait before polling again. A cursor skips earlier events; it does not reconstruct state you have discarded. See Session events for payloads and replay. sessions.get(id) returns the latest typed result, if the agent has reported one. Results retain their turn provenance and can outlive later work; see Sessions before treating a result as ready for review.

Start a session on a memory document

sessions.startOnDocument creates a memory document if it does not exist, then a session bound to it, and reports both ids and whether each already existed. These are two requests, not an atomic operation: the document remains if session creation fails. Retries reuse the document and converge on the session while the agent, environment and bindings remain unchanged.
The steps, in order:
  1. PUT /projects/<projectId>/memory/<resource>/documents/<documentId> with If-None-Match: * and the document body. 201 means the document was created. 412 means it exists; the call reads it with GET and leaves its content as it is. A 404 on that read means the ID was deleted and is reserved, which fails with code memory_document_deleted, since a binding to it would fail admission.
  2. POST /sessions with agentId: "<agent>@<environment>", source, and memory set to your further bindings plus { [resource]: { scope: "document", id: documentId, access } }. The Idempotency-Key header is sessionIdempotencyKey(idempotencyKey), the SHA-256 hex digest of opencomputer.memory.session, a NUL byte and your key. 201 created the session; 200 means the key had already created it. Anything else under that key fails with code idempotency_key_reused; the document was left as it is.
The result: The helper addresses the environment’s agent alias on every call; the platform records the deployment the session started on, so a retry after a redeploy returns the same session. A new key would create another session; it does not recover a lost response. startSessionOnDocument({ apiKey, baseUrl?, fetch?, ...params }), exported from the same subpath, is the standalone form of the call for code that holds a key and no client, and sessionIdempotencyKey(key) derives the session-create key.

Projects

Memory

Every call takes { environment } last; conditional writes also take the revision the write is conditional on, sent as If-Match. Bodies, the document object and the error codes are on Document memory.

Webhooks

create and rotateToken return the webhook with its token and full invocationUrl once; see Agent webhooks.

Event subscriptions

The shapes are on Event subscriptions.

GitHub repositories

projects.github.repositories(p, { environment, cursor?, limit? }) calls GET /projects/<p>/github/repositories and returns { repositories, nextCursor }, each repository { id, fullName, private, defaultBranch, archived } as the environment’s GitHub installation covers them.

Agents and deployments

Types

The subpath exports the types of every object above: Session, SessionSummary, SessionCreated, Turn, TurnReceipt, SessionEvent, Project, AgentSummary, Deployment, Webhook, Repository, the Create…Params and List…Query shapes, and DataValue for JSON payloads and results. The memory types (MemoryDocument, MemoryBindings, SessionMemoryBinding, MemoryResourceInventory, the document bodies, MemorySavedEvent, MemoryErrorCode) and the event subscription types (EventSubscription, CreateEventSubscriptionBody, OutcomeEvent, EventInput, TurnOutcomeDelivery, EventSubscriptionErrorCode) are exported from the same place.