Programmable Agent API

Drive Standard Code from your own code.

Standard Code sessions are durable, addressable threads on your instance. The CLI's control plane is available over HTTP and WebSockets. Create a thread, send it work, and watch the response in real time from any language.

Base URL https://api.standardcode.ai

Overview

The Programmable Agent API exposes the same primitives the Standard Code CLI is built on. It is a small, predictable REST surface plus one WebSocket for live updates:

  • Threads: conversations with an agent that have durable history and state. Create, list, read, and delete them.
  • Messages: work sent into a thread and every response the agent produces.
  • Streaming: live assistant text, tool activity, and end-of-turn signals delivered over a WebSocket.
  • Thread state: a durable per-thread key/value store you can read and write.

Everything is JSON over HTTPS. Standard fetch and WebSocket calls provide the full API without an SDK.

Authentication

Every request is authenticated with your Standard Code API key as a bearer token:

Authorization: Bearer sak_live_…

The fastest way to get a key is to sign in once with the CLI. On first run it opens your browser, and on approval it mints a personal key for your instance and stores it locally:

# installs the CLI and signs you in via the browser
npm install -g @standardagents/code
standardcode ~/some-project   # press Enter for browser sign-in

Your key is then written to ~/.standardagents/credentials under this instance's endpoint (the token field). Treat it like a password because it carries the same access as your session.

Scope. A key only sees your threads. It can create threads, send messages, stream them, and read their messages and state. Raw model request and response logs remain private to instance admins.

Quickstart

Use three calls to create a thread, send it a task, and read the reply:

# 1. Create a thread
curl -s https://api.standardcode.ai/api/threads \
  -H "Authorization: Bearer $STANDARDCODE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"agent_id":"standard_code_agent","tags":["api"]}'
# → {"threadId":"thr_abc123","agent_id":"standard_code_agent", ...}

# 2. Send a message to start the agent
curl -s https://api.standardcode.ai/api/threads/thr_abc123/messages \
  -H "Authorization: Bearer $STANDARDCODE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"role":"user","content":"Summarize what a durable object is in two sentences."}'

# 3. Read the conversation
curl -s "https://api.standardcode.ai/api/threads/thr_abc123/messages?limit=20" \
  -H "Authorization: Bearer $STANDARDCODE_KEY"

For live output, open the streaming WebSocket right after step 1 to watch the reply arrive as it is generated.

API reference

All paths are relative to https://api.standardcode.ai. Request and response bodies are JSON.

Threads

A thread is one conversation with an agent. It holds message history and durable state, and it can be resumed at any time from any machine.

Create a thread

POST/api/threads
FieldTypeDescription
agent_idrequiredstringThe agent to run. Use standard_code_agent for the Standard Code coding agent.
tagsstring[]Labels for later filtering (e.g. group threads by project or job id).
initial_messagesobject[]Optional seed messages ({ role, content }). Omit to start empty and send the first message separately.
// response
{ "threadId": "thr_abc123", "agent_id": "standard_code_agent" }

List your threads

GET/api/threads
QueryTypeDescription
agent_idstringOnly threads for this agent.
limitnumberPage size (default 50).
offsetnumberPagination offset.
searchstringMatch against thread titles / previews.

Returns { "threads": [ { id, agent_id, title, tags, created_at, … } ] }, scoped to threads your key owns.

Get, update, or delete a thread

GET/api/threads/:id
PATCH/api/threads/:id
DELETE/api/threads/:id

GET returns thread metadata. PATCH updates fields such as title or thread env (env_patch). DELETE removes the thread and its history.

Messages

Send a message

POST/api/threads/:id/messages

Sending a user message starts the agent's turn. The call returns as soon as the message is queued. The agent works asynchronously, and you can read the result by listing messages or using the stream.

FieldTypeDescription
contentrequiredstringThe message text.
rolerequiredstringuser, assistant, or system. Use user to give the agent work.
attachmentsobject[]Files as { name, mimeType, data } where data is base64. Images become vision context.
silentbooleanStore the message without showing it to the model.
{ "role": "user", "content": "Add a health check endpoint and a test for it." }

