Skip to main content
Base URL https://api.opencomputer.dev/v3. Management calls authenticate with your org API key; stream and steer also accept a client token. Each section toggles between the TypeScript SDK (@opencomputer/sdk), REST, and the oc CLI — pick one and the whole page follows.
The SDK uses camelCase for fields and params (last_turnlastTurn, idempotency_keyidempotencyKey); the wire shapes below are raw JSON. Opaque blobs — session metadata, event refs/raw — pass through verbatim; everything else (incl. event body) is camelCased. The CLI prints a table, or machine-readable JSON with --json.

Agent URLs and Hooks

Every Agent includes invoke_url (SDK: invokeUrl), its permanent application address. The hostname exposes exactly two invocation routes; all session reads and steering remain on the canonical Sessions API. Both use the same durable session-start path. Root requires one JSON value; Hooks allow either an empty body or one JSON value. Neither returns agent output synchronously. Queries, redirects, arbitrary paths, session routes, and browser CORS are absent. See Agent URLs and Hooks for the complete request contracts.
Root accepts an optional Idempotency-Key. A successful receipt contains request_id, session { id, status, head }, client_token, canonical links { events, messages }, and replayed. Hooks use Idempotency-Key, then webhook-id when the first is absent, and return only request_id, session { id, status }, and replayed. Hook creation returns { hook, hook_url } once. Hook contains id, agent_id, name, status (active|expired|revoked), secret_last4, nullable revoked_reason (manual|secret_exposure), nullable expires_at, and created_at.

Sessions

Create paramsagent is required; the model resolves to Managed (default) or a credential, else 422 no_credential / 422 managed_unavailable.
  • input — the task (string or envelope). Truncate large inputs; let the agent fetch the rest via sandbox tools.
  • model? — run this session on a different model than the agent’s (same provider/model form; its provider must match the agent’s runtime, e.g. anthropic/… for claude). Default = the agent’s model. Pinned for the session’s life like the rest of the snapshot. Rejected (400 invalid) for flue agents — their model is fixed in the deployed artifact.
  • key? — get-or-create (one session per key). Keyless: an Idempotency-Key header makes create retry-safe.
  • metadata? — opaque routing state (≤ 16 KB); on get/list + verbatim in webhooks; never sent to the model, not indexed.
  • limits? { tokens, turn_seconds, turns }: non-monetary. On built-in runtimes, tokens is checked from committed usage before the next turn and can overshoot by one in-flight turn; turn_seconds and turns remain separate. These limits are stored but not enforced for Flue sessions.
  • sources?: working repositories (the token never enters the agent sandbox; see GitHub). Built-in runtimes prepare them before turn one; Flue materializes them lazily. Each registered { repo, ref, sha?, name? } or inline { url, ref, sha, name?, auth }. ref is required; sha is required for inline sources but optional for a registered repo. For every runtime, selected repository access admits only registered repositories allowed by the agent policy and reauthorizes checkout and publishing at use time.
  • Client tokens: scopes? (read/steer), ttl? 60–86400 s (SDK ttlSeconds).
A built-in runtime session pins the agent’s active revision for its whole life. A Flue session records its selected deployment but executes on the agent’s one live Worker; deploying that Worker can therefore affect an existing session. Session Turn Session usage includes reported_turns, unreported_turns, and complete. When complete:false, any token/cost total present is a lower bound. Missing total_cost_usd means unknown, not zero; historical rows may contain {}. Flue session attribution may be best_effort, while its agent/org gateway remains the spend-enforcement authority. See usage and limits. A turn’s yield_reason tells you why it stopped: SessionSource — one of two variants: SourceSummary (sanitized; on create + GET …/sources)

Events

Filter by type (exact or prefix.*), turn_id, limit. after resumes from a seq; level is a visibility thresholduser < progress < internal (default internal; see visibility levels). Switch on type, don’t parse prose. …/messages is an alias for level=user + type=*.message. Event

Steer

Body: { text, idempotency_key? } or { envelope }. Returns 202 (or 200 on idempotent replay) with { event: { id, seq }, session: { id, status, head } }.

Watches

Managed with the SDK (session.watches.create/list/delete), the CLI (oc session watch/watches/unwatch), or REST — authenticate with your org API key (server-side). The agent-facing path is the watch_pull_request runtime tool. Full guide: Watches. wake_on is the wake condition (checks default · review · comment · merge); intent is the freeform “why,” replayed on wake. repo/pr are optional — omitted, they resolve to the PR this session opened. A watch fires only on PRs the same session opened, on Connected-App (oc_app) repos. Limits: 10 active watches per session, 30-day TTL (and never outlives the PR). Watch Delivered events — appended into the session log at level user with source: "github", carrying a normalized summary (not the raw webhook): github.pr.checks_completed · github.pr.review_submitted · github.pr.comment · github.pr.merged · github.pr.closed.

