Agent SDK
Build local or remote Agents with project files, sandboxed commands, plugins, and persistent Sessions
Agent SDK
@downcity/agent provides a local Agent and a remote RemoteAgent. Both are session-first: Agent composes capabilities, while Session owns a continuous conversation and its execution state.
One-minute mental model
| Object | Owns | Does not own |
|---|---|---|
Workspace | Project files, env, Store, Tools, Shell, and Sandbox | Models, plugins, Session orchestration |
Agent | Model, instructions, final Tools, plugins, and Sessions | HTTP/RPC transports |
Session | Conversation state, message history, execution order, and approvals | Project resource ownership |
PluginContext | Stable Agent capabilities projected to a Plugin | A second Agent facade |
SessionTurnContext | Execution context and lifecycle for one Turn | Long-lived Agent state |
RemoteAgent | Access to a server-side Agent and its Sessions | Server-side model configuration |
Choose local or remote
| Scenario | Use |
|---|---|
| Agent and application run in the same Node.js process | Agent |
| The application injects models, Tools, plugins, and Shell directly | Agent |
| Another process already exposes the Agent over HTTP/RPC | RemoteAgent |
| The client only creates Sessions, sends prompts, and subscribes | RemoteAgent |
Network serving does not belong to Agent. Use AgentHTTP or AgentRPC from @downcity/server to expose a local Agent.
Recommended local composition
Shell is the standard entry for project commands and processes. The SDK does not select a platform Sandbox automatically; install and inject the Adapter for the current operating system. This example uses macOS:
import { Agent, Workspace } from "@downcity/agent";
import { MacOsSeatbeltSandbox } from "@downcity/sandbox-macos";
import { Shell } from "@downcity/shell";
const shell = new Shell({
sandbox: new MacOsSeatbeltSandbox(),
});
const workspace = new Workspace({
path: process.cwd(),
shell,
});
const agent = new Agent({
id: "repo-helper",
workspace,
model,
});
try {
const session = await agent.sessions.create();
const turn = await session.prompt({ query: "Summarize this repository" });
const result = await turn.finished;
console.log(result.text);
} finally {
await agent.dispose();
}Remember this primary path:
Workspace + Shell → Agent → Session → prompt() → turn.finished → dispose()agent.dispose() releases the Agent and its exclusive Workspace, including plugin lifecycle, ActionSchedule, Shell processes, PTYs, and Sandbox resources. Do not dispose the same Workspace again in the normal flow.
Model ownership
In pure SDK embedding, the host owns model instances:
- Set the default with
new Agent({ model }). - Or override it for one local Session with
await session.set({ model }).
In a Downcity project, the CLI host resolves the model from project configuration and the City AIService catalog. Remote Sessions do not expose client-side model configuration; the server host always owns the model.