List messages

GET/api/threads/:id/messages
QueryTypeDescription
limitnumberPage size (default 100).
offsetnumberPagination offset.
orderstringasc or desc.
includeSilentbooleanInclude silent messages.

Returns { "messages": [ { id, role, content, created_at, … } ] }. A queued message the agent hasn't processed yet is included with metadata.queued: true. An assistant message whose turn is finished has visible content and no pending tool calls.

Streaming (WebSocket)

WS/api/threads/:id/stream

Open a WebSocket to a thread to receive its output live. Because browsers and WebSocket clients can't set an Authorization header on the handshake, pass your key as the token query parameter:

wss://api.standardcode.ai/api/threads/thr_abc123/stream?token=$STANDARDCODE_KEY

Add &reasoning=1 to also receive the model's internal reasoning stream. The socket emits newline-free JSON text frames:

typePayloadMeaning
message_chunk{ chunk, message_id }A fragment of the assistant's visible answer, as it's generated.
reasoning_chunk{ chunk, message_id }A fragment of internal reasoning (only when you pass reasoning=1).
message_data{ data: { role, content, status, … } }A complete message. An assistant message with text and no tool calls marks the end of a turn.
event{ eventType, data }Lifecycle events like tool_call_started, tool_call_done, and generation.
Keep-alive. Send the plain text frame stream_ping periodically; the server replies stream_pong through its hibernation-safe auto-response path. Reconnect when no frame arrives within your silence window. Durable history preserves the output across socket connections.

Thread state (KV)

Each thread has a durable key/value store. Use it to attach JSON-serializable metadata such as a job ID or status that resumes with the thread.

GET/api/threads/:id/kv?key=NAME
POST/api/threads/:id/kv
DELETE/api/threads/:id/kv?key=NAME

GET with no key browses all entries (supports search, limit, offset). POST writes { key, value }. DELETE removes a key.

Stopping a run

POST/api/threads/:id/stop

Interrupts the agent's current turn. The thread stays intact and can be continued by sending another message.

Full example

This plain Node example creates a thread, streams it live, and prints the answer without dependencies:

const BASE = "https://api.standardcode.ai";
const KEY = process.env.STANDARDCODE_KEY;
const auth = { "Authorization": `Bearer ${KEY}`, "Content-Type": "application/json" };

// 1. Create a thread
const { threadId } = await fetch(`${BASE}/api/threads`, {
  method: "POST", headers: auth,
  body: JSON.stringify({ agent_id: "standard_code_agent", tags: ["api"] }),
}).then(r => r.json());

// 2. Open the live stream
const ws = new WebSocket(`${BASE.replace("https","wss")}/api/threads/${threadId}/stream?token=${KEY}`);
ws.onmessage = (e) => {
  const f = JSON.parse(e.data);
  if (f.type === "message_chunk") process.stdout.write(f.chunk);
  if (f.type === "message_data" && f.data?.role === "assistant" && !f.data.tool_calls) ws.close();
};

// 3. Give it work
await fetch(`${BASE}/api/threads/${threadId}/messages`, {
  method: "POST", headers: auth,
  body: JSON.stringify({ role: "user", content: "Explain what this API does in one paragraph." }),
});

Limits & notes

  • Ownership. A key only accesses threads it created. There is no cross-tenant access.
  • Sessions are the unit. A thread actively working counts as one session against your plan, exactly like the CLI. Idle threads cost nothing; subagents are free.
  • Host tools need the bridge. Tools that act on your machine (reading files, running commands) execute through the CLI's secure bridge. The API supports reasoning, planning, subagent orchestration, and answers. Connect the CLI to give the agent filesystem access.
  • Logs are private. Instance admins retain exclusive access to raw model request and response logs. On a self-hosted enterprise license your organization is the instance admin, with full access to its own logs. See Standard Code for enterprise.

Write to enterprise@standardagents.ai with questions or requests for the API.