# Build a Coding Agent Using Claude Agent SDK and Daytona (/docs/guides/claude/claude-agent-sdk-interactive-terminal-sandbox)

This guide demonstrates how to run an autonomous coding agent based on [Claude Code](https://code.claude.com/docs/overview) inside a Daytona sandbox environment. The agent uses the [Claude Agent SDK](https://platform.claude.com/docs/agent-sdk/overview) to follow user prompts.

The agent can develop full-stack web apps, write code in any language, install dependencies, and run scripts. It can also start and manage dev servers, and generate preview links for live apps.

---

### 1. Workflow Overview [#1-workflow-overview]

When you launch the main module, a Daytona sandbox is created and a Python agent is initialized inside it. The agent is based on the [Claude Agent SDK](https://platform.claude.com/docs/agent-sdk/overview).

You interact with the main program via a command line chat interface. The program sends your prompts to the agent inside the sandbox, which executes them and returns the results:

```
$ npm run start                                   174s
Creating sandbox...
Installing Agent SDK...
Initializing Agent SDK...
Press Ctrl+C at any time to exit.
User: Build a Zelda-like game where I can move around the screen and talk to famous programmers
Thinking...
I'll build a Zelda-like game for you! This will be a fun project with player movement and NPC interactions with famous programmers.
🔨 Write
🔨 Write
Now let me start a simple HTTP server to host the game:
🔨 Bash
Perfect! I've created a Zelda-like game called "Programmer's Quest" for you! 🎮

## Game Features:

✨ Zelda-style gameplay:
- Top-down 2D view with classic retro aesthetics
- Player character with sword and shield
- Grid-based movement system
- Environmental obstacles (trees and rocks)

👥 Famous Programmers as NPCs:
1. Linus Torvalds - Creator of Linux
2. Grace Hopper - COBOL pioneer and Admiral
3. Alan Turing - Father of computer science
4. Ada Lovelace - First computer programmer
5. Dennis Ritchie - Creator of C and UNIX

🎮 Controls:
- Arrow Keys or WASD - Move your character
- SPACE - Talk to NPCs when you're near them

🌟 Gameplay:
- Explore the grassy map and find all 5 legendary programmers
- Each NPC has multiple quotes that cycle when you talk to them
- NPCs glow when you're near them
- Dialog boxes appear with their famous quotes
- Track your progress in the HUD

## Play Now:
🎯 [Click here to play the game!](https://80-8e2c4d23-212a-4f1e-bb6c-abfa71aeed3a.proxy.daytona.works)

The game features smooth movement, collision detection with trees and rocks, and an immersive dialog system. Try to find and talk to all 5 famous programmers to learn their wisdom! Each has 3 different quotes that cycle as you keep talking to them.

Enjoy your adventure! 🗡️✨
User:
```

The agent can also host web apps and provide you with a preview link using the [Daytona Preview Links](https://www.daytona.io/docs/preview/) feature. When your task involves running or previewing a web application, the agent automatically reasons about this need, hosts the app, and generates a preview link for you to inspect the live result:

<Image
  src="/docs/images/claude-agent-sdk-interactive-terminal-sandbox-result.gif"
  alt="RPG game demo generated by coding agent"
  width={600}
/>

You can continue interacting with your agent until you are finished. When you exit the program, the sandbox will be deleted automatically.

### 2. Project Setup [#2-project-setup]

#### Clone the Repository [#clone-the-repository]

First, clone the daytona [repository](https://github.com/daytona/guides.git) and navigate to the example directory:

```bash
git clone https://github.com/daytona/guides.git
cd guides/typescript/anthropic/single-claude-agent-sdk
```

#### Configure Environment [#configure-environment]

Get your API keys:

- **Daytona API key:** [Daytona Dashboard](https://app.daytona.com/dashboard/keys)
- **Anthropic API key:** [Anthropic Console](https://console.anthropic.com/)

Copy `.env.example` to `.env` and add your keys:

```bash
DAYTONA_API_KEY=your_daytona_key
SANDBOX_ANTHROPIC_API_KEY=your_anthropic_key
```

<Callout type="caution" title="API Key Security">
Note: The `SANDBOX_ANTHROPIC_API_KEY` key is passed into the Daytona sandbox environment and is accessible to any code executed inside the sandbox.
</Callout>

#### Alternative: Inject the Key as a Daytona Secret [#alternative-inject-the-key-as-a-daytona-secret]

The default setup passes the Anthropic key into the sandbox as a plain environment variable, so anything running inside the sandbox - including the agent itself - can read the raw key with `env`. [Daytona Secrets](/docs/secrets) keep the raw value out of the sandbox entirely: the environment variable holds only an opaque placeholder (`dtn_secret_<id>`), and Daytona's outbound proxy substitutes the real value into HTTPS request headers at egress - and only for requests to the hosts the Secret allows. An agent that dumps the environment, or sends it to a host outside the allowlist, exposes only the placeholder. The proxy does not rewrite responses, so an allowed host that echoes the key returns the real value into the sandbox.

The Secret-based flow needs `@daytona/sdk` 0.192.0 or newer and a one-time Secret setup:

1. Create the Secret once for your organization - in the [Daytona Dashboard](https://app.daytona.com/dashboard/secrets) or with a one-off script (save as `create-secret.ts` next to this guide's `.env` and run `npx tsx create-secret.ts`):

   ```typescript
   import { Daytona } from '@daytona/sdk'
   import * as dotenv from 'dotenv'

   dotenv.config()

   async function main() {
     const value = process.env.SANDBOX_ANTHROPIC_API_KEY
     if (!value) throw new Error('SANDBOX_ANTHROPIC_API_KEY is not set')

     const daytona = new Daytona()
     await daytona.secret.create({
       name: 'anthropic-api-key',
       value,
       hosts: ['api.anthropic.com'], // the only host the real key may be sent to
     })
   }

   main()
   ```

2. In `src/index.ts`, swap the `ANTHROPIC_API_KEY` env var for a `secrets:` mapping (environment variable name to Secret name):

   ```diff
    sandbox = await daytona.create({
      // Claude Code is memory intensive, so we use a medium snapshot
      snapshot: 'daytona-medium', // This snapshot has 4GiB RAM and 2 vCPUs
   -  envVars: {
   -    ANTHROPIC_API_KEY: process.env.SANDBOX_ANTHROPIC_API_KEY,
   -  },
   +  secrets: {
   +    ANTHROPIC_API_KEY: 'anthropic-api-key',
   +  },
    })
   ```

Inside the sandbox, `env` now shows `ANTHROPIC_API_KEY=dtn_secret_...`, yet the Claude Agent SDK still authenticates: it sends the key as the `x-api-key` HTTPS request header to `api.anthropic.com`, where the proxy swaps in the real value. Substitution happens only in HTTPS requests to allowed hosts - requests to any other host carry the harmless placeholder. See the [Secrets documentation](/docs/secrets#substitution-scope) for the full substitution scope.

#### Local Usage [#local-usage]

<Callout type="note" title="Node.js Version">
Node.js 18 or newer is required to run this example. Please ensure your environment meets this requirement before proceeding.
</Callout>

Install dependencies:

```bash
npm install
```

Run the agent:

```bash
npm run start
```

The agent will start and wait for your prompt.

### 3. Example Usage [#3-example-usage]

Example chat session:

```
$ npm run start
Creating sandbox...
Installing Agent SDK...
Initializing Agent SDK...
Press Ctrl+C at any time to exit.
User: Create a fun pet store landing page in Svelte
Thinking...
I'll create a fun pet store landing page in Svelte for you! Let me set up the project and build an engaging landing page with animations and a colorful design.
🔨 Bash
🔨 Bash
Now let me create a fun and engaging pet store landing page with animations, colorful sections, and interactive elements:
🔨 Read
> 🔨 Write
Now let me create the component files:
🔨 Write
🔨 Write
🔨 Write
🔨 Write
🔨 Write
Now let's update the main CSS file and start the development server:
🔨 Read
🔨 Write
Now let's start the development server:
🔨 Bash
🔨 TaskOutput
Perfect! 🎉 I've created a fun and colorful pet store landing page in Svelte! Here's what I built:

## Features:

✨ Hero Section

- Beautiful gradient background with animated floating cards
- Eye-catching navigation bar
- Call-to-action buttons with hover effects
- Bouncing emoji animations

🎯 Features Section

- 4 key benefits (Free Delivery, Premium Quality, Special Offers, Award Winning)
- Interactive cards with hover animations
- Icons that rotate and scale on hover

🛍️ Products Section

- 6 featured products with colorful backgrounds
- Star ratings
- Add to cart functionality
- Smooth hover animations

📧 Newsletter Section

- Vibrant gradient background with floating pet emojis
- Email subscription form
- Success message animation
- Special 20% off offer

👣 Footer

- Comprehensive navigation links
- Social media icons
- Dark gradient design

## Live Preview:

Your pet store is now running at: https://80-b3739199-d90e-4bde-ab18-450d74c950e8.proxy.daytona.works

The page includes:

- Smooth scroll behavior
- Responsive design for mobile devices
- Fun animations throughout
- Interactive elements with hover effects
- Colorful gradients and modern styling
- Emoji-based icons for a playful feel

Click the link to see your fun pet store landing page in action! 🐾
User:

```

### 4. Understanding the Agent's Architecture [#4-understanding-the-agents-architecture]

This example consists of two main components:

- **Main Program:** The main program is a Node.js script (`index.ts`) that runs on your local machine. It uses the Daytona SDK to create and manage a Daytona sandbox. The main program provides a command line interface for interacting with the agent inside the sandbox.
- **Sandbox Agent:** The sandbox agent is a Python script (`coding_agent.py`) that runs inside the Daytona sandbox. It uses the Claude Agent SDK to create a customized coding agent similar to Claude Code.

#### Initialization [#initialization]

On initialization, the main program:

1. Creates a new [Daytona sandbox](/docs/sandboxes) with your Anthropic API key included in the environment variables.
2. Installs the Claude Agent SDK by running `pip install` in the sandbox with [process execution](/docs/process-code-execution#command-execution).
3. Creates a new [code interpreter context](/docs/process-code-execution#run-code-stateful).
4. Uploads the coding agent script to the sandbox with [file uploading](/docs/file-system-operations#upload-a-single-file).
5. Initializes the Claude Agent SDK by running `import coding_agent` in the code interpreter context.
6. Waits for user input and sends prompts to the agent in the code interpreter context as shown below.

#### Main Program Code [#main-program-code]

Once the agent is running, the program creates a readline interface to read user input and sends it to the agent.
Each user request is passed to the agent by running a Python command in the code interpreter context:

```typescript
const result = await sandbox.codeInterpreter.runCode(
  `coding_agent.run_query_sync(os.environ.get('PROMPT', ''))`,
  {
    context: ctx,
    envs: { PROMPT: prompt },
    onStdout,
    onStderr,
  }
)
```

The `onStdout` and `onStderr` callbacks are used to pass the agent's output back to the main program. After the agent finishes responding to the prompt, the main program waits for the next user input.

#### Sandbox Agent Code [#sandbox-agent-code]

The sandbox agent uses the [Claude Agent SDK](https://platform.claude.com/docs/agent-sdk/overview) to create a customized coding agent based on Claude Code.
The agent is initialized with a system prompt that includes the workspace directory and an example of the [preview URL format](/docs/preview):

```python
system_prompt = """
You are running in a Daytona sandbox.
Use the /home/daytona directory instead of /workspace for file operations.
Your public preview URL for port 80 is: {}.
""".format(preview_url)
```

It also specifies the [tools and permission mode](https://platform.claude.com/docs/agent-sdk/quickstart#key-concepts) of the agent:

```python
client = ClaudeSDKClient(
  options=ClaudeAgentOptions(
    allowed_tools=["Read", "Edit", "Glob", "Grep", "Bash"],
    permission_mode="acceptEdits",
    system_prompt=system_prompt
  )
)
```

The code to run queries and receive responses follows the examples in Anthropic's [Claude Agent Python SDK documentation](https://platform.claude.com/docs/agent-sdk/python).

#### Clean up [#clean-up]

When you exit the main program, the Daytona sandbox and all files are automatically deleted.

**Key advantages:**

- Secure, isolated execution in Daytona sandboxes
- Communicate with the agent directly in your terminal
- Automatic dev server detection and live preview links
- Multi-language and full-stack support
- Simple setup and automatic cleanup
