OpenHands: агент, который сам пишет и запускает код
Обычный ИИ-помощник в редакторе кода подсказывает следующую строку и останавливается — дальше решение принимаете вы. OpenHands устроен иначе: он получает задачу на естественном языке, пишет код, реально его выполняет в терминале, смотрит на результат или ошибку и сам правит код заново, пока задача не будет решена или не кончится лимит попыток. Это удобно, когда нужно быстро закрыть рутинную задачу без постоянного присмотра — но именно из-за того, что агент реально исполняет свой код, а не просто предлагает его на просмотр, тема безопасности здесь не факультативная, а обязательная часть настройки.
Содержание
- Что такое OpenHands и чем он отличается от автодополнения кода
- Базовый принцип: цикл «написал → выполнил → увидел ошибку → исправил»
- Архитектура: агент, среда выполнения и интерфейс
- Почему реальное выполнение кода — это реальный риск
- Обязательная практика: строгая изоляция среды выполнения
- Пошаговый запуск в безопасной конфигурации
- Реалистичные ожидания: для чего годится, а для чего — нет
Что такое OpenHands и чем он отличается от автодополнения кода
OpenHands (бывший OpenDevin) — открытый проект автономного ИИ-агента для разработки. Ключевое отличие от Copilot-подобных инструментов не в том, какую модель он использует, а в замкнутости цикла: агент не просто генерирует текст кода, который вы читаете и запускаете сами, а делает это за вас — от постановки задачи до проверки результата.
Практическая разница проявляется на простом примере. Если вы просите обычного ассистента «напиши функцию парсинга CSV», вы получаете код и сами его тестируете. Если вы даёте ту же задачу OpenHands, он пишет файл с функцией, запускает тестовый скрипт, читает вывод в терминале — traceback, если код упал, или неверный результат, если тест не прошёл, — вносит правку и запускает снова. Цикл повторяется, пока тест не пройдёт или пока не будет исчерпан лимит шагов/токенов, заданный в конфигурации. Внешне это выглядит как работа джуниора, которому дали тикет и не мешают — он сам компилирует, сам смотрит на ошибку и сам чинит, обращаясь к модели за каждым следующим шагом.
Базовый принцип: цикл «написал → выполнил → увидел ошибку → исправил»
Внутри у большинства подобных агентов, включая OpenHands, один и тот же паттерн, который в индустрии иногда называют ReAct-подобным циклом (reason + act):
- Постановка задачи. Пользователь описывает, что нужно сделать: «добавь эндпоинт в Flask-приложении», «почини падающий тест test_parser.py», «перепиши скрипт на использование pandas вместо ручного парсинга».
- Генерация действия. Модель решает, что сделать дальше: написать файл, отредактировать существующий, выполнить команду в терминале, посмотреть содержимое директории.
- Реальное выполнение. Это критический шаг, отличающий агента от автодополнения — действие не показывается человеку на утверждение, а тут же выполняется в среде выполнения (runtime): команда уходит в shell, код запускается интерпретатором, файл действительно записывается на диск.
- Наблюдение за результатом. Агент получает обратно то, что получил бы человек за терминалом: stdout, stderr, код возврата, содержимое изменённого файла.
- Анализ и следующая итерация. Если результат не совпал с ожидаемым (тест не прошёл, интерпретатор выбросил исключение, команда завершилась с ненулевым кодом), агент интерпретирует ошибку и генерирует следующее действие — как правило, правку кода с учётом текста ошибки.
- Условие остановки. Цикл прерывается, когда задача решена (тесты зелёные, требуемый файл создан и работает) либо когда исчерпан лимит: число итераций, бюджет токенов, время выполнения.
Здесь и кроется суть отличия от простого чат-бота с примерами кода в ответе: у OpenHands нет паузы для человека между «написал код» и «выполнил код». Это именно то, что делает агента полезным — не нужно вручную копировать код в терминал и разбирать traceback самому. И это же то, что делает его опасным без должных ограничений.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть ИИ на сервереАрхитектура: агент, среда выполнения и интерфейс
В OpenHands (как и в схожих проектах) обычно выделяют три логических слоя:
- Агент (agent) — сама логика, которая на основе задачи и истории действий решает, что делать дальше, обращаясь к LLM (может быть как облачная модель через API, так и локально развёрнутая).
- Среда выполнения (runtime/sandbox) — изолированное окружение, где реально исполняются команды и код агента. Обычно это отдельный Docker-контейнер с рабочей директорией, куда у агента есть доступ к shell, файловой системе и, при необходимости, к браузеру для веб-задач.
- Интерфейс — веб-UI или CLI, где человек ставит задачу, наблюдает за логом действий агента в реальном времени и может вмешаться (остановить, поправить, продолжить вручную).
Важный нюанс: сам факт, что раннтайм по умолчанию упакован в контейнер, ещё не значит, что настройка безопасна «из коробки». Дефолтная конфигурация многих подобных инструментов рассчитана на удобство разработчика на его собственной машине, а не на безопасный запуск на сервере с реальными данными.
Почему реальное выполнение кода — это реальный риск
Здесь стоит остановиться подробно, потому что это самая важная часть темы, а не второстепенное примечание.
Когда агент предлагает код, худшее, что может случиться — вы прочитаете неудачное решение и отклоните его. Когда агент выполняет код, каждая сгенерированная команда действует на реальную файловую систему, реальные процессы, реальную сеть — ровно так же, как если бы её ввёл человек за терминалом. ИИ-модель при этом не обладает пониманием последствий на уровне «это удалит продакшн-базу» — она статистически генерирует правдоподобное следующее действие, и в подавляющем большинстве случаев оно безобидно, но не гарантированно.
Практические сценарии, которые не требуют экзотики, а вытекают просто из ошибок логики:
- Агент решает, что для «чистого теста» нужно удалить временные файлы, и неверно определяет границу «временного» — под удаление попадает то, что временным не было.
- При рефакторинге агент переписывает конфиг и по ошибке указывает путь на уровень выше нужной директории.
- Скрипт миграции данных содержит логическую ошибку в условии
WHERE, и вместо тестовой выборки затрагивает всю таблицу. - Цикл «попробовать снова» на неверном шаге превращается в бесконечный: агент раз за разом выполняет ресурсоёмкую команду, не замечая, что причина ошибки не в этом, и исчерпывает диск, память или процессорное время.
- Агент с доступом к сети «для проверки» по своей инициативе обращается к внешним хостам — не по злому умыслу, а потому что это показалось ему логичным шагом решения задачи.
Ни один из этих сценариев не требует «взлома» или злонамеренного кода — это обычные ошибки логики, на которые способен любой начинающий разработчик, только у агента нет интуитивного «стоп, а если я ошибаюсь» перед нажатием Enter. Почему контейнер сам по себе не гарантирует полную изоляцию, мы подробно разбираем в статье про миф контейнерной изоляции: он ограничивает поверхность атаки, но не заменяет продуманную конфигурацию.
Обязательная практика: строгая изоляция среды выполнения
Из предыдущего раздела следует простое практическое правило: автономный агент, который реально исполняет сгенерированный код, должен запускаться только в изолированной песочнице — без исключений, даже для «простых» задач. Ниже — конкретные пункты, из которых должна состоять такая изоляция.
1. Отдельная рабочая директория, а не весь сервер. Runtime агента должен видеть только специально выделенную директорию проекта (workspace), примонтированную в контейнер, а не корень файловой системы хоста и не домашнюю директорию с другими проектами. В терминах Docker это означает точечный volume-маунт, а не -v /:/host и не запуск процесса агента напрямую на хосте вне контейнера:
docker run --rm -it \
-v /srv/agent-workspace/project-x:/workspace \
-v /srv/agent-workspace/project-x/.openhands-state:/.openhands \
-e SANDBOX_VOLUMES=/srv/agent-workspace/project-x:/workspace:rw \
--network agent-net \
docker.all-hands.dev/all-hands-ai/openhands:latest
Здесь агент физически не может «дотянуться» до файлов вне /workspace, даже если ошибётся в пути — операционная система просто не даст доступа.
2. Никакого доступа к продакшн-данным и продакшн-системам. Если задача агента — «почини баг в скрипте обработки заказов», это не повод давать ему прямое подключение к боевой базе данных или продакшн-API с реальными пользователями. Правильная схема — копия данных (или анонимизированная выборка) в изолированной среде, где ошибка агента максимум испортит копию, которую легко восстановить. Прямой доступ к продакшену через агента — это то же самое, что дать джуниору первого дня рут-доступ к боевому серверу, только без паузы на «подумать».
3. Явные лимиты на ресурсы и время. Циклическая природа агента («попробовал → не вышло → попробовал ещё раз») означает, что зацикливание — не гипотетический, а регулярно встречающийся сценарий на практике (мы разбирали конкретный такой случай в статье про агента, который зациклился ночью и сжёг лимиты). Обязательно ограничивайте:
# ограничение ресурсов контейнера с раннтаймом агента
docker run --rm -it \
--cpus="2" \
--memory="4g" \
--pids-limit=256 \
-e MAX_ITERATIONS=30 \
-v /srv/agent-workspace/project-x:/workspace \
docker.all-hands.dev/all-hands-ai/openhands:latest
Параметр числа итераций (в OpenHands это настраивается через конфигурацию агента, max_iterations в config.toml или переменную окружения) не даёт агенту молотить один и тот же неверный подход десятки раз подряд, сжигая бюджет на вызовы модели. Ограничение CPU/памяти и pids-limit защищает хост от того, что сгенерированный код случайно запустит fork-бомбу или бесконечный процесс.
4. Сетевая изоляция по умолчанию закрыта, открывается точечно. Если задаче не требуется исходящий доступ в интернет — не давайте его. Если требуется (например, установка пакетов) — ограничьте список хостов через отдельную docker-сеть с правилами, а не оставляйте агента с полным доступом «на всякий случай». Подробный разбор конкретных механизмов — сетевых неймспейсов, seccomp-профилей, безопасного проброса Docker-сокета — мы делаем отдельно в материале про изоляцию сервисов через Docker, а для задач с повышенными требованиями к изоляции стоит рассмотреть runtime уровня VM — их мы разбираем в статье про gVisor и Kata Containers, где контейнерный API сочетается с изоляцией, близкой к полноценной виртуальной машине.
5. Снимки состояния перед запуском. Раз агент может неожиданно затронуть файлы workspace, привычка делать git commit перед каждым запуском — не паранойя, а минимальная страховка: откат к рабочему состоянию должен занимать секунды, а не требовать восстановления из бэкапа.
Пошаговый запуск в безопасной конфигурации
Ниже — минимальный практический чек-лист для разворачивания OpenHands на своём сервере с уже применёнными выше принципами:
- Подготовьте отдельную директорию под проект и убедитесь, что в ней нет ничего, кроме нужных для задачи файлов:
mkdir -p /srv/agent-workspace/project-x
cd /srv/agent-workspace/project-x
git init && git add -A && git commit -m "baseline before agent run"
- Создайте отдельную Docker-сеть без прямого доступа к остальной инфраструктуре сервера:
docker network create --internal agent-net
(флаг --internal отключает выход в интернет из этой сети; если пакеты ставить всё же нужно — вместо --internal используйте сеть с явным egress-фильтром на конкретные хосты).
- Запустите контейнер с ограничениями ресурсов и точечным маунтом, как показано в примерах выше, задав ключ API модели через переменную окружения, а не хардкодом в конфиге.
- В веб-интерфейсе OpenHands сформулируйте задачу максимально конкретно — не «улучши проект», а «в файле
parser.pyфункцияparse_lineпадает на пустых строках, добавь обработку и покрой тест-кейсом» — и укажите разумный лимит итераций именно под эту задачу.
- Наблюдайте за логом действий в реальном времени, не оставляя агента без присмотра на длительный запуск, особенно на первых прогонах, пока не появится доверие к тому, как он ведёт себя на ваших задачах.
- По завершении обязательно проверьте diff перед тем, как переносить результат в основную ветку или тем более в продакшн:
git diff --stat
git diff
Реалистичные ожидания: для чего годится, а для чего — нет
Автономный цикл «пиши-запускай-чини» реально экономит время, но полезность жёстко привязана к масштабу задачи.
| Тип задачи | Подходит ли автономный агент | Почему |
|---|---|---|
| Написать конкретную функцию по чёткому ТЗ | Да | Узкая, проверяемая цель — тест либо проходит, либо нет |
| Исправить баг с понятным описанием и репродукцией | Да | Есть чёткий критерий успеха, ошибка воспроизводима |
| «Улучшить производительность приложения» | Осторожно | Размытая цель, агент может оптимизировать не то, что важно вам |
| Миграция схемы боевой базы данных | Нет без ручного ревью | Ошибка необратима или дорого обратима, нужен человеческий контроль каждого шага |
| Полный рефакторинг незнакомой кодовой базы за один запуск | Осторожно | Слишком широкий контекст, кумулятивная ошибка на раннем шаге портит всё, что после |
| Задача с доступом к реальным пользовательским данным | Нет | Возможная порча данных не тестовая, а реальная |
Практический вывод: доверяйте циклу для ограниченных, чётко очерченных задач — там, где легко сформулировать и легко проверить критерий «готово». Для всего, что затрагивает что-то важное — продакшн, реальные данные, необратимые операции — human-in-the-loop не опция, а обязательное условие: смотрите diff, читайте, что реально изменилось, и только потом принимаете результат, вместо того чтобы доверять автономному циклу вслепую. Автономность агента экономит вам время на написание черновика решения, но не снимает с вас ответственность за то, что в итоге попадёт в рабочий код.
Если хочется быстрее разобраться, чем автономный агент вообще отличается от привычного чат-бота с подсказками кода, стоит взглянуть на разбор в статье про агентов и чат-ботов на практике — там показано, где заканчивается автодополнение и начинается настоящая автономность с её рисками и выгодами.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть ИИ на сервереНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
OpenHands может работать с локальной моделью, а не только с облачным API?
Да, проект поддерживает подключение локально развёрнутых моделей через совместимые с OpenAI API эндпоинты — это снижает риск утечки кода наружу, но требует сервера с достаточными ресурсами под саму модель, отдельно от ресурсов под раннтайм агента.
Достаточно ли просто запустить агента в Docker, чтобы считать это безопасным?
Нет — контейнер снижает поверхность атаки, но без точечного маунта, ограничения ресурсов и сетевой изоляции сам факт «это в Docker» не защищает от порчи данных внутри примонтированной директории или от исчерпания ресурсов хоста.
Что делать, если агент зациклился и продолжает повторять неудачное действие?
Останавливайте запуск вручную через интерфейс и снижайте max_iterations для повторного запуска; если зацикливание регулярное — это обычно сигнал, что задача сформулирована слишком широко или без чёткого критерия завершения.
Нужно ли давать агенту доступ в интернет?
Только если задача явно этого требует (например, установка зависимостей) — и тогда лучше ограничить исходящие соединения списком конкретных хостов, а не оставлять сеть полностью открытой.
Можно ли доверить агенту сразу продакшн-задачу, если очень нужен быстрый результат?
Не стоит — риск необратимой ошибки в продакшене не компенсируется экономией времени; для боевых систем такой агент годится максимум как черновик решения, который проверяет и применяет человек.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →