Skip to main content
The ADE SDK is how a third-party app embeds ADE chat. Your process owns a slim ADE runtime as a child, talks to it over JSON-RPC, and presents chat as durable named threads. The runtime is a guest: isolated home, sync off, no machine-brain authority. It dies with your process. This is not ADE desktop or personal chats in the ADE app. Those stay first-party. Use the SDK when your product needs an agent chat sidecar.

Install

npm install @ade-dev/sdk — Node 22, then a 10-line client.

Quickstart

Open a thread, send a message, resume by key after a restart.

MCP servers

Inject your tools. Strict mode is enforced only on Claude — read the honesty table.

Chat UI

React components that render the conversation for your users.

API reference

Every export with its exact signature, generated from the declarations.

Packages

Both packages are MIT. The runtime binary and ADE itself are AGPL-3.0-only, and an embedding exception lets a proprietary app ship an unmodified runtime binary. See License for the per-artifact table and the exact conditions.

How it fits

The client downloads (or you pin) an ade binary, spawns ade runtime run --socket <path> --profile embedded, and exposes threads.open(key). Reopening the same key after a restart continues the conversation. doctor() reports the SDK version, the runtime version, the socket, and provider auth. SDK 0.7 uses isolated provider logins by default; set useMachineLogin: true to reuse the host machine’s Claude or Codex login. doctor() reports the active login mode. See Accounts.

What’s new in 0.7

SDK 0.7 keeps the runtime range at >=1.2.82 <2.0.0; new runtime actions are feature-detected. It adds provider accounts and sign-in, secret-safe API credentials and endpoint presets, provider capability reports, per-thread account/credential/preset selection, usage-limit handling, and queue/recovery controls.
  • BREAKING: login isolation is the default. Machine logins are no longer reused implicitly. Set useMachineLogin: true to preserve SDK 0.6 behavior, or sign the user in under the app’s isolated runtime.
  • Host-owned secrets. resolveSecret(provider, credentialId) sends a vault value only to the live runtime session; it is not written to the SDK thread store.
  • Usage limits. Pick wait, failover or ask and listen for usageLimit when the host needs to show a decision.

What’s new in 0.6

SDK 0.6.0 supported runtime >=1.2.82 <2.0.0, the same range as 0.5. On an older runtime, tool filters are refused before they are sent (they need capabilities.personalChats.mcpToolFilters), and a mid-turn updateMcpServers is refused with turn_in_flight instead of queued. The header refresh needs nothing new.
  • Tokens that expire during a chat. mcpHeaders may be async, and it runs before every send, retry and editLast: a changed token is pushed before the turn, and thread.refreshMcpHeaders() pushes one on demand. See Tokens that expire during a chat.
  • Per-server tool filters. allowedTools / disallowedTools on an MCP server choose which of its tools reach the model. A filter the provider cannot enforce is refused, never dropped. See Filtering a server’s tools.
  • updateMcpServers during a turn. The runtime queues the servers for the turn’s end instead of refusing, and the session summary reports mcpServersPending: true until the swap.

What’s new in 0.5

SDK 0.5.1 supports runtime >=1.2.82 <2.0.0. The lower bound did not move across 0.5: nothing in that line needs a new wire, so a host on runtime 1.2.82 keeps working. Patch 0.5.1 carries one tidy that landed on main after 0.5.0 published: the buffered-event category list no longer names cto_voice, a category an agent-role sidecar never receives. See Version compatibility.
  • Attachment roots that fail the whole open. checkAttachmentRoot(path, home) and filterAttachmentRoots(list, home) test a root before you send it, so one bad entry no longer locks every chat. An identical list is not sent again. See Where a path may point.
  • A host hook for removals. registerAdeIpc({ onThreadRemoved }) fires for every delete and archive the served client reports, whoever made it, so your chat list stays exact. It follows a client swapped per account as soon as the bridge serves a call. See Electron.
  • A cost preference for new chats. models.defaultModel({ prefer }) and pickDefaultModel(models, { prefer }) rank a provider’s models yourself, so a host can start on Sonnet instead of the provider’s most expensive default. See pickDefaultModel.
  • Less noise from an embedded runtime. Four lines an embedded runtime printed on every start — the role-ceiling sentence, its brain.role_ceiling_below_cto warning, and the two “could not bound runtime log” lines — are gone from runtime 1.2.83. An older runtime still prints them.
  • Docs. ModelCatalogEntry.provider now points at isSupportedProvider; the retry and edit docs say the rollback does not cover the disk and how to find the files yourself; the activity-label docs now state that a bare MCP key is compared with the tool’s own name, with an example.

What’s new in 0.4

