---
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. Pass your LLM API keys so the agent can reach its provider.

    <CodeGroup>
      ```typescript Local
      import { SandboxAgent } from "sandbox-agent";
      import { local } from "sandbox-agent/local";

      // Runs on your machine. Inherits process.env automatically.
      const sdk = await SandboxAgent.start({
        sandbox: local(),
      });
      ```

      ```typescript E2B
      import { SandboxAgent } from "sandbox-agent";
      import { e2b } from "sandbox-agent/e2b";

      const sdk = await SandboxAgent.start({
        sandbox: e2b({
          create: {
            // Pass whichever keys your agent needs
            envs: {
              ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
              OPENAI_API_KEY: process.env.OPENAI_API_KEY,
            },
          },
        }),
      });
      ```

      ```typescript Daytona
      import { SandboxAgent } from "sandbox-agent";
      import { daytona } from "sandbox-agent/daytona";

      const sdk = await SandboxAgent.start({
        sandbox: daytona({
          create: {
            envVars: {
              ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
              OPENAI_API_KEY: process.env.OPENAI_API_KEY,
            },
          },
        }),
      });
      ```

      ```typescript Vercel
      import { SandboxAgent } from "sandbox-agent";
      import { vercel } from "sandbox-agent/vercel";

      const sdk = await SandboxAgent.start({
        sandbox: vercel({
          create: {
            runtime: "node24",
            env: {
              ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
              OPENAI_API_KEY: process.env.OPENAI_API_KEY,
            },
          },
        }),
      });
      ```

      ```typescript Modal
      import { SandboxAgent } from "sandbox-agent";
      import { modal } from "sandbox-agent/modal";

      const sdk = await SandboxAgent.start({
        sandbox: modal({
          create: {
            // Pass whichever keys your agent needs
            secrets: {
              ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY,
              OPENAI_API_KEY: process.env.OPENAI_API_KEY,
            },
          },
        }),
      });
      ```

      ```typescript Cloudflare
      import { SandboxAgent } from "sandbox-agent";
      import { cloudflare } from "sandbox-agent/cloudflare";

      const sdk = await SandboxAgent.start({
        sandbox: cloudflare({ sdk: cfSandboxClient }),
      });
      ```

      ```typescript Docker
      import { SandboxAgent } from "sandbox-agent";
      import { docker } from "sandbox-agent/docker";

      // Good for testing. Not security-hardened like cloud sandboxes.
      const sdk = await SandboxAgent.start({
        sandbox: docker({
          env: [
            `ANTHROPIC_API_KEY=${process.env.ANTHROPIC_API_KEY}`,
            `OPENAI_API_KEY=${process.env.OPENAI_API_KEY}`,
          ],
        }),
      });
      ```
    </CodeGroup>

    Each provider handles provisioning, server installation, and networking. Install the provider's peer dependency (e.g. `@e2b/code-interpreter`, `dockerode`) in your project. See the [Deploy](/deploy/local) guides for full setup details. For multi-tenant billing, per-user keys, and gateway options, see [LLM Credentials](/llm-credentials).

    <AccordionGroup>
      <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 sdk = 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 sdk = 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">
    ```typescript
    const session = await sdk.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);
    ```
  </Step>

  <Step title="Clean up">
    ```typescript
    await sdk.destroySandbox(); // tears down the sandbox and disconnects
    ```

    Use `sdk.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 sdk = await SandboxAgent.start({
  sandbox: e2b({
    create: {
      envs: { ANTHROPIC_API_KEY: process.env.ANTHROPIC_API_KEY },
    },
  }),
});

try {
  const session = await sdk.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 sdk.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>
