Local Agent Quickstart
Create a local Agent with a model, Shell, platform Sandbox, and its first Session execution
Local Agent Quickstart
Use this path to embed an Agent directly in a Node.js application. A complete local Agent combines a Workspace, Shell, platform Sandbox, model, and Session.
Install
This example uses macOS:
pnpm add @downcity/agent @downcity/shell @downcity/sandbox-macos @ai-sdk/openaiOn another platform, replace only the Sandbox package and instance:
| Platform | Package | Adapter |
|---|---|---|
| macOS | @downcity/sandbox-macos | MacOsSeatbeltSandbox |
| Linux | @downcity/sandbox-linux | LinuxBubblewrapSandbox |
| Windows | @downcity/sandbox-windows-mxc | WindowsMxcSandbox |
Complete minimal example
import { Agent, Workspace } from "@downcity/agent";
import { createOpenAI } from "@ai-sdk/openai";
import { MacOsSeatbeltSandbox } from "@downcity/sandbox-macos";
import { Shell } from "@downcity/shell";
const openai = createOpenAI({
apiKey: process.env.OPENAI_API_KEY!,
});
const shell = new Shell({
sandbox: new MacOsSeatbeltSandbox(),
});
const workspace = new Workspace({
path: "/path/to/project",
shell,
});
const agent = new Agent({
id: "repo-helper",
workspace,
model: openai.responses("gpt-5"),
});
try {
const session = await agent.sessions.create();
const turn = await session.prompt({
query: "Summarize the current repository structure",
});
const result = await turn.finished;
console.log(result.text);
} finally {
await agent.dispose();
}Six key steps
- Create the Sandbox Adapter for the current platform.
- Create
Shelland inject the Sandbox. - Create
Workspaceand pass it the Shell. - Create
Agentwith the Workspace and model. - Create a Session, start a Turn with
prompt(), and awaitturn.finished. - Call
agent.dispose()infinally.
Shell matters: without it, Workspace still provides file and search Tools, but Agent has no shell_exec or shell_session and cannot run project commands or manage long-lived processes. The SDK does not choose a Sandbox automatically or silently fall back to unrestricted execution when an Adapter is missing.
Objects and lifecycle
Workspace + Shell → Agent → Session → Turn
└──────────────→ agent.dispose()- One Workspace instance can bind to only one Agent.
- Multiple Workspace instances may point to the same physical directory for different Agents.
- Plugin lifecycle and ActionSchedule begin starting immediately after
new Agent(...). - Session entry points wait for the Agent runtime; call
await agent.ready()only when you need an explicit startup checkpoint. agent.dispose()also releases the exclusive Workspace, Shell processes, PTYs, and Sandbox. Do not callworkspace.dispose()again.- HTTP/RPC transports do not belong to Agent; use
@downcity/serverwhen you need network serving.
Model resolution
Local execution resolves the model in this order:
- A Session model set with
await session.set({ model }). - The default
modelpassed to Agent.
If neither exists, the Session cannot execute. A pure SDK host owns model instances directly; in a Downcity project, the CLI host resolves the model from project configuration and the City AIService catalog.