> ## Documentation Index
> Fetch the complete documentation index at: https://docs.runloop.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Running Agents on Sandboxes

> Empower your agents to run code inside a devbox.

<Tip>Start with the [Runloop Quickstart](/docs/tutorials/quickstart) to use the examples below.</Tip>

## Overview

In this tutorial, you'll create an AI agent and use it to modify code in a demo TypeScript todo application that runs inside a devbox. You'll set up a devbox with code and agent mounts, execute the agent to change the app's color scheme, then review the changes and create a git branch. Every operation happens inside the devbox, which provides a secure, isolated environment for your workflow.

<Note title="Starter image">
  The starter image is used when you start a devbox without specifying an image, and as the default base when you build a blueprint without providing Dockerfile content. It includes:

  * **Core tools:** jq, sudo
  * **Extras:** dnsutils, iputils-ping, less, vim, rsync,
    gh
  * **Python stack:** Python 3.12, pip, uv
  * **Node stack:** Node 22.15.0, npm, Yarn 1.22.22 via
    corepack
</Note>

<Steps>
  <Step title="Set up your environment">
    Follow the [Runloop Quickstart](/docs/tutorials/quickstart) to set up your development environment. This includes:

    * Creating an API key
    * Setting up your `RUNLOOP_API_KEY` environment variable
    * Installing the Runloop SDK

    Make sure you have completed these steps before proceeding.
  </Step>

  <Step title="Create a Claude Agent">
    You can create a new agent or use an existing one. In this tutorial, we'll create a demo agent specifically for updating the todo app's color scheme.

    <CodeGroup>
      ```python Python theme={null}
      import asyncio
      from runloop_api_client import AsyncRunloopSDK

      runloop = AsyncRunloopSDK()

      agent = await runloop.agent.create(
        name="demo-color-theme-agent",
        version="2.0.0",
        source={
          "type": "npm",
          "npm": {
            "package": "@anthropic-ai/claude-code"
          }
        }
      )
      agent_id = agent.id
      print(f"Created agent: {agent_id}")
      ```

      ```typescript TypeScript theme={null}
      import { RunloopSDK } from '@runloop/api-client';

      const runloop = new RunloopSDK();

      const agent = await runloop.agent.create({
        name: "demo-color-theme-agent",
        version: "2.0.0",
        source: {
          type: 'npm',
          npm: {
            package: '@anthropic-ai/claude-code'
          }
        }
      });
      const agentId = agent.id;
      console.log(`Created agent: ${agentId}`);
      ```
    </CodeGroup>
  </Step>

  <Step title="Set up agent secrets">
    Create the following secrets in your Runloop account:

    * **`GH_TOKEN`**: GitHub personal access token. [Create a token](https://github.com/settings/tokens) on GitHub, then create the secret in Runloop.
    * **`ANTHROPIC_API_KEY`**: Anthropic API key. [Create a key](https://console.anthropic.com/) in Anthropic Console, then create the secret in Runloop.

    See the [Account Secrets documentation](/docs/devboxes/configuration/account-secrets) for instructions on creating secrets in Runloop.
  </Step>

  <Step title="Create a devbox with agent and code mount">
    Now we'll create a devbox with a code mount for a TypeScript todo application. The code mount will clone the [sample-todo-nextjs repository](https://github.com/runloopai/sample-todo-nextjs) into the devbox, and we'll configure the agent to work with it.

    <CodeGroup>
      ```python Python theme={null}
      # Create a devbox with a TypeScript todo app code mount
      devbox = await runloop.devbox.create(
        mounts=[
          {
            "type": "code_mount",
            "repo_name": "sample-todo-nextjs",
            "repo_owner": "runloopai",
          },
          {
            "type": "agent_mount",
            "agent_id": agent_id,
          }
        ],
        secrets={
          "GH_TOKEN": "GH_TOKEN",  # Maps secret name to env var
          "ANTHROPIC_API_KEY": "ANTHROPIC_API_KEY"  # Claude API key for the agent
        }
      )
      print(f"Devbox created: {devbox.id}")
      ```

      ```typescript TypeScript theme={null}
      // Create a devbox with a TypeScript todo app code mount and agent mount
      const devbox = await runloop.devbox.create({
        mounts: [
          {
            type: 'code_mount',
            repo_name: 'sample-todo-nextjs',
            repo_owner: 'runloopai',
          },
          {
            type: 'agent_mount',
            agent_id: agentId,
          }
        ],
        secrets: {
          GH_TOKEN: 'GH_TOKEN',  // Maps secret name to env var
          ANTHROPIC_API_KEY: 'ANTHROPIC_API_KEY'  // Claude API key for the agent
        }
      });
      console.log(`Devbox created: ${devbox.id}`);
      ```
    </CodeGroup>

    <Note>
      The [sample-todo-nextjs repository](https://github.com/runloopai/sample-todo-nextjs) will be cloned into `~/sample-todo-nextjs` in the devbox. This is a demo TypeScript todo application created by ZenStack and built with Next.js.
    </Note>
  </Step>

  <Step title="Execute agent to change the color scheme">
    Now we'll run the agent on the devbox to modify the color scheme of the todo app. The agent will have access to the mounted code and can make changes.

    <CodeGroup>
      ```python Python theme={null}
      # Create a named shell and navigate to the todo app directory
      shell = devbox.shell("agent-shell")
      await shell.exec("cd ~/sample-todo-nextjs")

      # Run the agent on the devbox to change the color scheme using Claude Code
      # Use -p flag for print mode (non-interactive, SDK usage)
      result = await shell.exec(
        'claude -p "Change the color scheme. Update the background colors and text colors to use a dark theme with blue accents. Make the changes to the CSS or Tailwind configuration files."'
      )

      print(f"Agent execution completed")
      print(f"Result: {await result.stdout()}")
      ```

      ```typescript TypeScript theme={null}
      // Create a named shell and navigate to the todo app directory
      const shell = devbox.shell('agent-shell');
      await shell.exec('cd ~/sample-todo-nextjs');

      // Run the agent on the devbox to change the color scheme using Claude Code
      // Use -p flag for print mode (non-interactive, SDK usage)
      const result = await shell.exec(
        'claude -p "Change the color scheme. Update the background colors and text colors to use a dark theme with blue accents. Make the changes to the CSS or Tailwind configuration files."'
      );

      console.log('Agent execution completed');
      console.log('Result:', await result.stdout());
      ```
    </CodeGroup>
  </Step>

  <Step title="Get results and create a branch">
    After the agent has made changes, you can check the git diff to see what was modified, then create a new branch for the changes.

    <Note>
      We're using the same named shell from the previous step, which maintains the working directory state. This means we don't need to use `cd` commands - the shell is already in the `~/sample-todo-nextjs` directory. Learn more about [named shells](/docs/devboxes/named-shells).
    </Note>

    <CodeGroup>
      ```python Python theme={null}
      # Use the same named shell (maintains directory state)
      # Check the git diff to see what changed
      diff_result = await shell.exec("git diff")
      print("Git diff:")
      print(await diff_result.stdout())

      # Create a new branch for the changes
      branch_name = "update-color-scheme"
      branch_result = await shell.exec(f"git checkout -b {branch_name}")
      print(f"Created branch: {branch_name}")

      # Stage and commit the changes
      await shell.exec("git add .")
      commit_result = await shell.exec(
        'git commit -m "Update color scheme to dark theme with blue accents"'
      )
      print("Changes committed!")

      # Clean up by shutting down the devbox
      await devbox.shutdown()
      ```

      ```typescript TypeScript theme={null}
      // Use the same named shell (maintains directory state)
      // Check the git diff to see what changed
      const diffResult = await shell.exec('git diff');
      console.log('Git diff:');
      console.log(await diffResult.stdout());

      // Create a new branch for the changes
      const branchName = 'update-color-scheme';
      await shell.exec(`git checkout -b ${branchName}`);
      console.log(`Created branch: ${branchName}`);

      // Stage and commit the changes
      await shell.exec('git add .');
      await shell.exec(
        'git commit -m "Update color scheme to dark theme with blue accents"'
      );
      console.log('Changes committed!');

      // Clean up by shutting down the devbox
      await devbox.shutdown();
      ```
    </CodeGroup>

    <Note>
      The agent has successfully modified the color scheme, and you've created a new branch with the changes. You can now push this branch to your repository or create a pull request if needed.
    </Note>
  </Step>
</Steps>

## What You Accomplished

Congratulations! You've successfully completed a full workflow for running AI agents on sandboxed devboxes. Here's what you accomplished:

* **Created and configured an AI agent** with Claude that can modify code in repositories
* **Set up a devbox** with both code mounts (to access repository code) and agent mounts (to run your agent)
* **Executed an agent command** that modified the color scheme of a real TypeScript application
* **Used named shells** to maintain working directory state across multiple commands
* **Reviewed agent-generated changes** using git diff and created a new branch with the modifications

You now have a working pattern for safely running AI agents on code in isolated environments. This workflow allows you to review and test AI-generated changes before applying them to your main codebase, providing a secure way to leverage AI assistance in your development process.

## Next Steps

Continue with these optional workflows to enhance your development process:

<Columns cols={3}>
  <Card title="Share Live Preview" icon="globe" href="/docs/tutorials/running-agents-on-sandboxes/share-live-preview">
    Start your app and share a live preview link in pull requests using devbox tunnels. Allow reviewers to see changes in action before merging.
  </Card>

  <Card title="Suspend and Resume Workflow" icon="pause" href="/docs/tutorials/running-agents-on-sandboxes/suspend-resume-workflow">
    Suspend your devbox to preserve state, wait for PR feedback, and resume to continue working iteratively. Perfect for responding to code review comments.
  </Card>

  <Card title="Turn-Based Interaction" icon="comments" href="/docs/tutorials/running-agents-on-sandboxes/turn-based-interaction">
    Create a turn-based workflow where the agent updates a GitHub PR with progress and responds to PR comments as prompts for iterative collaboration.
  </Card>
</Columns>
