Local Agent

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/openai

On another platform, replace only the Sandbox package and instance:

PlatformPackageAdapter
macOS@downcity/sandbox-macosMacOsSeatbeltSandbox
Linux@downcity/sandbox-linuxLinuxBubblewrapSandbox
Windows@downcity/sandbox-windows-mxcWindowsMxcSandbox

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

  1. Create the Sandbox Adapter for the current platform.
  2. Create Shell and inject the Sandbox.
  3. Create Workspace and pass it the Shell.
  4. Create Agent with the Workspace and model.
  5. Create a Session, start a Turn with prompt(), and await turn.finished.
  6. Call agent.dispose() in finally.

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 call workspace.dispose() again.
  • HTTP/RPC transports do not belong to Agent; use @downcity/server when you need network serving.

Model resolution

Local execution resolves the model in this order:

  1. A Session model set with await session.set({ model }).
  2. The default model passed 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.

Next steps