Coding agents: минимализм, контроль и Docker

Да, я могу придумать флоу работы с агентами. Вот пример текста:

С возрастом мой тулинг для разработки становится все аскетичнее и проще. Меня перестали привлекать бибиканья Vim, бесконечные скобки Emacs и подбор миллионов плагинов для VS Code. Со временем от инструментов я начал ожидать предсказуемости. Это же правило распространилось и на AI-агентов.

Агенты стали обыденным инструментом в моей профессиональной карьере: при помощи AI я пишу статьи, решаю задачи, исследую проекты, провожу ресерчи. И как весь другой мой тулинг, харнес прошел эволюцию от сложного к простому.

Изначально я действительно гнался за кучей фичей, ставил все более и более странные плагины, пока однажды не наткнулся на статью Марио Цехнера о минималистичном агенте pi1. В этой заметке я не хочу слово-в-слово пересказывать пост Марио, вместо этого расскажу, как выглядит мой сетап и почему это работает.

Мем: на обоих краях кривой - LLM с bash и парой инструментов, в середине - сложный стек агентов
Мой путь: от bash и пары инструментов через сложный стек - обратно к bash и паре инструментов.

Минимализм #

Изначально у моего агента было множество подключенных MCP, LSP, плагинов, пока я не попробовал поставить pi и начать с чистого листа. Оказывается, ничего из вышеперечисленного лично мне не надо:

  • MCP засоряют контекст и хорошо заменяются связкой CLI + skill;
  • LSP в целом довольно шумные и путают агентов;
  • плагины, как правило, добавляли просто визуальные украшательства и ничего кроме.

Отказавшись от всего, мой агент перестал тратить время на изменение статуса задач в GUI, формирование запроса на отображение вопросов. Флоу стал максимально простым и понятным - обычный чат, в который я пишу, что мне надо, а агент это делает. Если у агента возникает какой-то вопрос, он мне его задает прямым текстом.

Спустя полгода активной агентской разработки и 4 крупных проекта этот принцип ни капли не изменился, ни разу не было задачи, когда мне было неудобно и я полез бы искать плагин для решения проблемы.

Сабагенты #

Еще одна вещь, на которую мне открыл глаза Марио. Возможно, для кого-то это покажется радикальным, но сабагенты не нужны.

Раньше я использовал сабагенты для построения какого-то loop’а разработки или надеялся, что большая и умная модель сама поймет, что нужно запустить второго агента для ревью или ресерча. Это и правда работало, но работало непрозрачно. У меня не было контроля за тем, что сабагент-ресерчер нашел и отдал основному агенту, не нагаллюцинировали ли эти два товарища чего-нибудь.

Сейчас я сам решаю, что мне нужен ресерч. Запускаю обычный чат и в нем провожу исследование. Результаты записываю в отдельный *.md-файл, который потом использую в качестве контекста в новом чате. У меня появился контроль над тем, когда нужно провести ресерч, что попадет в контекст при разработке и когда нужно выполнить ревью. Плюс все md-артефакты переживают перезапуск сессий, могут использоваться многократно для смежных задач.

Безопасность #

Меня довольно сильно пугает идея давать агентам полный доступ к проекту и к shell. Но, к сожалению, без этого невозможна полноценная агентская разработка. При этом доступ к секретам - отдельный риск: показательный пример - инцидент при оценке моделей OpenAI на Hugging Face2.

Вариант с ручным апрувом выполнения команд и доступа к файлам3 меня быстро утомил. По сути приходится просматривать все действия агентов, что убивает весь вайб от вайбкодинга. Вместо этого я принял компромиссное решение.

Мой агент всегда работает в yolo-режиме. Нужно установить какой-то пакет? Ставит. Нужен sudo-доступ для редактирования системных конфигов? Он есть. Звучит страшно, не так ли? Поэтому агент живет в Docker.

Есть довольно много решений, как запаковать агента в контейнер4 5. У меня небольшой самописный скрипт + свой образ, в который сразу установлены всякие Python/Ruff/Golang/Node/etc. Скрипт нужен, чтобы прокидывать только текущую директорию в режиме rw. Никаких других папок агент не видит и не может испортить. Плюс к агенту в руки не попадают никакие логины в GitHub, GitLab => уменьшается вероятность внезапного опенсорса рабочих проектов.

Однако есть еще один неприятный вектор создания факапов, и тут на сцену выходит мой первый плагин. Агенту на уровне харнеса запрещено вызывать write-команды Git. Он может читать историю, просматривать blame и выполнять любые другие read-команды, но не может коммитить, пушить, пулить и мержить. Плагин просто это все блокирует и бьет агента по рукам. Я сам решаю, когда и что нужно закоммитить, что отправить в стэш.

Как итог, агент может делать все, что хочет в рамках текущего проекта, но не может:

  • испортить мне систему;
  • испортить соседние проекты;
  • испортить ветки коллег.

Понятно, что это не дает 100% гарантии от целенаправленного слива или порчи проектов. Но чтобы агент обошел текущую систему «защиты», ему нужно поставить соответствующую задачу. В обычной жизни, мне кажется, неожиданные факапы сводятся к 0.

Резюмируя, я отказался от всего тулинга, к которому пришла индустрия за годы существования агентов. Взамен я получил свободу агентов и одновременно высокую степень контроля над ними.

Да, из-за этих ограничений я не стал 100x инженером, который за месяц может сделать то, что команда делает за годы. Всего лишь 10x инженер, который ревьюит все изменения перед коммитом и который случайно не форспушнет в ветку коллеги.


  1. Марио Цехнер о pi coding agent . ↩︎

  2. OpenAI: инцидент безопасности при оценке моделей на Hugging Face . ↩︎

  3. OpenCode: permissions - настройка разрешённых, запрещённых и требующих подтверждения действий. ↩︎

  4. Docker AI sandboxes - изолированные окружения для запуска агентов. ↩︎

  5. pi-less-yolo - запуск pi в Docker-контейнере с ограниченным доступом к файловой системе. ↩︎