Или: как получить эффект на $1,8 млн, потратив около $19 тыс. на токены.
Коротко: Hermes Agent автономно разобрал и подчистил почти миллион строк не самого эффектного, но крайне нужного кода. Пока агенты работали, Teknium и команда не выпадали из разработки новых возможностей.
Капитальную уборку в Hermes — open-source агенте Nous Research — откладывали долго. Причина знакомая любой инженерной команде: рефакторинг съедает время, которое иначе ушло бы на функции и исправление ошибок. К сентябрю в репозитории накопилось свыше миллиона строк Python-кода без учёта тестов. Один только gateway/run.py разросся до 34 847 строк. Читать такой файл — примерно как искать нужный провод в коробке после переезда.
Цель была без особой поэзии: сократить файлы, вынести общие утилиты, распилить чрезмерно длинные функции и сделать кодовую базу менее вязкой для сопровождения. 2 сентября автор поручил эту работу Hermes. Основной прогон занял около 19 часов активной работы: в нём участвовали 1 393 субагента, а пиковая параллельность достигала 218 исполнителей.
После перезапуска, продолжения сессии и двух циклов проверки сообществом изменения объединили в PR 4 сентября. Объём нетестового Python-кода уменьшился на 34,4%.
Расчётная цена моделей для главного запуска составила около $19 300; с последующими сессиями — примерно $25 тыс. Человеческое ревью в эту сумму не входит. По оценке команды, вручную аналогичная работа обошлась бы в $150 тыс.–$1,8 млн и заняла бы у небольшой группы от двух месяцев до двух лет. В обычный продуктовый план такая задача, скорее всего, просто не влезла бы.
Автор каждый день использует Hermes Agent для разработки самого Hermes Agent. В совместной работе агент запоминает удачные приёмы, уточняет свои навыки после правок и постепенно подстраивается под инженерные стандарты команды. Поэтому к моменту большого рефакторинга у него уже был не пустой контекст, а накопленный рабочий опыт — то, ради чего мы и настраиваем агентную память и накопление навыков в рабочих проектах.
Нужен большой набор PR с упрощениями — или один большой PR. Количество строк кода должно заметно сократиться, минимум на 30% в целом. Нужно разбить god-файлы, унифицировать повторно используемые вспомогательные функции и убрать бесконечные цепочки if-if-if-else. Код должен стать понятнее, аккуратнее и проще в сопровождении. Никаких отговорок и ожидания решений от автора: завершить работу и представить готовый PR либо набор PR.
Для этого использовали команду /goal. Она задаёт агенту постоянную цель и не даёт ему остановиться в тот момент, когда обычный исполнитель уже сказал бы: «На этом, пожалуй, всё».
Самоулучшение — не на словах
Навык hermes-agent-dev вырос из ежедневной работы с репозиторием. Когда команда находила более удачный процесс или автор поправлял ошибку в подходе, Hermes автоматически фиксировал этот урок в переиспользуемом виде. Постепенно там собрались инструкции по подготовке PR, типичным ловушкам и проверкам перед слиянием изменений.
Навыки Hermes — это понятные человеку Markdown-документы, при необходимости дополненные справочными материалами и скриптами. Агент может подгружать их в следующих задачах, а затем дополнять или переписывать по ходу дела. Не магия, конечно. Но довольно практичная память.
Например, в текущем hermes-agent-dev есть правило для неуспешной проверки:
воспроизвести проблему на HEAD
origin/mainв чистом окружении, чтобы понять, существовала ли она до изменений
Иными словами, если тест упал, сначала стоит запустить его на неизменённой ветке. Тогда видно, действительно ли сбой вызван новым патчем. Этот же принцип применили к рефакторингу: Hermes зафиксировал baseline и сопоставлял с ним ошибки, возникавшие при интеграции результатов исполнителей.
Навык распространяют среди инженеров компании. Каждый может подключить его к своей конфигурации Hermes и получить уже отработанные процессы, не начиная с чистого листа. Такие механики особенно важны там, где требуется не разовый бот: мы собираем агентов под конкретный инженерный процесс и доводим их до рабочего состояния.
Как запускали рефакторинг
Оркестратор измерил кодовую базу и разбил её на 36 непересекающихся зон. На основе цели автора и накопленных рекомендаций он сам подготовил письменные задания — не пришлось вручную раздавать инструкции каждому исполнителю.
Агенты работали через git worktree: отдельные checkout-копии позволяли менять код параллельно и не перетирать чужие файлы. В заданиях указывались участки для упрощения, интерфейсы, которые нельзя ломать, и набор обязательных проверок перед коммитом.
Некоторые исполнители, в свою очередь, делегировали части работы дальше. Получилось дерево глубиной до трёх уровней ниже исходного агента. Главный агент почти не правил исходники сам: он координировал, формировал задания и скрипты, читал отчёты, объединял ветки, запускал тесты. По сути, это рабочий пример того, как спроектировать рой агентов с оркестратором и разделением зон, а не один «умный чат» с длинным промптом.
Вся координация шла в одном Python-процессе на настольном компьютере с процессором i7 и 64 ГБ оперативной памяти. Инструменты агентов запускались как локальные подпроцессы, а удалённый инференс выполняла Claude Fable 5.1.
Агенты сверяли конкретные интерфейсы с исходным состоянием. Например, JSON Schema инструмента должна была остаться идентичной, а вывод CLI-команды --help сравнивался побайтно. После каждого проверенного шага требовался коммит. Это не бюрократия ради бюрократии: при сотнях параллельных изменений следы нужны всегда.
Примерно через 50 минут истёк токен аутентификации провайдера, и прогон остановился. Бывает. Коммиты и задания при этом сохранились. Автор открыл отдельную сессию Hermes, чтобы разобраться в причине, подготовить передачу контекста и передать его возобновлённому запуску. После этого исполнители вернулись к сохранённым изменениям, дочистили незавершённые участки и продолжили работу.
Самый крупный файл, gateway/run.py, разделили на модули для маршрутизации сообщений, streaming, RPC и обработки жизненного цикла. В других частях проекта повторяющиеся хелперы свели воедино, а длинные цепочки if/elif, завязанные на именах, заменили таблицами диспетчеризации.
Без промахов не обошлось. Ревьюеры нашли публичные имена, которые агенты удалили, потому что внутри репозитория на них никто не ссылался; внешние плагины, однако, могли их импортировать. Автоматическая замена вызовов suppress() изменила обработку исключений примерно в 65 местах. Это оказались реальные регрессии, не пойманные существующими тестами. Их исправили до merge в ходе двух раундов ревью; после слияния появились и дополнительные исправления.
Действительно ли с кодом стало проще?
Цифры в PR показывают масштаб изменений довольно наглядно:
| Метрика | До | После |
|---|---|---|
| Строки Python без тестов, все директории | 1 063 826 | 698 363 |
| Файлы длиннее 5 000 строк | 37 | 6 |
| Функции длиннее 300 строк | 192 | 2 |
Самая длинная цепочка if/elif | 92 ветви | 9 |
gateway/run.py | 34 847 строк | 5 512 строк |
Но есть интересный вопрос: если людям стало проще ориентироваться в коде, значит ли это, что проще стало и агентам? Разделённая функция короче, зато иногда приходится прыгать по вызовам между файлами. Команда проверила одну часть этой гипотезы, смоделировав поиск одинаковых фрагментов по 4 000 символов в обеих версиях репозитория.
Каждый поиск находил определение, читал окно в 60 строк и запрашивал дополнительные окна по 2 000 строк только тогда, когда определение не помещалось целиком. Средний объём возвращаемых токенов на поиск снизился с 2 218 до 993. Число поисков, которым требовалось ещё одно окно, упало с 628 до 184. Ряд функций, прежде требовавших десятки тысяч токенов, теперь читается за несколько тысяч.
Это измерение относится именно к поиску, а не к полноценному выполнению инженерных задач. Более того, медианный поиск вернул чуть больше токенов: комментариев и docstring стало меньше, поэтому фиксированное окно строк содержит более плотный код. Среднее значение снизилось благодаря тому, что гигантские определения стали существенно компактнее.
Были и компромиссы. Разделение файлов увеличило число модулей и импортных зависимостей, а некоторые точки входа стали загружаться медленнее. Рефакторинг сделал отдельные участки понятнее, но не отменил все связи между ними. Шесть файлов всё ещё больше 5 000 строк — работа не превращается в идеальную только потому, что её выполняли агенты.
Данные бенчмарка содержат результаты поиска, а также замеры зависимостей и времени выполнения.
Что команда вынесла из этого запуска
Сотни параллельных исполнителей подсветили и узкие места самого Hermes. В отдельных worktree агенты запускали около 30 экземпляров Pyright — Python language server, который суммарно занимал примерно 8,7 ГБ памяти. После доработки worktree смогли использовать единый сервер, при этом команда отдельно проверила, что диагностика по-прежнему корректно приходит от каждого рабочего дерева.
Также уменьшили дублирование HTTP-транспортов и исправили ссылки, удерживавшие уже завершивших работу агентов в памяти. В инструкции для будущих исполнителей добавили ограничения по размеру файлов, сложности функций и размещению нового поведения — по областям репозитория, чтобы правила появлялись в нужный момент, а не лежали мёртвым грузом в общей документации.
Наконец, появилась проверка удалённых публичных имён и тесты для ревью. Именно такие барьеры решают, можно ли пускать агентов в живой репозиторий, — мы выстроим CI, тесты и окружения под агентные пайплайны, прежде чем отдавать им код.
Навыки Hermes автоматически пополнились уроками этого рефакторинга, и ими можно поделиться со всей командой. По оценке Nous Research, результат обошёлся примерно в 1% от ручной стоимости и занял около 1% от ручного срока.
Главный вывод здесь, пожалуй, не в красивом числе 1 393. Сильный эффект даёт связка из накопленного опыта, чёткой цели, проверок и грамотной координации исполнителей. В следующий раз команда начнёт уже не с нуля: у инженеров и их агентов останутся навыки, правила и вполне конкретные уроки этого запуска.
