This example runs a Letta Code agent inside a Daytona sandbox. You can interact with the agent via the CLI to run automations, build apps, and launch web apps or services using Daytona preview links.
Note: In this example, your Letta API key is passed into the sandbox environment and may be accessible to any code executed within it.
- Secure sandbox execution: The agent operates within a controlled environment, along with code or commands run by the agent.
- Letta Code integration: Includes the full capabilities of Letta Code, including reading and editing code files, running shell commands, and persistent memory.
- Stateful Agents: Letta Code uses stateful agents under the hood (with the Letta API), which have built-in memory and can be resumed across sandbox sessions. Agents can also be viewed in Letta's Agent Development Environment.
- Preview deployed apps: Use Daytona preview links to view and interact with your deployed applications.
- Node.js: Version 18 or higher is required
To run this example, you need to set the following environment variables:
DAYTONA_API_KEY: Required for access to Daytona sandboxes. Get it from Daytona DashboardSANDBOX_LETTA_API_KEY: Required to run Letta Code. Get it from Letta Platform
Create a .env file in the project directory with these variables.
-
Install dependencies:
npm install
-
Run the example:
npm run start
When this example is run, the agent follows the following workflow:
- A new Daytona sandbox is created.
- Letta Code is installed in the sandbox.
- Letta code is launched in bidirectional headless mode with a Daytona-specific system prompt.
- User queries are passed to the agent as JSON, and JSON responses are parsed and displayed to the user.
- When the script is terminated, the sandbox is deleted.
The quickstart passes the Letta 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 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 exfiltrates it never sees a usable key.
The Secret-based flow needs @daytona/sdk 0.192.0 or newer and a one-time Secret setup:
-
Create the Secret once for your organization - in the Daytona Dashboard or with a one-off script (save as
create-secret.tsnext to this guide's.envand runnpx tsx create-secret.ts):import { Daytona } from '@daytona/sdk' import * as dotenv from 'dotenv' dotenv.config() async function main() { const value = process.env.SANDBOX_LETTA_API_KEY if (!value) throw new Error('SANDBOX_LETTA_API_KEY is not set') const daytona = new Daytona() await daytona.secret.create({ name: 'letta-api-key', value, hosts: ['api.letta.com'], // the only host the real key may be sent to }) } main()
-
In
src/index.ts, swap theLETTA_API_KEYenv var for asecrets:mapping (environment variable name to Secret name):sandbox = await daytona.create({ - envVars: { LETTA_API_KEY: process.env.SANDBOX_LETTA_API_KEY }, + secrets: { LETTA_API_KEY: 'letta-api-key' }, })
Inside the sandbox, env now shows LETTA_API_KEY=dtn_secret_..., yet Letta Code still authenticates: it sends the key as an HTTPS Authorization header to api.letta.com, where the proxy swaps in the real value. Substitution happens only in HTTPS request headers toward allowed hosts - requests to any other host carry the harmless placeholder. See the Secrets documentation for the full substitution scope.
Creating sandbox...
Installing Letta Code...
Starting Letta Code...
Initializing agent...
Agent initialized. Press Ctrl+C at any time to exit.
You: make and run a lunar lander web server
Thinking...
🔧 TodoWrite
🔧 Write /home/daytona/workspace/index.html
🔧 TodoWrite
🔧 Start HTTP server on port 8000
🔧 BashOutput
🔧 TodoWrite
Perfect! 🚀 Your Lunar Lander game is now running!
Play the game here: https://8000-1a1ebb4b-e521-4881-87bf-494777570a8a.proxy.daytona.works
## How to Play:
- ↑ / W - Fire main thruster (slow descent)
- ← / A - Fire left thruster (move right)
- → / D - Fire right thruster (move left)
## Objective:
Land on the green landing pad with:
- Vertical speed < 2 m/s
- Horizontal speed < 1 m/s
Watch your fuel! You start with 1000 units and each thruster burns fuel. The lander starts with some horizontal drift to make it challenging. Good luck, astronaut! 🌙
See the main project LICENSE file for details.