Бэкенды среды выполнения
PRX поддерживает несколько бэкендов выполнения для запуска инструментов, команд и внешних процессов. Подсистема среды выполнения абстрагирует среду выполнения за трейтом RuntimeAdapter, позволяя переключаться между локальным выполнением процессов, Docker-контейнерами и WebAssembly-песочницами без изменения конфигурации агента.
Обзор
Когда агент выполняет инструмент, требующий запуска внешней команды (скрипты оболочки, MCP-серверы, интеграции навыков), бэкенд среды выполнения определяет, как эта команда выполняется:
| Бэкенд | Изоляция | Накладные расходы | Применение |
|---|---|---|---|
| Native | На уровне процесса | Минимальные | Разработка, доверенные окружения |
| Docker | На уровне контейнера | Умеренные | Промышленная эксплуатация, недоверенные инструменты, воспроизводимость |
| WASM | На уровне песочницы | Низкие | Портируемые навыки, максимальная изоляция, система плагинов |
Цикл агента
│
├── Вызов инструмента: "shell" с командой "ls -la"
│
▼
┌───────────────────────────────────┐
│ RuntimeAdapter │
│ ┌─────────┬─────────┬─────────┐ │
│ │ Native │ Docker │ WASM │ │
│ │ Runtime │ Runtime │ Runtime │ │
│ └────┬────┴────┬────┴────┬────┘ │
└───────┼─────────┼─────────┼──────┘
│ │ │
┌────▼────┐ ┌──▼───┐ ┌──▼────┐
│ Process │ │ ctr │ │ wasmr │
│ spawn │ │ exec │ │ exec │
└─────────┘ └──────┘ └───────┘Трейт RuntimeAdapter
Все бэкенды реализуют трейт RuntimeAdapter:
#[async_trait]
pub trait RuntimeAdapter: Send + Sync {
async fn execute(&self, command: &str, args: &[String],
env: &HashMap<String, String>, working_dir: Option<&Path>,
timeout: Duration) -> Result<ExecutionOutput>;
async fn is_available(&self) -> bool;
fn name(&self) -> &str;
}ExecutionOutput содержит stdout, stderr, exit_code и duration.
Конфигурация
Выбор и настройка бэкенда среды выполнения в config.toml:
[runtime]
# Выбор бэкенда: "native" | "docker" | "wasm" | "auto"
backend = "auto"
# Глобальный таймаут выполнения (может быть переопределён для каждого инструмента).
default_timeout_secs = 60
# Максимальный размер вывода, захватываемого из stdout/stderr.
max_output_bytes = 1048576 # 1 МБ
# Список разрешённых переменных окружения. Только эти переменные
# передаются дочерним процессам (все бэкенды).
env_whitelist = ["PATH", "HOME", "TERM", "LANG", "USER"]Автоопределение
Когда backend = "auto", PRX выбирает бэкенд на основе доступности:
- Если Docker запущен и доступен, используется Docker
- Если доступна среда выполнения WASM, используется WASM для совместимых инструментов
- Возврат к Native
Автоопределение выполняется один раз при запуске, и выбранный бэкенд записывается в журнал.
Бэкенд Native
Бэкенд Native порождает команды как локальные дочерние процессы с помощью tokio::process::Command. Это самый простой и быстрый бэкенд, не требующий дополнительных зависимостей.
Конфигурация
[runtime]
backend = "native"
[runtime.native]
# Оболочка для выполнения команд.
shell = "/bin/bash"
# Дополнительные переменные окружения.
[runtime.native.env]
RUSTFLAGS = "-D warnings"Характеристики
| Свойство | Значение |
|---|---|
| Изоляция | Только на уровне процесса (наследует права пользователя) |
| Время запуска | < 10 мс |
| Доступ к ФС | Полный (ограничен правами пользователя и песочницей) |
| Доступ к сети | Полный (ограничен песочницей) |
| Зависимости | Нет |
| Платформа | Все (Linux, macOS, Windows) |
Соображения безопасности
Бэкенд Native не обеспечивает изоляции помимо стандартных границ Unix-процессов. Команды выполняются с теми же правами, что и процесс PRX. Всегда комбинируйте с подсистемой песочницы при выполнении недоверенных команд:
[runtime]
backend = "native"
[security.sandbox]
backend = "bubblewrap"
allow_network = false
writable_paths = ["/tmp"]Бэкенд Docker
Бэкенд Docker выполняет команды внутри эфемерных контейнеров. Каждое выполнение создаёт новый контейнер, запускает команду, захватывает вывод и уничтожает контейнер.
Конфигурация
[runtime]
backend = "docker"
[runtime.docker]
image = "debian:bookworm-slim"
socket = "/var/run/docker.sock"
memory_limit = "256m"
cpu_limit = "1.0"
pids_limit = 100
network = "none" # "none" | "bridge" | "host"
mount_workspace = true
workspace_mount_path = "/workspace"
auto_pull = true
auto_remove = trueВремя запуска составляет 500 мс — 2 с в зависимости от образа. Доступ к файловой системе ограничен контейнером плюс явно подключённые тома.
Безопасность
Бэкенд Docker обеспечивает строгую изоляцию по умолчанию: изоляция сети (network = "none"), ограничения ресурсов (память/CPU/PID), файловая система корня только для чтения, без привилегированного режима и автоматическое удаление контейнера после выполнения. Поддерживается переопределение образа для каждого инструмента через [runtime.docker.tool_images].
Бэкенд WASM
Бэкенд WASM (WebAssembly) выполняет инструменты, скомпилированные в модули .wasm. WASM обеспечивает портируемое, изолированное выполнение с детальным контролем возможностей через WASI (WebAssembly System Interface).
Конфигурация
[runtime]
backend = "wasm"
[runtime.wasm]
# Движок WASM: "wasmtime" | "wasmer"
engine = "wasmtime"
# Каталог, содержащий модули .wasm.
module_path = "~/.local/share/openprx/wasm/"
# Возможности WASI, предоставляемые модулям WASM.
[runtime.wasm.capabilities]
filesystem_read = ["/workspace"]
filesystem_write = ["/tmp"]
network = false
env_vars = ["HOME", "USER"]
# Максимальное время выполнения одного вызова WASM.
timeout_secs = 30
# Максимальное выделение памяти для модулей WASM.
max_memory_mb = 128Характеристики
| Свойство | Значение |
|---|---|
| Изоляция | Песочница WASM (на основе возможностей) |
| Время запуска | 10-50 мс |
| Доступ к ФС | Только предоткрытые каталоги WASI |
| Доступ к сети | Настраивается через WASI |
| Зависимости | Среда выполнения wasmtime или wasmer (условная компиляция) |
| Платформа | Все (WASM платформонезависим) |
Условная компиляция
Бэкенд WASM условно компилируется за флагом функции:
# Сборка PRX с поддержкой WASM
cargo build --release --features wasm-runtimeБез флага функции бэкенд WASM недоступен, и backend = "auto" его пропустит.
Система плагинов
Бэкенд WASM обеспечивает работу системы плагинов PRX. Навыки, распространяемые как модули .wasm, могут загружаться динамически без доверия нативному коду. Регистрируйте WASM-инструменты в config.toml в разделе [tools.custom.<name>] с type = "wasm" и путём module.
Фабричная функция
PRX использует фабричную функцию (create_runtime) для выбора бэкенда при запуске. Она сопоставляет настроенную строку backend с соответствующей реализацией RuntimeAdapter и проверяет доступность бэкенда (например, работает ли демон Docker, скомпилирован ли движок WASM).
Матрица сравнения
| Характеристика | Native | Docker | WASM |
|---|---|---|---|
| Сложность настройки | Нет | Демон Docker | Флаг функции + модули |
| Задержка запуска | < 10 мс | 500 мс - 2 с | 10-50 мс |
| Уровень изоляции | Низкий | Высокий | Высокий |
| Контроль ресурсов | Ограничения ОС | cgroups | Ограничения памяти WASM |
| Изоляция сети | Через песочницу | Встроенная | Возможность WASI |
| Изоляция ФС | Через песочницу | Встроенная | Предоткрытие WASI |
| Портируемость | Платформозависимая | OCI-образы | Платформонезависимая |
| Совместимость инструментов | Все | Все (с образом) | Только скомпилированные в WASM |
Замечания по безопасности
- Бэкенд среды выполнения — это уровень защиты, а не замена песочницы. Обе системы работают вместе — среда выполнения предоставляет среду выполнения, песочница добавляет ограничения на уровне ОС.
- Бэкенд Docker требует доступа к Docker-сокету, который сам по себе является привилегированным ресурсом. Запускайте PRX под выделенной служебной учётной записью.
- Модули WASM не имеют неявных полномочий. Каждая возможность (файловая система, сеть, окружение) должна быть явно предоставлена.
- Настройка
env_whitelistприменяется ко всем бэкендам. API-ключи и секреты никогда не передаются в среды выполнения инструментов.