mirror of
https://github.com/harivansh-afk/sandbox-agent.git
synced 2026-04-15 04:03:31 +00:00
* SDK sandbox provisioning: built-in providers, docs restructure, and quickstart overhaul - Add built-in sandbox providers (local, docker, e2b, daytona, vercel, cloudflare) to the TypeScript SDK so users import directly instead of passing client instances - Restructure docs: rename architecture to orchestration-architecture, add new architecture page for server overview, improve getting started flow - Rewrite quickstart to be TypeScript-first with provider CodeGroup and custom provider accordion - Update all examples to use new provider APIs - Update persist drivers and foundry for new SDK surface Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix SDK typecheck errors and update persist drivers for insertEvent signature - Fix insertEvent call in client.ts to pass sessionId as first argument - Update Daytona provider create options to use Partial type (image has default) - Update StrictUniqueSessionPersistDriver in tests to match new insertEvent signature - Sync persist packages, openapi spec, and docs with upstream changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Add Modal and ComputeSDK built-in providers, update examples and docs - Add `sandbox-agent/modal` provider using Modal SDK with node:22-slim image - Add `sandbox-agent/computesdk` provider using ComputeSDK's unified sandbox API - Update Modal and ComputeSDK examples to use new SDK providers - Update Modal and ComputeSDK deploy docs with provider-based examples - Add Modal to quickstart CodeGroup and docs.json navigation - Add provider test entries for Modal and ComputeSDK - Remove old standalone example files (modal.ts, computesdk.ts) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Fix Modal provider: pre-install agents in image, fire-and-forget exec for server - Pre-install agents in Dockerfile commands so they are cached across creates - Use fire-and-forget exec (no wait) to keep server alive in Modal sandbox - Add memoryMiB option (default 2GB) to avoid OOM during agent install Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * Sync upstream changes: multiplayer docs, logos, openapi spec, foundry config Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * SDK: Add ensureServer() for automatic server recovery Add ensureServer() to SandboxProvider interface to handle cases where the sandbox-agent server stops or goes to sleep. The SDK now calls this method after 3 consecutive health-check failures, allowing providers to restart the server if needed. Most built-in providers (E2B, Daytona, Vercel, Modal, ComputeSDK) implement this. Docker and Cloudflare manage server lifecycle differently, and Local uses managed child processes. Also update docs for quickstart, architecture, multiplayer, and session persistence; mark persist-* packages as deprecated; and add ensureServer implementations to all applicable providers. Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com> * wip --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
415 lines
11 KiB
Text
415 lines
11 KiB
Text
---
|
|
title: "Quickstart"
|
|
description: "Get a coding agent running in a sandbox in under a minute."
|
|
icon: "rocket"
|
|
---
|
|
|
|
<Steps>
|
|
<Step title="Install">
|
|
<Tabs>
|
|
<Tab title="npm">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x
|
|
```
|
|
</Tab>
|
|
<Tab title="bun">
|
|
```bash
|
|
bun add sandbox-agent@0.3.x
|
|
# 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>
|
|
</Step>
|
|
|
|
<Step title="Start the sandbox">
|
|
`SandboxAgent.start()` provisions a sandbox, starts a lightweight [Sandbox Agent server](/architecture) inside it, and connects your SDK client.
|
|
|
|
<Tabs>
|
|
<Tab title="Local">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { local } from "sandbox-agent/local";
|
|
|
|
// Runs on your machine. Inherits process.env automatically.
|
|
const client = await SandboxAgent.start({
|
|
sandbox: local(),
|
|
});
|
|
```
|
|
|
|
See [Local deploy guide](/deploy/local)
|
|
</Tab>
|
|
|
|
<Tab title="E2B">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x @e2b/code-interpreter
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { e2b } from "sandbox-agent/e2b";
|
|
|
|
// Provisions a cloud sandbox on E2B, installs the server, and connects.
|
|
const client = await SandboxAgent.start({
|
|
sandbox: e2b(),
|
|
});
|
|
```
|
|
|
|
See [E2B deploy guide](/deploy/e2b)
|
|
</Tab>
|
|
|
|
<Tab title="Daytona">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x @daytonaio/sdk
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { daytona } from "sandbox-agent/daytona";
|
|
|
|
// Provisions a Daytona workspace with the server pre-installed.
|
|
const client = await SandboxAgent.start({
|
|
sandbox: daytona(),
|
|
});
|
|
```
|
|
|
|
See [Daytona deploy guide](/deploy/daytona)
|
|
</Tab>
|
|
|
|
<Tab title="Vercel">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x @vercel/sandbox
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { vercel } from "sandbox-agent/vercel";
|
|
|
|
// Provisions a Vercel sandbox with the server installed on boot.
|
|
const client = await SandboxAgent.start({
|
|
sandbox: vercel(),
|
|
});
|
|
```
|
|
|
|
See [Vercel deploy guide](/deploy/vercel)
|
|
</Tab>
|
|
|
|
<Tab title="Modal">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x modal
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { modal } from "sandbox-agent/modal";
|
|
|
|
// Builds a container image with agents pre-installed (cached after first run),
|
|
// starts a Modal sandbox from that image, and connects.
|
|
const client = await SandboxAgent.start({
|
|
sandbox: modal(),
|
|
});
|
|
```
|
|
|
|
See [Modal deploy guide](/deploy/modal)
|
|
</Tab>
|
|
|
|
<Tab title="Cloudflare">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x @cloudflare/sandbox
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { cloudflare } from "sandbox-agent/cloudflare";
|
|
import { SandboxClient } from "@cloudflare/sandbox";
|
|
|
|
// Uses the Cloudflare Sandbox SDK to provision and connect.
|
|
// The Cloudflare SDK handles server lifecycle internally.
|
|
const cfSandboxClient = new SandboxClient();
|
|
const client = await SandboxAgent.start({
|
|
sandbox: cloudflare({ sdk: cfSandboxClient }),
|
|
});
|
|
```
|
|
|
|
See [Cloudflare deploy guide](/deploy/cloudflare)
|
|
</Tab>
|
|
|
|
<Tab title="Docker">
|
|
```bash
|
|
npm install sandbox-agent@0.3.x dockerode get-port
|
|
```
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { docker } from "sandbox-agent/docker";
|
|
|
|
// Runs a Docker container locally. Good for testing.
|
|
const client = await SandboxAgent.start({
|
|
sandbox: docker(),
|
|
});
|
|
```
|
|
|
|
See [Docker deploy guide](/deploy/docker)
|
|
</Tab>
|
|
</Tabs>
|
|
|
|
<div style={{ height: "1rem" }} />
|
|
|
|
**More info:**
|
|
|
|
<AccordionGroup>
|
|
<Accordion title="Passing LLM credentials">
|
|
Agents need API keys for their LLM provider. Each provider passes credentials differently:
|
|
|
|
```typescript
|
|
// Local — inherits process.env automatically
|
|
|
|
// E2B
|
|
e2b({ create: { envs: { ANTHROPIC_API_KEY: "..." } } })
|
|
|
|
// Daytona
|
|
daytona({ create: { envVars: { ANTHROPIC_API_KEY: "..." } } })
|
|
|
|
// Vercel
|
|
vercel({ create: { env: { ANTHROPIC_API_KEY: "..." } } })
|
|
|
|
// Modal
|
|
modal({ create: { secrets: { ANTHROPIC_API_KEY: "..." } } })
|
|
|
|
// Docker
|
|
docker({ env: ["ANTHROPIC_API_KEY=..."] })
|
|
```
|
|
|
|
For multi-tenant billing, per-user keys, and gateway options, see [LLM Credentials](/llm-credentials).
|
|
</Accordion>
|
|
|
|
<Accordion title="Implementing a custom provider">
|
|
Implement the `SandboxProvider` interface to use any sandbox platform:
|
|
|
|
```typescript
|
|
import { SandboxAgent, type SandboxProvider } from "sandbox-agent";
|
|
|
|
const myProvider: SandboxProvider = {
|
|
name: "my-provider",
|
|
async create() {
|
|
// Provision a sandbox, install & start the server, return an ID
|
|
return "sandbox-123";
|
|
},
|
|
async destroy(sandboxId) {
|
|
// Tear down the sandbox
|
|
},
|
|
async getUrl(sandboxId) {
|
|
// Return the Sandbox Agent server URL
|
|
return `https://${sandboxId}.my-platform.dev:3000`;
|
|
},
|
|
};
|
|
|
|
const client = await SandboxAgent.start({
|
|
sandbox: myProvider,
|
|
});
|
|
```
|
|
</Accordion>
|
|
|
|
<Accordion title="Connecting to an existing server">
|
|
If you already have a Sandbox Agent server running, connect directly:
|
|
|
|
```typescript
|
|
const client = await SandboxAgent.connect({
|
|
baseUrl: "http://127.0.0.1:2468",
|
|
});
|
|
```
|
|
</Accordion>
|
|
|
|
<Accordion title="Starting the server manually">
|
|
<Tabs>
|
|
<Tab title="curl">
|
|
```bash
|
|
curl -fsSL https://releases.rivet.dev/sandbox-agent/0.3.x/install.sh | sh
|
|
sandbox-agent server --no-token --host 0.0.0.0 --port 2468
|
|
```
|
|
</Tab>
|
|
<Tab title="npx">
|
|
```bash
|
|
npx @sandbox-agent/cli@0.3.x server --no-token --host 0.0.0.0 --port 2468
|
|
```
|
|
</Tab>
|
|
<Tab title="Docker">
|
|
```bash
|
|
docker run -p 2468:2468 \
|
|
-e ANTHROPIC_API_KEY="sk-ant-..." \
|
|
-e OPENAI_API_KEY="sk-..." \
|
|
rivetdev/sandbox-agent:0.3.2-full \
|
|
server --no-token --host 0.0.0.0 --port 2468
|
|
```
|
|
</Tab>
|
|
</Tabs>
|
|
</Accordion>
|
|
</AccordionGroup>
|
|
</Step>
|
|
|
|
<Step title="Create a session and send a prompt">
|
|
<CodeGroup>
|
|
|
|
```typescript Claude
|
|
const session = await client.createSession({
|
|
agent: "claude",
|
|
});
|
|
|
|
session.onEvent((event) => {
|
|
console.log(event.sender, event.payload);
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Summarize the repository and suggest next steps." },
|
|
]);
|
|
|
|
console.log(result.stopReason);
|
|
```
|
|
|
|
```typescript Codex
|
|
const session = await client.createSession({
|
|
agent: "codex",
|
|
});
|
|
|
|
session.onEvent((event) => {
|
|
console.log(event.sender, event.payload);
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Summarize the repository and suggest next steps." },
|
|
]);
|
|
|
|
console.log(result.stopReason);
|
|
```
|
|
|
|
```typescript OpenCode
|
|
const session = await client.createSession({
|
|
agent: "opencode",
|
|
});
|
|
|
|
session.onEvent((event) => {
|
|
console.log(event.sender, event.payload);
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Summarize the repository and suggest next steps." },
|
|
]);
|
|
|
|
console.log(result.stopReason);
|
|
```
|
|
|
|
```typescript Cursor
|
|
const session = await client.createSession({
|
|
agent: "cursor",
|
|
});
|
|
|
|
session.onEvent((event) => {
|
|
console.log(event.sender, event.payload);
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Summarize the repository and suggest next steps." },
|
|
]);
|
|
|
|
console.log(result.stopReason);
|
|
```
|
|
|
|
```typescript Amp
|
|
const session = await client.createSession({
|
|
agent: "amp",
|
|
});
|
|
|
|
session.onEvent((event) => {
|
|
console.log(event.sender, event.payload);
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Summarize the repository and suggest next steps." },
|
|
]);
|
|
|
|
console.log(result.stopReason);
|
|
```
|
|
|
|
```typescript Pi
|
|
const session = await client.createSession({
|
|
agent: "pi",
|
|
});
|
|
|
|
session.onEvent((event) => {
|
|
console.log(event.sender, event.payload);
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Summarize the repository and suggest next steps." },
|
|
]);
|
|
|
|
console.log(result.stopReason);
|
|
```
|
|
|
|
</CodeGroup>
|
|
|
|
See [Agent Sessions](/agent-sessions) for the full sessions API.
|
|
</Step>
|
|
|
|
<Step title="Clean up">
|
|
```typescript
|
|
await client.destroySandbox(); // tears down the sandbox and disconnects
|
|
```
|
|
|
|
Use `client.dispose()` instead to disconnect without destroying the sandbox (for reconnecting later).
|
|
</Step>
|
|
|
|
<Step title="Inspect with the UI">
|
|
Open the Inspector at `/ui/` on your server (e.g. `http://localhost:2468/ui/`) to view sessions and events in a GUI.
|
|
|
|
<Frame>
|
|
<img src="/images/inspector.png" alt="Sandbox Agent Inspector" />
|
|
</Frame>
|
|
</Step>
|
|
</Steps>
|
|
|
|
## Full example
|
|
|
|
```typescript
|
|
import { SandboxAgent } from "sandbox-agent";
|
|
import { e2b } from "sandbox-agent/e2b";
|
|
|
|
const client = await SandboxAgent.start({
|
|
sandbox: e2b({
|
|
create: {
|
|
envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
|
|
},
|
|
}),
|
|
});
|
|
|
|
try {
|
|
const session = await client.createSession({ agent: "claude" });
|
|
|
|
session.onEvent((event) => {
|
|
console.log(`[${event.sender}]`, JSON.stringify(event.payload));
|
|
});
|
|
|
|
const result = await session.prompt([
|
|
{ type: "text", text: "Write a function that checks if a number is prime." },
|
|
]);
|
|
|
|
console.log("Done:", result.stopReason);
|
|
} finally {
|
|
await client.destroySandbox();
|
|
}
|
|
```
|
|
|
|
## Next steps
|
|
|
|
<CardGroup cols={2}>
|
|
<Card title="SDK Overview" icon="compass" href="/sdk-overview">
|
|
Full TypeScript SDK API surface.
|
|
</Card>
|
|
<Card title="Deploy to a Sandbox" icon="box" href="/deploy/local">
|
|
Deploy to E2B, Daytona, Docker, Vercel, or Cloudflare.
|
|
</Card>
|
|
</CardGroup>
|