How to Integrate the Daytona Connector for Full Linux Container Sandboxes in Flue
The Daytona connector adapts the official @daytona/sdk client to Flue's SandboxFactory interface, enabling agents to execute commands in fully isolated Linux containers instead of the default in-process Bash environment.
Integrating the Daytona connector for full Linux container sandboxes transforms how agents run code in the withastro/flue repository. This connector plugs into Flue's modular architecture to replace local execution with remote, full-OS Linux containers. By implementing the SandboxFactory contract defined in packages/sdk/src/sandbox.ts, the Daytona connector provides persistent sandboxes with package managers, network stacks, and the ability to mount custom volumes.
Architecture and Runtime Flow
Flue's connector system creates a clean abstraction between the agent logic and the execution environment. Understanding this flow helps you debug integration issues and optimize sandbox reuse.
The Connector Interface
The SandboxFactory type in packages/sdk/src/types.ts defines the contract that all sandbox connectors must fulfill. When you invoke flue run, the system creates a harness via init, which receives your factory and builds a SessionEnv through createSandboxSessionEnv in packages/sdk/src/sandbox.ts.
The Daytona connector implements this by wrapping an initialized Daytona sandbox inside a DaytonaSandboxApi class. This class fulfills the SandboxApi interface methods including readFile, writeFile, and exec. The connector specification lives in connectors/sandbox--daytona.md (lines 39-53), while the generated TypeScript implementation resides at connectors/daytona.ts or .flue/connectors/daytona.ts depending on your project layout.
Execution Delegation Chain
The runtime follows a strict delegation pattern to ensure isolation:
Agent code → init({ sandbox: daytona(sandbox) }) → createSandboxSessionEnv
→ SessionEnv methods delegate to Daytona SDK → Remote Linux container
This chain guarantees that every LLM tool invocation—whether shell commands, file reads, or file writes—executes inside the remote container rather than the host machine.
Installation and Configuration
Setting up the Daytona connector requires three components: the connector code itself, the SDK dependency, and valid API credentials.
Step 1: Generate the Connector
Use the Flue CLI to install the Daytona connector into your project:
flue add daytona --print
This command prints the installation script and writes the connector file to ./connectors/daytona.ts or ./.flue/connectors/daytona.ts. Reference the detailed guide in docs/connect-daytona.md for project-specific layout options.
Step 2: Install Dependencies
Add the Daytona SDK to your package.json as specified in connectors/sandbox--daytona.md:
npm install @daytona/sdk
Step 3: Configure Environment Variables
The connector expects runtime credentials via environment variables. Create an environment file containing:
DAYTONA_API_KEY– Required for authenticationDAYTONA_API_URL– Optional, for custom Daytona instancesDAYTONA_TARGET– Optional, to specify the target region
Load these using Flue's environment flag:
flue dev --env .env.local
# or
flue run --env production.env
Basic Implementation Example
Once configured, wire the connector into your agent by importing the daytona factory and passing a configured Daytona sandbox to init.
import type { FlueContext } from '@flue/sdk/client';
import { Daytona } from '@daytona/sdk';
import { daytona } from '../connectors/daytona'; // adjust path if using .flue/
export const triggers = { webhook: true };
export default async function ({ init, env }: FlueContext) {
// Initialize the Daytona client with API credentials
const client = new Daytona({ apiKey: env.DAYTONA_API_KEY });
// Create a fresh Linux container (supports custom images, env vars, etc.)
const sandbox = await client.create();
// Initialize Flue harness with the Daytona-backed sandbox
const harness = await init({
sandbox: daytona(sandbox),
model: 'anthropic/claude-sonnet-4-6',
});
// Execute commands inside the remote container
const session = await harness.session();
return await session.shell('uname -a');
}
This implementation runs uname -a inside a full Linux container managed by Daytona, returning the remote kernel information rather than host system details.
Advanced Usage: Persistent Sandbox Sessions
For workflows requiring setup persistence—such as cloning repositories or installing dependencies before running LLM tasks—reuse the same Daytona sandbox across multiple Flue sessions.
export default async function ({ init, payload, env }: FlueContext) {
const client = new Daytona({ apiKey: env.DAYTONA_API_KEY });
const sandbox = await client.create();
// Setup phase: initialize environment
const setupHarness = await init({ sandbox: daytona(sandbox) });
const setupSession = await setupHarness.session();
await setupSession.shell(`git clone ${payload.repo} /workspace/project`);
await setupSession.shell('npm install', { cwd: '/workspace/project' });
// Working phase: same sandbox, different working directory
const workHarness = await init({
id: 'project',
sandbox: daytona(sandbox),
cwd: '/workspace/project',
model: 'anthropic/claude-sonnet-4-6',
});
const workSession = await workHarness.session();
return await workSession.prompt(payload.prompt);
}
daytona(sandbox) creates a factory bound to that specific container instance. Passing the same sandbox object to multiple init calls maintains state between sessions while isolating execution from the host machine.
Key Source Files Reference
Understanding these files helps you debug integration issues and extend the connector:
packages/sdk/src/sandbox.ts– ContainscreateSandboxSessionEnvand theSandboxApicontract thatDaytonaSandboxApiimplements.packages/sdk/src/types.ts– Defines TypeScript interfaces includingSandboxFactory,SessionEnv, andFileStat.connectors/sandbox--daytona.md– Specification document with connector implementation details (lines 39-53) and installation requirements.connectors/daytona.ts– Generated TypeScript file created byflue add daytonacontaining thedaytona()factory function.docs/connect-daytona.md– End-user documentation covering installation, configuration, and troubleshooting.examples/hello-world/.flue/agents/with-tools.ts– Reference implementation showing sandbox usage patterns you can adapt for Daytona.
Summary
- Integration point: The
SandboxFactoryinterface inpackages/sdk/src/types.tsenables swapping the default Bash environment for remote containers. - Installation: Run
flue add daytona --printto generate the connector, then install@daytona/sdkvia npm. - Configuration: Provide
DAYTONA_API_KEYthrough environment files loaded withflue run --env <file>. - Implementation: Wrap a Daytona sandbox with the
daytona()factory and pass it toinit({ sandbox: daytona(sandbox) }). - Persistence: Reuse the same Daytona sandbox instance across multiple
initcalls to maintain state between setup and execution phases. - Isolation: All file system and shell operations execute inside full Linux containers via the
DaytonaSandboxApiclass, ensuring complete environment isolation.
Frequently Asked Questions
How does the Daytona connector differ from Flue's default Bash environment?
The default environment runs commands in-process using the host machine's Bash shell, while the Daytona connector delegates execution to remote Linux containers. According to the withastro/flue source code, the default SessionEnv executes locally, whereas the Daytona implementation in connectors/daytona.ts routes all exec, readFile, and writeFile calls through the @daytona/sdk to isolated sandboxes with full OS capabilities, package managers, and network isolation.
Can I use custom Docker images with the Daytona connector?
Yes, you can specify custom images when creating the Daytona sandbox. When calling client.create(), pass image configuration options as supported by the Daytona SDK. The connector itself is image-agnostic—it simply requires a valid sandbox instance. Pre-install languages, mount volumes, or configure the container via the Daytona SDK before passing it to the daytona() factory in your Flue agent.
What environment variables are required to run the Daytona connector?
You must provide DAYTONA_API_KEY, with optional DAYTONA_API_URL and DAYTONA_TARGET for custom deployments. The connector reads these at runtime from the environment file specified via flue dev --env <file> or flue run --env <file>. Without DAYTONA_API_KEY, the @daytona/sdk client initialization fails, preventing sandbox creation.
Is sandbox persistence maintained across multiple agent invocations?
Persistence depends on whether you reuse the same Daytona sandbox instance. Creating a new client.create() call spins up a fresh container, while passing the same sandbox object to multiple init calls maintains state. The source code in packages/sdk/src/sandbox.ts shows that SessionEnv instances created from the same factory share the underlying sandbox connection, making them ideal for multi-step workflows requiring dependency installation or file persistence.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →