---
title: "Quickstart"
description: "Start the server and send your first message."
icon: "rocket"
---

<Steps>
  <Step title="Install skill (optional)">
    <Tabs>
      <Tab title="npx">
        ```bash
        npx skills add rivet-dev/skills -s sandbox-agent
        ```
      </Tab>
      <Tab title="bunx">
        ```bash
        bunx skills add rivet-dev/skills -s sandbox-agent
        ```
      </Tab>
    </Tabs>
  </Step>

  <Step title="Set environment variables">
    Each coding agent requires API keys to connect to their respective LLM providers.

    <Tabs>
      <Tab title="Local shell">
        ```bash
        export ANTHROPIC_API_KEY="sk-ant-..."
        export OPENAI_API_KEY="sk-..."
        ```
      </Tab>

      <Tab title="E2B">
        ```typescript
        import { Sandbox } from "@e2b/code-interpreter";

        const envs: Record<string, string> = {};
        if (process.env.ANTHROPIC_API_KEY) envs.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
        if (process.env.OPENAI_API_KEY) envs.OPENAI_API_KEY = process.env.OPENAI_API_KEY;

        const sandbox = await Sandbox.create({ envs });
        ```
      </Tab>

      <Tab title="Daytona">
        ```typescript
        import { Daytona } from "@daytonaio/sdk";

        const envVars: Record<string, string> = {};
        if (process.env.ANTHROPIC_API_KEY) envVars.ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
        if (process.env.OPENAI_API_KEY) envVars.OPENAI_API_KEY = process.env.OPENAI_API_KEY;

        const daytona = new Daytona();
        const sandbox = await daytona.create({
          snapshot: "sandbox-agent-ready",
          envVars,
        });
        ```
      </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.4.1-full \
          server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>
    </Tabs>

    <AccordionGroup>
      <Accordion title="Extracting API keys from current machine">
        Use `sandbox-agent credentials extract-env --export` to extract your existing API keys (Anthropic, OpenAI, etc.) from local Claude Code or Codex config files.
      </Accordion>
      <Accordion title="Testing without API keys">
        Use the `mock` agent for SDK and integration testing without provider credentials.
      </Accordion>
      <Accordion title="Multi-tenant and per-user billing">
        For per-tenant token tracking, budget enforcement, or usage-based billing, see [LLM Credentials](/llm-credentials) for gateway options like OpenRouter, LiteLLM, and Portkey.
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Run the server">
    <Tabs>
      <Tab title="curl">
        Install and run the binary directly.

        ```bash
        curl -fsSL https://releases.rivet.dev/sandbox-agent/0.4.x/install.sh | sh
        sandbox-agent server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>

      <Tab title="npx">
        Run without installing globally.

        ```bash
        npx @sandbox-agent/cli@0.4.x server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>

      <Tab title="bunx">
        Run without installing globally.

        ```bash
        bunx @sandbox-agent/cli@0.4.x server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>

      <Tab title="npm i -g">
        Install globally, then run.

        ```bash
        npm install -g @sandbox-agent/cli@0.4.x
        sandbox-agent server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>

      <Tab title="bun add -g">
        Install globally, then run.

        ```bash
        bun add -g @sandbox-agent/cli@0.4.x
        # Allow Bun to run postinstall scripts for native binaries (required for SandboxAgent.start()).
        bun pm -g 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
        sandbox-agent server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>

      <Tab title="Node.js (local)">
        For local development, use `SandboxAgent.start()` to spawn and manage the server as a subprocess.

        ```bash
        npm install sandbox-agent@0.4.x
        ```

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

        const sdk = await SandboxAgent.start();
        ```
      </Tab>

      <Tab title="Bun (local)">
        For local development, use `SandboxAgent.start()` to spawn and manage the server as a subprocess.

        ```bash
        bun add sandbox-agent@0.4.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
        ```

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

        const sdk = await SandboxAgent.start();
        ```
      </Tab>

      <Tab title="Build from source">
        If you're running from source instead of the installed CLI.

        ```bash
        cargo run -p sandbox-agent -- server --no-token --host 0.0.0.0 --port 2468
        ```
      </Tab>
    </Tabs>

    Binding to `0.0.0.0` allows the server to accept connections from any network interface, which is required when running inside a sandbox where clients connect remotely.

    <AccordionGroup>
      <Accordion title="Configuring token">
        Tokens are usually not required. Most sandbox providers (E2B, Daytona, etc.) already secure networking at the infrastructure layer.

        If you expose the server publicly, use `--token "$SANDBOX_TOKEN"` to require authentication:

        ```bash
        sandbox-agent server --token "$SANDBOX_TOKEN" --host 0.0.0.0 --port 2468
        ```

        Then pass the token when connecting:

        <Tabs>
          <Tab title="TypeScript">
            ```typescript
            import { SandboxAgent } from "sandbox-agent";

            const sdk = await SandboxAgent.connect({
              baseUrl: "http://your-server:2468",
              token: process.env.SANDBOX_TOKEN,
            });
            ```
          </Tab>

          <Tab title="curl">
            ```bash
            curl "http://your-server:2468/v1/health" \
              -H "Authorization: Bearer $SANDBOX_TOKEN"
            ```
          </Tab>

          <Tab title="CLI">
            ```bash
            sandbox-agent --token "$SANDBOX_TOKEN" api agents list \
              --endpoint http://your-server:2468
            ```
          </Tab>
        </Tabs>
      </Accordion>
      <Accordion title="CORS">
        If you're calling the server from a browser, see the [CORS configuration guide](/cors).
      </Accordion>
    </AccordionGroup>
  </Step>

  <Step title="Install agents (optional)">
    To preinstall agents:

    ```bash
    sandbox-agent install-agent --all
    ```

    If agents are not installed up front, they are lazily installed when creating a session.
  </Step>

  <Step title="Install desktop dependencies (optional, Linux only)">
    If you want to use `/v1/desktop/*`, install the desktop runtime packages first:

    ```bash
    sandbox-agent install desktop --yes
    ```

    Then use `GET /v1/desktop/status` or `sdk.getDesktopStatus()` to verify the runtime is ready before calling desktop screenshot or input APIs.
  </Step>

  <Step title="Create a session">
    ```typescript
    import { SandboxAgent } from "sandbox-agent";

    const sdk = await SandboxAgent.connect({
      baseUrl: "http://127.0.0.1:2468",
    });

    const session = await sdk.createSession({
      agent: "claude",
      sessionInit: {
        cwd: "/",
        mcpServers: [],
      },
    });

    console.log(session.id);
    ```
  </Step>

  <Step title="Send a message">
    ```typescript
    const result = await session.prompt([
      { type: "text", text: "Summarize the repository and suggest next steps." },
    ]);

    console.log(result.stopReason);
    ```
  </Step>

  <Step title="Read events">
    ```typescript
    const off = session.onEvent((event) => {
      console.log(event.sender, event.payload);
    });

    const page = await sdk.getEvents({
      sessionId: session.id,
      limit: 50,
    });

    console.log(page.items.length);
    off();
    ```
  </Step>

  <Step title="Test with Inspector">
    Open the Inspector UI at `/ui/` on your server (for example, `http://localhost:2468/ui/`) to inspect sessions and events in a GUI.

    <Frame>
      <img src="/images/inspector.png" alt="Sandbox Agent Inspector" />
    </Frame>
  </Step>
</Steps>

## Next steps

<CardGroup cols={3}>
  <Card title="Session Persistence" icon="database" href="/session-persistence">
    Configure in-memory, Rivet Actor state, IndexedDB, SQLite, and Postgres persistence.
  </Card>
  <Card title="Deploy to a Sandbox" icon="box" href="/deploy/local">
    Deploy your agent to E2B, Daytona, Docker, Vercel, or Cloudflare.
  </Card>
  <Card title="SDK Overview" icon="compass" href="/sdk-overview">
    Use the latest TypeScript SDK API.
  </Card>
</CardGroup>