Agents

Body: name, prompt, model, runtime? (claude|codex), key?, credential?, limits?. PATCH takes the same minus runtime (fixed at create). runtime/model provider must agree (claudeanthropic/…, codexopenai/…). credential: a cred_… id (BYO, provider-matched) or "managed" (via OpenComputer, billed to credits) — mutually exclusive with key. Create, get, and list responses include the permanent computed invoke_url (SDK invokeUrl). It has no trailing slash; join / or /hooks/<token> with URL semantics. See Agent URLs and Hooks. POST /agents is idempotent by name: fresh → 201, matching config → 200, differing → 409. Editing prompt/model (here or via deploy) creates a revision; the agent keeps a pointer to its active revision (GET /agents/:idactive_revision) and sessions pin it. The agent row holds only identity + bindings. POST /agents/import is the reviewed repository-import command described below. It deliberately creates an agent with no active revision; revision #1 appears only after the queued build and live deployment verify successfully.

Repository access

Repository access is available for every runtime and is separate from the repository used to deploy an agent. selected bounds session sources, checkout, and pull-request publishing for all runtimes; all preserves the open behavior.
TypeScript SDK
REST API
The wire response is:
Use { "mode": "all" } for every repository in the current and future App grant. An empty selected list disables repository work but not chat. When the grant is not_installed, effective_repositories is the known-empty []. Only a transient unavailable grant uses null, because no complete set was read. In selected mode, the owner-bound OpenComputer App is the only repository authority.

Deployments and revisions

You deploy an agent’s behavior. A deployment is a time-aware attempt; only a successful attempt produces an immutable revision. Failed attempts and their logs remain in deployment history. See the Deployments & revisions guide.

Review and import a repository agent

