Ejecución de Código en la Nube en Menos de 90ms: Cómo Daytona Reemplazó a Docker en Nuestro Stack de Agentes IA
Tabla de contenidos
Todo agente de IA que escribe código necesita un lugar donde ejecutarlo. El agente genera un script de Python, un comando de shell, un pipeline de datos — y algo tiene que ejecutar ese código de forma segura, aislado de tu entorno de producción.
Durante el último año, usamos Docker. Levantar un contenedor, ejecutar el código, destruirlo. Funciona. Pero “funciona” tiene un costo: 2-5 segundos de latencia de arranque en frío por sandbox. Cuando tu agente hace 10-20 llamadas a herramientas por tarea, eso son 30-100 segundos solo esperando que los contenedores arranquen.
Entonces probamos Daytona. Arranque en menos de 90ms. Sin Docker daemon. Sandboxes efímeros en la nube que se levantan más rápido de lo que tu agente puede pensar en el siguiente paso.
El Problema: Los Arranques en Frío de Docker Arruinan la Experiencia del Agente
Nuestros agentes de IA usan pydantic-ai-backend — una biblioteca de Python que proporciona backends de almacenamiento de archivos y ejecución de código para agentes de Pydantic AI. Antes de Daytona, teníamos tres backends:
| Backend | Almacenamiento | Ejecución | Caso de Uso |
|---|---|---|---|
StateBackend | En memoria | No | Pruebas, sesiones efímeras |
LocalBackend | Sistema de archivos | Sí | Desarrollo local |
DockerSandbox | Contenedor | Sí | Multi-usuario, código no confiable |
Docker era nuestra elección para producción. Ejecución aislada, entorno controlado, sin riesgo de que los agentes destruyan el host. Pero la sobrecarga de arranque era real:
- Descargar imagen (si no está en caché) — segundos
- Crear contenedor — cientos de ms
- Iniciar contenedor — cientos de ms
- Esperar health check — variable
- Ejecutar el comando real — la única parte que importa
Llega Daytona: Sandboxes Efímeros en la Nube
Daytona proporciona sandboxes efímeros en la nube — VMs aisladas que pre-aprovisionan recursos y eliminan la sobrecarga de arranque en frío. Menos de 90ms desde la creación hasta la ejecución del primer comando.
Añadimos DaytonaSandbox como cuarto backend en pydantic-ai-backend v0.1.12:
from pydantic_ai_backends import DaytonaSandbox, create_console_toolsetfrom pydantic_ai import Agentfrom dataclasses import dataclass
@dataclassclass Deps: backend: DaytonaSandbox
sandbox = DaytonaSandbox(api_key="dtna_...")
try: toolset = create_console_toolset() agent = Agent("openai:gpt-4.1", deps_type=Deps) agent = agent.with_toolset(toolset)
result = agent.run_sync( "Write a script that calculates fibonacci and run it", deps=Deps(backend=sandbox), ) print(result.output)finally: sandbox.stop()El mismo agente, el mismo toolset, la misma API — diferente backend. El agente no sabe (ni le importa) si está ejecutándose en Docker o en Daytona.
La Arquitectura: Abstracción BaseSandbox
Para soportar Daytona junto a Docker de forma limpia, extrajimos una clase base abstracta BaseSandbox:
class BaseSandbox(ABC): """Abstract sandbox backend for isolated code execution."""
@abstractmethod def execute(self, command: str, timeout: int = 1800) -> ExecuteResult: ...
@abstractmethod def _read_bytes(self, path: str) -> bytes: ...
@abstractmethod def write(self, path: str, content: str | bytes) -> WriteResult: ...
def edit(self, path: str, old: str, new: str, replace_all: bool = False) -> EditResult: # Default: read → Python string replace → write ...Tanto DockerSandbox como DaytonaSandbox heredan de BaseSandbox. Al toolset no le importa cuál recibe.
| Método | Docker | Daytona |
|---|---|---|
execute() | docker.exec_run() | sandbox.process.exec() |
_read_bytes() | Shell cat vía Docker exec | API nativa de descarga de archivos |
write() | Shell cat > vía Docker exec | API nativa de carga de archivos |
stop() | Eliminar contenedor | Eliminar sandbox en la nube |
Las APIs nativas de archivos de Daytona son particularmente interesantes — en lugar de pasar por un shell (como hace Docker), Daytona sube/descarga archivos directamente a través de su SDK.
Docker vs Daytona: Cuándo Usar Cada Uno
| Característica | DaytonaSandbox | DockerSandbox |
|---|---|---|
| Tiempo de arranque | Menos de 90ms | 2-5 segundos |
| Infraestructura | Nube (plataforma Daytona) | Docker daemon local |
| Configuración necesaria | Solo API key | Docker instalado + ejecutándose |
| Aislamiento | VM en la nube | Contenedor |
| Costo | Precios de Daytona | Gratis (recursos locales) |
| Ideal para | CI/CD, serverless, nube | Desarrollo local, auto-hospedado |
Usa Daytona cuando: despliegues en la nube, la latencia de arranque importa, escalado horizontal, pipelines CI/CD donde Docker-in-Docker es problemático.
Usa Docker cuando: ejecutas localmente, necesitas runtimes personalizados, quieres auto-hospedar todo, eres sensible al costo.
Configuración: 3 Líneas para Cambiar
# Before: Dockerfrom pydantic_ai_backends import DockerSandboxsandbox = DockerSandbox(image="python:3.12-slim")
# After: Daytonafrom pydantic_ai_backends import DaytonaSandboxsandbox = DaytonaSandbox(api_key="dtna_...")Instala con el extra de Daytona:
pip install pydantic-ai-backend[daytona]Por Qué Importan los Menos de 90ms
El número en bruto es impresionante, pero el impacto real está en los flujos de trabajo del agente:
Las llamadas secuenciales a herramientas se acumulan. Un agente resolviendo una tarea de programación podría: leer 5 archivos, planificar, escribir 3 archivos, ejecutar tests, corregir 2 archivos, ejecutar tests de nuevo. Son ~15 llamadas a herramientas. Con la sobrecarga de 2 segundos de Docker por operación de sandbox: 30 segundos de espera. Con Daytona: ~1.3 segundos de sobrecarga total.
Los agentes interactivos necesitan capacidad de respuesta. Cuando un usuario observa al agente trabajar en una terminal, cada segundo de latencia se siente como retraso. Menos de 100ms hace que la ejecución se sienta instantánea.
Los pipelines CI/CD son los más beneficiados. En CI, normalmente no puedes ejecutar Docker-in-Docker fácilmente. Daytona solo necesita una API key — sin daemon, sin contenedores privilegiados, sin montar sockets.
El Patrón Composite: Lo Mejor de Ambos
Para configuraciones complejas, CompositeBackend enruta diferentes operaciones a diferentes backends:
from pydantic_ai_backends import CompositeBackend, LocalBackend, DaytonaSandbox
backend = CompositeBackend( backends={ "local": LocalBackend("/workspace"), "sandbox": DaytonaSandbox(api_key="dtna_..."), }, routing={"src/": "local", "tmp/": "sandbox"},)Lee archivos fuente localmente (rápido, sin sobrecarga), ejecuta código no confiable en Daytona (aislado, efímero). El agente no lo sabe — el composite enruta cada llamada.
Conclusiones Clave
- La abstracción de backends vale la pena —
BaseSandboxnos permitió añadir Daytona sin tocar una sola línea de código del agente o lógica del toolset - Los menos de 90ms son reales — las VMs pre-aprovisionadas de Daytona eliminan por completo el arranque en frío de Docker
- Docker no está muerto — sigue siendo la elección correcta para desarrollo local y configuraciones auto-hospedadas
- La UX del agente es acumulativa — 15 llamadas a herramientas x 2 segundos de sobrecarga = 30 segundos de dolor. Las pequeñas mejoras de latencia se acumulan
Pruébalo: pydantic-ai-backend en GitHub — pip install pydantic-ai-backend[daytona]
Artículos relacionados
De create-react-app a create-ai-app: El nuevo estándar para aplicaciones de IA
En 2016, create-react-app estandarizó cómo construimos frontends. En 2026, las aplicaciones de IA necesitan el mismo mom...
AGENTS.md: Cómo hacer tu código amigable para agentes de IA (Copilot, Cursor, Codex, Claude Code)
Cada herramienta de codificación con IA lee tu repositorio de manera diferente. Así es como AGENTS.md — el estándar emer...
De 0 a agente IA en produccion en 30 minutos — plantilla full-stack con 5 frameworks de IA
Tutorial paso a paso: configurador web, elige un preset, selecciona tu framework de IA, configura mas de 75 opciones, do...