@ade-dev/sdk 0.4.0, @ade-dev/chat-ui 0.4.0 and runtime 1.2.82 are available together. SDK 0.4.0 supports runtime >=1.2.82 <2.0.0. An older runtime still connects, and the features below that need 1.2.82 throw unsupported or do nothing. See Version compatibility.
  • Retry and edit. thread.retry() and thread.editLast(text) run the last user message again, and the transcript shows it once. Claude and Codex. See Retry and edit.
  • Links. onLinkClick on <AdeChat>, <Transcript>, <ProviderCard> and <ProviderCards>, so a host decides what opens and where. In Electron, pass it. See Links.
  • Attachment roots. attachmentRoots lets a thread attach files from folders outside its cwd without a copy. The attachments guide now says how paths compare. See Where a path may point.
  • Bridge. openOptions gets { exists, summary }, so a host can tell a resume from a create. allowThreadKey and allowModel can be async. thread.send options are filtered. threads.get, forget(key), and checkAdeBridge for a hand-copied preload. See Electron.
  • Client. threads.get(key), models.onChange, models.defaultModel, pickDefaultModel, the threadLifecycle event, and final on restart. See Reference.
  • Chat UI. Controlled draft, onSend, a render prop and threadRef on <AdeChat>; ThreadState.update, retry and editLast; a reload after a runtime restart or a retry. See Chat UI.
  • Runtime. Codex no longer shows a computer_use tool call that never ends, and the Computer Use server is not started for a thread whose policy does not allow it. update({ title: null }) clears the title. --version reports the runtime’s own version. No canUseTool warning on every Claude turn. The doctor().runtime.version probe of the SDK also works on a 1.2.81 binary started from inside ADE.

Breaking changes

  • Refusals caused by a running turn (setModel, a reasoning update) now throw turn_in_flight, not invalid_option. Branch on turn_in_flight.
  • window.ade from @ade-dev/sdk/electron/global is optional. createAdeIpcClient(window.ade) still compiles; code that reads window.ade.invoke directly needs a check.
  • The restart event payload has a new final field, and ADE_CLIENT_EVENTS has threadLifecycle. A listener table typed on the old list must add it.

What’s new in 0.3

@ade-dev/sdk 0.3.0 and @ade-dev/chat-ui 0.3.0 release together. SDK 0.3.0 supports runtime >=1.2.81 <2.0.0. See Version compatibility.
  • Thread lifecycle. threads.delete, threads.archive, threads.unarchive, and thread.update() for a rename, reasoning effort or fast mode. ThreadSummary and the thread carry title, the resolved model with its display name, and updatedAt. See Threads.
  • Attachments. type ("file" or "image", inferred when absent), so images reach the model as images. hydrate: false sends the path only. steer() takes attachments. See Attachments.
  • Paged history. thread.historyPage(). See History.
  • Credentials that change. MCP header values are no longer stored. refresh.mcpServers, thread.updateMcpServers() and the mcpHeaders callback supply current tokens. See MCP servers.
  • Codex MCP approvals. The permission policy now judges Codex MCP tool calls, and approve() answers them. approvalTimeoutMs lets the SDK decline an approval that nobody answers. See Permissions.
  • Runtime exits. client.on("exit" | "transport" | "restart"), a synthetic error status on each live thread, and opt-in autoRestart. See Runtime.
  • Electron bridge. The renderer no longer configures threads: an openOptions hook in main decides, or only four fields cross. allowModel, threads.list and the lifecycle calls over IPC, a client getter, @ade-dev/sdk/electron/global, and a copy-paste sandboxed preload. See Electron.
  • Packaging. resolvePackagedRuntime() and doctor().runtime.source: "packaged". See Bundling.
  • Chat UI. Composer rail slots and controlled attachments on <AdeChat>, a windowed transcript, tool identity and tool-result slots. See Chat UI.

Breaking changes

  • The Electron bridge drops every renderer threads.open option except provider, model, title and reasoningEffort, unless you set openOptions. See What a renderer may send.
  • When the runtime lost a session, the recreate uses the stored record first, not the call’s options. See Threads.
  • setModel() returns displayName and capabilities beside modelId, provider and model. A test that compares the whole result with toEqual must change.
thread.retry() and thread.editLast() are not in 0.3. They are in 0.4.

What this is not

  • Not a hosted ADE cloud API. The sidecar runs on the same machine as your app.
  • Not ADE desktop IPC. The SDK speaks the machine JSON-RPC surface.
  • Not a way to drive lanes, PRs, or the Work tab from a third-party renderer.

Next

Install

Node 22, npm, Electron main, pinning a binary.

Threads

Send, steer, interrupt, switch models, export.