Skip to main content
TypeScript SDK for Devin. Cloud and local sessions both speak the Agent Client Protocol — cloud over a WebSocket, local by running the Devin CLI on your machine — with the generated v3 API client available as an escape hatch.

Install

The SDK is beta-only for now: every release is a 0.0.1-beta.N prerelease on the beta dist-tag, and no version is published to latest, so the @beta suffix is required — a plain npm i @cognition-ai/sdk fails on purpose until the public launch.

Usage

createDevin(options) connects to the cloud over a WebSocket (CloudDevin) unless you pass a cwd, which spawns the CLI on this machine (LocalDevin); TypeScript narrows the return type accordingly. Both need a cog_… API key, from the apiKey option or DEVIN_API_KEY (locally the SDK hands it to the CLI for you). Both implement the shared DevinClient interface, and their sessions share the same send() / stream() / cancel() surface, so the same code drives Devin on your machine or in a cloud VM:
Clients are async-disposable — await using closes the connection (and the CLI process for local clients) at scope exit; without it, call .close() when done.

The v3 API escape hatch

ACP covers live interaction; everything else — session snapshots, structured output, pull requests, and platform resources (playbooks, secrets, organizations) — lives on the v3 API. The cloud client exposes the full generated v3 client as api:

Local sessions (Devin CLI)

LocalDevin spawns the Devin CLI as a subprocess and drives it over the Agent Client Protocol on stdio. Turns run on your machine: tool calls edit real files and run real commands in cwd. The CLI is bundled with the SDK as per-platform npm packages listed as optionalDependencies, so the binary lives in node_modules and is versioned by your lockfile — there is no path override; the SDK only runs a bundled, officially published CLI build. Authentication is the apiKey option (a cog_… personal access token, defaulting to $DEVIN_API_KEY, the same key cloud mode uses); the SDK never falls back to the CLI’s own devin auth login credential store. The CLI’s config, session store, and cache live under ~/.devin-sdk (override with stateDir), isolated from any interactive Devin CLI install on the same machine.
Cognition-specific events (_cognition.ai/* notifications — agent stop causes, context compaction, connection retries, …) are surfaced as a typed union via session.onExtension:

Cloud sessions over ACP

CloudDevin drives sessions running in Devin’s cloud over the same ACP protocol as LocalDevin, connected over the ACP WebSocket and authenticated with a personal access token (cog_…). Turns, streaming, permission handling, and _cognition.ai/* extension notifications work identically to local sessions; the generated v3 client stays available as the api escape hatch.

Tool calls, the same on both agents

The local CLI and the cloud describe tools differently on the wire (typed rawInput and cognition.ai/inferenceToolName locally; cognition.ai/eventType plus _meta details such as cognition.ai/command and cognition.ai/fileUpdates on the cloud). ToolCall.detail normalizes both into one discriminated union — exec, read, write, edit, list_directory, file_search, mcp, permission_request, ask_user_question, report_blocker, or other — so consumers narrow on detail.tool and never see the difference. The raw rawInput, meta, toolName and inferenceToolName stay on the call for anything the union does not cover.

Watching sessions you did not start

Every session exposes two views of its updates. run(), stream() and streamUpdates() are scoped to a turn this client sent. events() and updates() are scoped to the session: every live update for it, whoever started the turn, until the connection closes. Both typed flavours use the same SessionEventReducer, so a SessionEvent means the same thing wherever it came from.
The cloud pushes status transitions live but replays only the latest one, so a client that was offline cannot reconstruct what it missed: seed from listSessions() (each entry’s _meta carries statusEnum, userActionRequired, pendingRequest, sessionPRs, …) and stay attached for transitions. session.meta holds the latest session snapshot stamped on any update. Observers should leave onPermission unset — an answer from an observer is a real decision, and the protocol has no “abstain”.

Regenerating the API client

src/generated/ is produced by Fern from the committed OpenAPI spec (spec/v3-openapi.json). After changing the spec, run from the repo root (requires Docker):

Classes

Interfaces

Type Aliases

Variables