AI-инжиниринг
Sandboxes для агентов: e2b, Modal, Daytona - безопасный запуск кода
Цели урока
- Понять почему exec() и child_process опасны для AI-агентов без изоляции
- Разобраться в разнице Firecracker microVMs и Docker для sandbox-изоляции
- Интегрировать E2B SDK в агентный loop за несколько строк
- Применять production-паттерны: limits, cleanup, cost estimation
Агент написал код. Нужно его запустить. На чём? На проде? На хосте API-сервера? Ни то ни другое. Именно здесь ломается большинство первых coding agents. E2B, Modal, Daytona решают эту проблему - каждый по-своему.
- E2B: 8900+ GitHub звёзд, USD 21M Series A (2024), 88% Fortune 100 AI Early Adopters, клиенты - Perplexity, Groq, Hugging Face
- Firecracker (AWS, 2018) - технология за AWS Lambda: виртуализация с производительностью контейнера, 150ms cold start
- Daytona: 277ms cold start на Docker-контейнерах, популярен для dev environment automation
- Claude Code, Cursor, GitHub Copilot Workspace - все используют sandbox-изоляцию для запуска агент-генерированного кода
Предварительные знания
- Что такое автономный агент: цикл «решение - действие - наблюдение», итерации с инструментами
- Tool calling: как LLM вызывает функции и получает результаты обратно
- Базовое понимание Docker и контейнеров: образ, изоляция процессов, ресурсные лимиты
Firecracker, проблема небезопасного кода и появление E2B
Технологическая база для агентных песочниц появилась в 2018 году, когда AWS открыла исходники Firecracker - лёгкого VMM на Rust для AWS Lambda и Fargate. Идея: дать каждой нагрузке отдельное ядро Linux (изоляция уровня виртуализации), сохранив скорость запуска как у контейнера (cold start около 150ms). До этого выбор был жёстким: контейнеры быстрые, но с общим ядром, а полноценные VM безопасные, но медленные. С появлением LLM-агентов в 2022-2023 годах остро встала отдельная проблема: код, который генерирует модель, это untrusted code. Агент может сгенерировать rm -rf, бесконечный цикл или сетевой запрос с утечкой данных, не понимая последствий. Запускать такой код через eval() или exec() на хосте недопустимо. В 2023 году появился E2B (Environments to Build) - open-source песочница как сервис, построенная поверх Firecracker и предоставляющая Python/JS SDK с запущенным внутри Jupyter-сервером. Это закрыло разрыв между «агент написал код» и «код можно безопасно выполнить»: каждый запуск получает изолированную microVM с собственным ядром, ресурсными лимитами и чистым окружением.
Проблема запуска кода: почему нельзя просто exec()
Агент написал код. Нужно его запустить. На чём? На проде? На хосте API-сервера? Ни то ни другое. Именно здесь ломается большинство первых coding agents.
Код, который генерирует LLM - это **недоверенный код**. Он исходит от вероятностной системы, которая не несёт ответственности за результат. Даже с отличным промптом агент может сгенерировать `rm -rf /`, бесконечный цикл или сетевой запрос к внешнему серверу.
Три измерения проблемы изоляции:
- **Security** - недоверенный код не должен иметь доступа к файловой системе хоста, сети, секретам
- **Resource limits** - CPU, память, диск, время должны быть ограничены - иначе один агент кладёт весь сервер
- **Reproducibility** - чистое окружение для каждого запуска, без накопленных side effects
E2B (Environments to Build) - лидер рынка sandbox-as-a-service: 8900+ GitHub звёзд, USD 21M Series A, используется в 88% Fortune 100 компаний из списка AI Early Adopters. Клиенты: Perplexity, Groq, Hugging Face. Основан на Firecracker microVMs.
Почему нельзя использовать child_process.exec() для запуска кода от AI-агента?
Firecracker microVMs vs Docker: два подхода к изоляции
Два основных подхода к sandbox-изоляции для агентов - Docker-контейнеры и Firecracker microVMs. У каждого свои trade-offs.
| Характеристика | Docker | Firecracker microVM |
|---|---|---|
| Cold start | 50-100ms | 150ms |
| Изоляция ядра | Нет (shared kernel) | Да (dedicated kernel) |
| Memory overhead | ~1-3 MB | ~5 MB |
| Security | Namespace isolation | Hardware virtualization |
| Ядро exploit уязвимость | Возможна | Крайне сложна |
| Кто использует | Daytona (277ms start) | E2B, AWS Lambda |
Daytona - конкурент E2B на основе Docker. Cold start 277ms (с Docker-контейнерами vs 150ms у E2B с Firecracker). Компромисс: чуть медленнее, но контейнеры дешевле в эксплуатации и проще в кастомизации образов.
Практическое правило выбора платформы:
- **E2B** - лучше для: изоляция критична, публичный SaaS, untrusted user code, команды без DevOps-экспертизы
- **Modal** - лучше для: ML-воркнагрузки, GPU-задачи, python-heavy стек, batch processing
- **Daytona** - лучше для: dev environments, self-hosted требования, Docker-совместимые образы
- **Собственный Docker** - лучше для: enterprise с compliance требованиями, существующая Docker-инфраструктура
Firecracker был разработан AWS в 2018 году для AWS Lambda и Fargate. Открытый исходный код в ноябре 2018. Ключевое достижение: virtualization-grade isolation при container-grade performance. За счёт этого AWS Lambda может запускать тысячи функций на одном хосте без риска cross-tenant утечек.
Главное преимущество Firecracker перед Docker для sandbox агентов:
E2B SDK: интеграция с агентом за 10 строк
E2B SDK предоставляет простой TypeScript/Python интерфейс к Firecracker microVM. Агентный loop: генерация кода LLM - выполнение в sandbox - возврат stdout/stderr - итерация.
Ключевые методы E2B Sandbox API:
| Метод | Описание | Пример использования |
|---|---|---|
| sandbox.runCode(code) | Выполнить Python/JS код, вернуть stdout/stderr | Основной loop агента |
| sandbox.files.write(path, content) | Записать файл в sandbox | Создать входные данные для скрипта |
| sandbox.files.read(path) | Прочитать файл из sandbox | Получить результат работы агента |
| sandbox.commands.run(cmd) | Выполнить shell команду | pip install, git clone, etc. |
| sandbox.kill() | Уничтожить sandbox немедленно | В finally блоке всегда |
E2B поддерживает кастомные templates - Docker образы с предустановленными зависимостями. Для Data Science агента: шаблон с pandas, numpy, matplotlib. Для DevOps агента: terraform, kubectl, AWS CLI. Создание template: `e2b template build` из Dockerfile.
В агентном loop с E2B sandbox какой порядок шагов правильный?
Production паттерны: timeouts, limits, cleanup
Sandbox без ограничений - это ресурсная утечка и непредсказуемые счета. Production-паттерны для надёжной работы в масштабе.
Стоимость E2B: модель оплаты per compute-second. Sandbox стоит денег, пока он живёт - даже если агент ничего не делает.
| Проблема | Симптом | Решение |
|---|---|---|
| Sandbox leak | Растущие расходы без активных задач | finally { await sandbox.kill() } всегда |
| Infinite loop агента | Задача не завершается, счёт растёт | maxIterations + maxTimeMs лимиты |
| Накопленное состояние | Ошибки в поздних итерациях из-за ранних | Новый sandbox для каждой независимой задачи |
| Большой output | OOM или медленная передача результатов | maxOutputBytes + pagination результатов |
Persistent sandbox (живущий между несколькими user-сессиями) стоит дороже, чем ephemeral. E2B поддерживает `sandbox.pause()` и `sandbox.resume()` для экономии: sandbox сохраняет состояние, но не тратит compute в паузе. Полезно для IDE-like агентов с долгими сессиями.
Агент запущен в sandbox без timeoutMs и maxIterations лимитов. Что произойдёт при зацикливании?
Достаточно Docker-контейнера для безопасного запуска кода от агента
Docker обеспечивает namespace-изоляцию, но ядро остаётся общим. Kernel exploit в одном контейнере может затронуть хост
Для внутренних инструментов Docker часто достаточен. Для публичных SaaS с untrusted user code (например, coding assistant для тысяч пользователей) Firecracker microVM даёт принципиально другой уровень защиты: отдельное ядро = нет shared attack surface.
Sandbox - это только про безопасность. Производительность у него хуже
Firecracker 150ms и Docker 50-100ms - это приемлемо для большинства агентных задач. Основная задержка в агентном loop - LLM inference (200-800ms), не sandbox start
Если агент делает 10 итераций с claude-sonnet - это 2-8 секунд LLM time. Sandbox cold start 150ms - это менее 2% от общего времени. Оптимизировать нужно LLM latency, а не sandbox.
Итоги
- LLM-генерированный код - недоверенный: без sandbox возможны rm -rf, бесконечные циклы, утечки данных
- Firecracker (E2B) - dedicated kernel per sandbox, 150ms start, максимальная изоляция
- Docker (Daytona) - shared kernel, 50-277ms start, достаточно для большинства задач
- E2B SDK: Sandbox.create() -> runCode() -> kill() - агентный loop за 30 строк
- Обязательно: maxIterations, timeoutMs, finally { sandbox.kill() }
Вопросы для размышления
- Какой уровень изоляции нужен для конкретного use case: внутренний инструмент компании vs публичный coding assistant - и чем обосновать выбор?
- Как архитектурно разделить short-lived sandbox (для одной задачи) и persistent sandbox (для долгой сессии) - и когда это имеет смысл?
- Стоимость sandbox незначительна по сравнению с LLM токенами. Но что произойдёт если агент зациклится на 1000 запросах в день - посчитать реальные цифры.
Что дальше
Агент может безопасно выполнять код. Следующая задача - массовая обработка: тысячи документов за полцены через Batch API.
- Batch API — Async обработка тысяч запросов с 50% скидкой - следующий урок
- Автономные агенты — Фундамент: как агент принимает решения и итерирует
- Computer Use — Агент управляет GUI - смежная тема sandbox-изоляции
- Cost Management — Управление стоимостью: sandbox + LLM + оптимизация