Review resolves the moving production branch to one exact commit and interprets bounded metadata without executing repository code. Repository-first import accepts exact flue-app-v1 and flue-prompt-v1 results. GET /github/deploy-app returns the installed OpenComputer GitHub App and its pickable repositories. Each repository includes linked_sources[] with the owner-scoped path, production_ref, status, and owning agent { id, name }. Clients should block review when the selected normalized root has a claim. This is an early user-facing check; import repeats the uniqueness check transactionally.
The response always includes repository identity, normalized root, production_ref, exact sha, review_fingerprint, and one interpretation:
Exact Flue review
interpretation.disposition is exact, invalid, or unrecognized. Invalid and unrecognized are successful review responses, not service failures: invalid includes bounded issues; an unrecognized root can include up to 20 candidate_roots and explicitly reports truncation. Only exact includes a deployable profile and may proceed to import. No response contains a repository token or source bytes. For flue-prompt-v1, profile keeps the same manifest, source, and builder projection and additionally returns prompt: { bytes }, skills: { count, bytes, names }, and builder.synthesis_template. The profile accepts agent.toml, prompt.md, and optional skills/*/SKILL.md; the server synthesizes the complete Flue app during the managed build. The non-exact variants keep the common repository/root/SHA/fingerprint fields shown above and use these shapes:
Invalid or unrecognized interpretation
An unrecognized interpretation has source_profile: null, source_profile_version: null, and reason_code: "unrecognized_source". Its optional candidate entries are { path, source_profile: "flue-app-v1" | "flue-prompt-v1" | null, summary, marker }; selecting one always performs a new review. candidate_roots_truncated means more matches existed than the bounded response could return, so ask the user to choose a narrower root rather than selecting one automatically. Import sends the same source coordinates, a human-readable agent name, and the exact review receipt. The name is independent of the Flue entrypoint in agent.toml.
The server reauthorizes the repository and re-derives the reviewed plan, then creates { agent, source, deployment } atomically. If the branch head or relevant source changed, it returns 409 source_changed_re_review and creates nothing. Reusing the same idempotency key and command returns the same import; reusing it with different fields returns 409 idempotency_conflict. A name or repository-root conflict also returns 409 and identifies the existing agent when available. The source remains linked after import. Its source_profile, source_profile_version, and review_fingerprint describe the reviewed source identity. A later GitHub push that touches the selected production root automatically creates the next deployment. A flue-prompt-v1 source may graduate to flue-app-v1. Any other profile change sets the link status to source_profile_changed; no build starts and the current active revision remains unchanged.

Deploy

input: { type:"inline", prompt, model?, skills?, runtime? } (the complete built-in behavior — omitted skills = none) or { type:"github", ref?, sha? } (deploys an already-linked repository; repo/path come from the server-owned link). The CLI’s local prompt-defined Flue path uses a separately uploaded, digest-bound source reference; use oc agent deploy rather than constructing that transport manually. activate:false stages an inline built-in deployment. Built-in GitHub links remain branch-driven. A new Flue repository agent instead starts with POST /agents/import; import deploys the reviewed production head, and subsequent production-branch pushes deploy automatically. Flue has no preview/staged Worker. POST …/revisions is inline-only sugar. Deployment List returns { data, next_cursor }. Log reads return { data: [{ seq, cursor, recorded_at, phase, stream, chunk }], next_cursor, has_more }; treat seq and both cursors as opaque strings. Continue with after=next_cursor until has_more is false, then poll again while the deployment is nonterminal. Source archives, bundles, credentials, raw provider responses, and operator telemetry are never projected through these APIs.

Revisions, rollback & promote

Revisions are linear (numbered, immutable). :rev is a number or rev_… id. Activate moves the active pointer instantly (no rebuild); rollback (earlier) and promote (a staged one) are the same call. Revision

Skills

A skill is a folder with a SKILL.md; PUT/DELETE are deployments (versioned, rollback-able). Limits: 64 files, 256 KiB total, UTF-8, modes 0644/0755. Full guide: Skills.

Deploy from a repo

Linking deploys the current production HEAD immediately (unless deploy_now: false / --no-deploy). The link is unique by owner, repository, and normalized root. Unlinking stops deploy-on-push but does not delete the agent, revisions, deployment history, or sessions. For built-in runtimes, a push to the production branch activates while other branches stage. For Flue, only the production branch deploys. Scopes: deploy_now: false needs agents:link; the default (with an initial deploy) needs agents:link + agents:deploy, plus agents:activate when that deploy auto-activates. Repo/path are server-anchored to the link. Deployment sources use the OpenComputer App (no BYO). Full flow + guarantees: Deploy from a repo. DeploymentSource

Schedules

Run an agent on a cron — each firing starts a session. Managed with the SDK, the oc CLI, or REST (org key). Full guide: Schedules.
cron is a 5-field expression (1-minute floor); tz is an IANA name (UTC if omitted); input (≤ 32 KiB) is the first message of every run; overlap is skip (default) or allow. Schedules are also synced from agent.toml on deploy — a repo-driven agent rejects edits other than pause/resume (409). Max 20 per agent. Schedule Run — one per firing decision, newest-first: srn_… with outcome (enacted · skipped · failed), scheduled_for? (null for a manual fire), fired_at, session_id? (when enacted), error?. Chain session_id into GET /sessions/:id.

Slack

Managed Slack uses the OpenComputer-operated app. Starting authorization returns a browser-safe Slack OAuth URL, or the current active connection when the agent is already connected. The optional deployment id is validated return context, not a redirect URL. Status responses never contain credentials.
The managed status is active, disconnected, error, or revoked. An active response includes workspace, app, open_url, and connected_at; error states expose only a stable error_code. The connection list returns { data }; each item has the same public status shape plus agent: { id, name }. It contains no Slack token, signing secret, or credential reference. Treat it as a preflight convenience: authorization still enforces the one-workspace-to-one-agent claim transactionally. Builder-owned Slack apps remain a separate resource and can overlap during an explicit handoff: See Slack for installation, trust boundaries, and conversation behavior.

Destinations

Webhooks are configured via SDK/REST (no oc command).
Destination body: url, secret?, level? (user), types?[], include_raw? (false, SDK: includeRaw), enabled? (true). types accepts exact types or prefix.*.

Deliveries

Delivery records are read via SDK/REST (no oc command).
See Webhooks for signing, retries, dedupe. Destination Delivery

GitHub Apps and Repos

A GitHub App lets OpenComputer mint short-lived, repo-scoped tokens; a Repo is a stable handle resolving to your configured App (the OpenComputer App by default). Used for session sources (work repos) and deploy-from-a-repo (the agent’s definition repo). Install the OpenComputer App. In selected repository-access mode, every runtime uses the owner-bound OpenComputer App. In all mode, configured bring-your-own Apps may continue to back built-in-runtime session sources and PR publishing. Hosted Flue repository tools and deployment sources always use the owner-bound OpenComputer App.
Repo body: owner, repo, provider? (github), name?no auth (resolves via your App); idempotent by (provider, owner, repo). Registering is optional under the OpenComputer App (reference "owner/repo" directly). Responses never carry a token/secret; App responses have id, mode, status, github_app_id?, app_name?, is_default?. Guide.

Credentials

Credential body: provider (anthropic | openai), key, name?, is_default?. Keys are write-only. A BYO credential is optional — agents can run Managed (credential: "managed", the default). See Credentials.

Errors & rate limits

One envelope: { "error": { "type", "message" } }; the SDK throws typed OpenComputerError subclasses (AuthError, NotFoundError, ConflictError, ValidationError, RateLimitError); the CLI exits non-zero and prints the message (the JSON with --json). Cross-owner resources return 404 (not 403). Rate/concurrency limits aren’t enforced at launch (a 429 with Retry-After may come later; the SDK retries it).