---
title: "TypeScript"
description: "Use the TypeScript SDK to manage ACP sessions and Sandbox Agent HTTP APIs."
icon: "js"
---

The TypeScript SDK is centered on `sandbox-agent` and its `SandboxAgentClient`, which provides a Sandbox-facing API for session flows, ACP extensions, and binary HTTP filesystem helpers.

## Install

<Tabs>
  <Tab title="npm">
    ```bash
    npm install sandbox-agent
    ```
  </Tab>
  <Tab title="bun">
    ```bash
    bun add sandbox-agent
    # Allow Bun to run postinstall scripts for native binaries (required for SandboxAgent.start()).
    bun pm trust @sandbox-agent/cli-linux-x64 @sandbox-agent/cli-linux-arm64 @sandbox-agent/cli-darwin-arm64 @sandbox-agent/cli-darwin-x64 @sandbox-agent/cli-win32-x64
    ```
  </Tab>
</Tabs>

## Create a client

```ts
import { SandboxAgentClient } from "sandbox-agent";

const client = new SandboxAgentClient({
  baseUrl: "http://127.0.0.1:2468",
  token: process.env.SANDBOX_TOKEN,
  agent: "mock",
});
```

`SandboxAgentClient` is the canonical API. By default it auto-connects (`autoConnect: true`), so provide `agent` in the constructor. Use the instance method `client.connect()` only when you explicitly set `autoConnect: false`.

## Autospawn (Node only)

If you run locally, the SDK can launch the server for you.

```ts
import { SandboxAgent } from "sandbox-agent";

const client = await SandboxAgent.start({
  agent: "mock",
});

await client.dispose();
```

Autospawn uses the local `sandbox-agent` binary. Install `@sandbox-agent/cli` (recommended) or set
`SANDBOX_AGENT_BIN` to a custom path.

## Connect lifecycle

Use manual mode when you want explicit ACP session lifecycle control.

```ts
import {
  AlreadyConnectedError,
  NotConnectedError,
  SandboxAgentClient,
} from "sandbox-agent";

const client = new SandboxAgentClient({
  baseUrl: "http://127.0.0.1:2468",
  token: process.env.SANDBOX_TOKEN,
  agent: "mock",
  autoConnect: false,
});

await client.connect();

try {
  await client.connect();
} catch (error) {
  if (error instanceof AlreadyConnectedError) {
    console.error("already connected");
  }
}

await client.disconnect();

try {
  await client.prompt({ sessionId: "s", prompt: [{ type: "text", text: "hi" }] });
} catch (error) {
  if (error instanceof NotConnectedError) {
    console.error("connect first");
  }
}
```

## Session flow

```ts
const session = await client.newSession({
  cwd: "/",
  mcpServers: [],
  metadata: {
    agent: "mock",
    title: "Demo Session",
    variant: "high",
    permissionMode: "ask",
  },
});

const result = await client.prompt({
  sessionId: session.sessionId,
  prompt: [{ type: "text", text: "Summarize this repository." }],
});

console.log(result.stopReason);
```

Load, cancel, and runtime settings use ACP-aligned method names:

```ts
await client.loadSession({ sessionId: session.sessionId, cwd: "/", mcpServers: [] });
await client.cancel({ sessionId: session.sessionId });
await client.setSessionMode({ sessionId: session.sessionId, modeId: "default" });
await client.setSessionConfigOption({
  sessionId: session.sessionId,
  configId: "config-id-from-session",
  value: "config-value-id",
});
```

## Extension helpers

Sandbox extensions are exposed as first-class methods:

```ts
const models = await client.listModels({ sessionId: session.sessionId });
console.log(models.currentModelId, models.availableModels.length);

await client.setMetadata(session.sessionId, {
  title: "Renamed Session",
  model: "mock",
  permissionMode: "ask",
});

await client.detachSession(session.sessionId);
await client.terminateSession(session.sessionId);
```

## Event handling

Use `onEvent` to consume converted SDK events.

```ts
import { SandboxAgentClient, type AgentEvent } from "sandbox-agent";

const events: AgentEvent[] = [];

const client = new SandboxAgentClient({
  baseUrl: "http://127.0.0.1:2468",
  token: process.env.SANDBOX_TOKEN,
  agent: "mock",
  onEvent: (event) => {
    events.push(event);

    if (event.type === "sessionEnded") {
      console.log("ended", event.notification.params.sessionId ?? event.notification.params.session_id);
    }

    if (event.type === "agentUnparsed") {
      console.warn("unparsed", event.notification.params);
    }
  },
});
```

You can also handle raw session update notifications directly:

```ts
const client = new SandboxAgentClient({
  baseUrl: "http://127.0.0.1:2468",
  token: process.env.SANDBOX_TOKEN,
  agent: "mock",
  onSessionUpdate: (notification) => {
    console.log(notification.update.sessionUpdate);
  },
});
```

## Control + HTTP helpers

Agent/session and non-binary filesystem control helpers use ACP extension methods over `/v2/rpc`:

```ts
const health = await client.getHealth();
const agents = await client.listAgents();
await client.installAgent("codex", { reinstall: true });

const sessions = await client.listSessions();
const sessionInfo = await client.getSession(sessions.sessions[0].session_id);
```

These methods require an active ACP connection and throw `NotConnectedError` when disconnected.

Binary filesystem transfer intentionally remains HTTP:

- `readFsFile` -> `GET /v2/fs/file`
- `writeFsFile` -> `PUT /v2/fs/file`
- `uploadFsBatch` -> `POST /v2/fs/upload-batch`

Reason: these are Sandbox Agent host/runtime filesystem operations (not agent-specific ACP behavior), intentionally separate from ACP native `fs/read_text_file` / `fs/write_text_file`, and they may require streaming very large binary payloads that ACP JSON-RPC is not suited to transport efficiently.

ACP extension variants can exist in parallel for compatibility, but `SandboxAgentClient` should prefer the HTTP endpoints above by default.

## Error handling

All HTTP errors throw `SandboxAgentError`:

```ts
import { SandboxAgentError } from "sandbox-agent";

try {
  await client.listAgents();
} catch (error) {
  if (error instanceof SandboxAgentError) {
    console.error(error.status, error.problem);
  }
}
```

## Inspector URL

Build a URL to open the sandbox-agent Inspector UI with pre-filled connection settings:

```ts
import { buildInspectorUrl } from "sandbox-agent";

const url = buildInspectorUrl({
  baseUrl: "https://your-sandbox-agent.example.com",
  token: "optional-bearer-token",
  headers: { "X-Custom-Header": "value" },
});

console.log(url);
// https://your-sandbox-agent.example.com/ui/?token=...&headers=...
```

Parameters:
- `baseUrl` (required): The sandbox-agent server URL
- `token` (optional): Bearer token for authentication
- `headers` (optional): Extra headers to pass to the server (JSON-encoded in the URL)

## Types

The SDK exports typed events and responses for the Sandbox layer:

```ts
import type {
  AgentEvent,
  AgentInfo,
  HealthResponse,
  SessionInfo,
  SessionListResponse,
  SessionTerminateResponse,
} from "sandbox-agent";
```

For low-level protocol transport details, see [ACP HTTP Client](/advanced/acp-http-client).
