Give an agent a workspace. Get back validated results.
Quick start • Why Runcell • Docs • Examples • Development
Runcell is an open-source TypeScript runtime for agents that work with files and tools. Choose a catalog model or register a provider, then run it in a workspace. A run can return:
- changed files as bytes;
- schema-validated data, with invalid results repaired or rejected;
- streamed text through
agent.stream(); - token usage and estimated cost for the run (
result.usage); - threads and sandbox snapshots that you can store as JSON.
import { createAgent, createThread } from 'runcell';
const agent = createAgent({ model: 'anthropic/claude-sonnet-4-5' });
const thread = createThread();
// A chat turn: stream the reply, keep the memory.
const { textStream, result } = agent.stream({
prompt: 'Read feedback.txt and summarize the top complaints.',
files: [{ path: 'feedback.txt', text: feedback }],
thread,
});
for await (const delta of textStream) process.stdout.write(delta);
await result;
await db.save(thread.id, thread.toJSON()); // the whole conversation, as JSONNote
Runcell 1.x is stable and follows Semantic Versioning. The examples in this repository run end-to-end with local credentials.
Runcell exposes three primitives:
- An agent is a stateless callable.
- A sandbox is the agent's workspace.
- A thread stores conversation state.
Agents read, write, and run commands through the sandbox. The bundled virtual sandbox works without additional setup. Vercel Sandbox, containers, and custom providers can supply an OS security boundary when the workload requires one.
Pass any Standard Schema validator, including Zod, Valibot, or ArkType. Runcell validates the submitted value and attempts repair turns when validation fails. If repair fails, the run rejects instead of returning the invalid value.
Threads and portable filesystem snapshots serialize to JSON. The application chooses where to store them and can resume them on another machine or sandbox provider.
The built-in model catalog includes Anthropic, OpenAI, Google, and other providers. Extensions can register additional providers before Runcell resolves the configured model. Lifecycle callbacks report run activity, and extension hooks can block tool calls.
Successful runs expose result.usage; getRunUsage(error) safely discovers
usage on measurable failures after a session starts. Both report per-run token
counts and the estimated cost in US dollars at API list price, sourced from the
models.dev-derived catalog. Runs on subscription
credentials report the same as-if-API price, so agent costs stay observable
regardless of how you authenticate.
For local and personal projects, credentials: 'local' runs agents on the AI
subscriptions you already pay for — Claude Pro/Max, ChatGPT Plus/Pro, or
GitHub Copilot — via a one-time npx pi /login. Provider terms govern this
use and differ per provider; API keys are the provider-supported path for
commercial and deployed work, and Runcell refuses local credentials in
production unless explicitly enabled.
Runcell does not include a database or workflow engine. The application owns persistence, concurrency, and orchestration.
When a schema is present, result.data contains the validated value. Model
prose remains available for logs.
const result = await agent.run({
prompt: 'Triage this bug report.',
files: [{ path: 'report.txt', text: report }],
schema: z.object({
severity: z.enum(['low', 'medium', 'high', 'critical']),
recommendedFixes: z.array(z.string()),
}),
});
result.data.severity; // typed and validatedOmit the schema and the streamed text becomes the output, which suits chat replies.
npm install runcell # zod is optional and used for structured output
npx pi # optional: /login with your Claude/ChatGPT/Copilot
# subscription instead of setting an API keyimport { createAgent } from 'runcell';
// Local development: run on your subscription login (see npx pi above).
const dev = createAgent({
model: 'anthropic/claude-sonnet-4-5',
credentials: 'local',
});
// Production: credentials come from environment variables (default).
const agent = createAgent({ model: 'anthropic/claude-sonnet-4-5' });
const reply = await agent.run({ prompt: 'Say hello.' });
console.log(reply.text);Model ids can be provider-qualified when one id exists under several providers:
openai-codex/gpt-5.5.
For a chat UI, the run streams as the wire format assistant-ui
and AI SDK's useChat consume. The whole backend is one route handler:
export async function POST(req: Request) {
const { messages } = await req.json();
return agent.stream({ messages }).toUIMessageStreamResponse();
}- Chat agents with streamed replies, persisted conversation state, and an
optional workspace per conversation. Plug into assistant-ui or
useChatwith zero glue: see the integrations and the chat-agent guide. - File pipelines: seed files in, let the agent work, get changed files back as bytes.
- Typed extraction and triage: reviews, reports, classifications your code consumes as data, not prose.
- Multi-agent workspaces: share one sandbox handle between agents; they see each other's files.
- Resumable jobs: snapshot the workspace + serialize the thread, park them in your database, pick both up later on another machine.
// Ephemeral (default): fresh workspace per run, destroyed after.
await agent.run({ prompt });
// Caller-owned: persists across runs; yours to destroy.
const sandbox = await createVirtualSandbox();
await agent.run({ prompt: 'Scaffold the project.', sandbox });
await sandbox.exec('npm test');
await db.save(id, await sandbox.snapshot());
await sandbox.destroy();Modes: virtual (bundled, default) · host (externally-isolated CI/containers)
· vercel (cloud, optional @ai-sdk/sandbox-vercel peer, Node 22+) ·
custom (bring your own provider). Details in the
sandboxes guide.
Read the full documentation.
| Guide | |
|---|---|
| Getting started | Install, credentials, models, first runs |
| Building a chat agent | Streaming + threads + persistence, end to end |
| Sandboxes | Handles, ownership, snapshot/restore, modes |
| Threads | Conversation memory and persistence |
| Structured output | Schemas, repair turns, plain turns |
| Streaming | agent.stream() and SSE |
| Files, tools, and events | Workspace I/O, host tools, callbacks |
| Credentials | env, local, API keys, shared stores |
| Pi extensions | Custom providers, auth extensions, hooks |
| API reference | Every export and type |
The examples in examples/ are compile-checked and runnable; they
default to local credentials so they're easy to run on a configured machine.
| Command | Demonstrates |
|---|---|
npm run example:01 |
Minimal createAgent() + agent.run() |
npm run example:02 |
Structured output validation and incomplete-result handling |
npm run example:03 |
Passing files into the sandbox |
npm run example:04 |
Text, tool, file-change, repair, and finish events |
npm run example:05 |
Host-side custom tools |
npm run example:06 |
Credential modes |
npm run example:07 |
Minimal shared credential store |
npm run example:08 |
Structured output plus returned file validation |
npm run example:09 |
Chat agent: streaming, thread persistence, shared sandbox |
npm run example:10 |
Multi-phase runs sharing one sandbox and thread |
RUNCELL_EXAMPLE_CREDENTIALS=local npm run examples:runnpm install
npm run check # build, format, lint, typecheck, tests
RUNCELL_LIVE=1 RUNCELL_LIVE_CREDENTIALS=local npm run test:liveMonorepo layout: the public package lives in packages/agent/ (published as
runcell); examples/ are compile-checked against it.