Загрузка 0
ПОДЕЛИТЬСЯ

Мой блог

Листай вниз

Как превратить правила команды разработки в инструкции для LLM-агента

Как превратить правила команды разработки в инструкции для LLM-агента

Привет! На связи команда разработки Just AI. Сегодня расскажем, как мы автоматизировали часть задач в процессах разработки, используя четкие инструкции для LLM-агента. Речь идет не о генерации функций или написании кода по промпту — с этим кодинг-ассистенты уже справляются неплохо. Нас интересовало другое: что происходит с задачей до и после того, как программист закончил писать код. Требуется создать merge request, подготовить описание изменений, запустить сборку, дождаться результата, прикрепить ссылку к тикету в Jira, сменить статус, передать задачу тестировщику, списать время и дождаться ревью. На небольшой задаче таких рутинных шагов набирается около десятка. Приходится держать в голове порядок действий, внутренние договоренности команды и постоянно переключаться между различными инструментами. Мы решили автоматизировать этот слой при помощи LLM-агента, описав правила работы обычными текстовыми инструкциями и подключив к ним инструменты для взаимодействия с Jira, GitLab, Jenkins и Sentry. В этом материале мы подробно разберем, как разделили эти действия на слои, какие ограничения внедрили и что изменилось в повседневной практике.

Где теряется время при закрытии задачи

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

  • Открыть тикет в Jira, внимательно прочитать описание и комментарии.
  • Сделать исправление, запушить код и назвать ветку в строгом соответствии с правилами.
  • Описать merge request для код-ревьюеров.
  • Оформить в задаче понятный отчет о проделанной работе для тестировщика.
  • Перейти в Jenkins, запустить сборку и дождаться ее завершения.
  • Привязать ссылку на полученную сборку к задаче.
  • Напоминать коллегам о необходимости посмотреть MR.
  • Передать задачу тестировщику, удостоверившись, что окружение развернуто на стенде.
  • Перевести тикет в соответствующий статус и зафиксировать потраченное время.

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

Реклама

LLM умеет работать с кодом. А с процессом?

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

  • контекст задачи приходилось передавать модели вручную: копировать описание из Jira, затем комментарии, скачивать и прикладывать файлы;
  • даже если модель генерировала отличный комментарий, забрать его и перенести в трекер приходилось самостоятельно.

Логичным следующим шагом выглядело подключение MCP к трекеру, выдача токена и предоставление прав на прямую запись в задачу. Но здесь вскрылась другая трудность: сам по себе доступ к API никак не объясняет агенту, как именно принято работать в конкретном коллективе. Например, нейросеть может составить в тикете избыточный подробный комментарий на несколько абзацев. Формально текст корректен, но тестировщику он не нужен — ему должно быть понятно, что именно изменилось и что сборка прошла успешно. Главный вывод на данном этапе заключался в том, что технического доступа к API недостаточно. Протокол MCP отвечает лишь на вопрос «что технически можно сделать», но для выполнения работы по внутренним стандартам правила и ограничения необходимо фиксировать отдельно.

Архитектура системы в три слоя

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

Нижний уровень представлен вызовами API рабочих систем: трекера, репозитория, инструментов сборки и мониторинга. Самостоятельное написание таких интеграций с нуля под каждый сервис отнимает много времени, поэтому для простых задач мы задействовали скилл-генератор из открытых наборов — в нашем случае MCP Builder. Достаточно описать требования человеческим языком: например, поставить задачу создать сервер для нашего CI, который будет запускать сборку, запрашивать текущий статус и читать логи.

Над MCP располагаются actions. Это атомарные действия, фиксирующие порядок работы с конкретным инструментом. К примеру, файл jira/comment.md описывает не просто факт отправки комментария, но и требования к его содержимому, а также обязательную проверку после публикации. Верхний уровень занимают playbooks — сценарии для рутинных процессов, выполняемых регулярно: слияние изменений, сборка проекта, обновление статуса задачи и ее дальнейшая передача.

Дополнительно права доступа агента настраиваются в файле .claude/settings.json. Там четко указано, какие операции система может проводить автономно, а где требуется обязательная остановка и запрос подтверждения у человека. Полный цикл обработки запроса выглядит следующим образом: CLAUDE.md обращается к индексу playbooks, выбирает нужный playbook, активирует action, задействует MCP, запрашивает подтверждение и выполняет действие.

Если разработчик просит собрать проект ZB-451 и отписаться в задачу, агент сначала находит подходящий сценарий, затем нужные атомарные шаги и только после этого вызывает конкретные MCP-инструменты. Подобное разделение архитектуры позволяет модифицировать ее части изолированно. Если меняется процедура запуска сборки, достаточно обновить соответствующий action, тогда как зависящие от него playbooks останутся прежними.

Как устроен action

Одно логическое действие оформляется строго в виде отдельного файла. Внутри используется единая структура: назначение, список инструментов, последовательность шагов и проверка результата. При проектировании таких инструкций важно учитывать несколько ключевых нюансов.

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

Реклама

Инструменты задаются через белый список. Если конкретный инструмент не прописан в файле action, агент не сможет его вызвать, что служит надежным способом ограничить радиус возможных ошибок.

Проверка результата является обязательным условием. Нейросети недостаточно просто зафиксировать отсутствие ошибок в ответе API — необходимо явно указать, какой итог считать успешным. Например, если инструмент возвращает идентификатор созданного комментария, публикация считается успешной; если ID отсутствует, фиксируется ошибка и повторный запрос не отправляется.

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

Почему одно действие — один файл

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

Кроме того, чем короче и лаконичнее инструкция, тем точнее ей следует языковая модель. Мы стараемся умещать описание одной задачи в пределах 50–70 строк: только конкретное действие и условия его выполнения без лишней сопутствующей информации.

Наконец, из атомарных блоков можно легко собирать новые процессы на лету. Если пользователь запрашивает сборку с условием отправить уведомление коллеге в Mattermost и перевести тикет при успехе, системе не обязательно иметь заранее заготовленный сценарий — при наличии трех соответствующих actions агент самостоятельно выстроит нужную цепочку.

Индексы инструкций и экономия контекста

Когда объем справочной информации и инструкций вырастает, возникает техническая задача эффективного поиска нужных данных без загрузки всего репозитория в оперативную память модели. Для этого мы реализовали двухуровневый индекс.

Точка входа одна — CLAUDE.md, единственный файл, который агент читает сам, без просьбы. Дальше запрос «напиши в задачу, что баг пофикшен» проходит так: playbooks/_index.md → actions/_index.md → actions/tracker/comment.md → MCP-сервер. В индексе хранится по одной строке на действие. Агент сначала смотрит короткое описание, а целиком загружает только тот файл, который подходит для текущего запроса. Индексы мы генерируем из шапок файлов, а не редактируем вручную.

Если подходящего playbook нет, агент ищет действие напрямую. Если не находит и его — останавливается и спрашивает человека, а не пытается придумать новый способ работы. Так в контексте остаются только инструкции, которые нужны для конкретного запроса.

Зачем нужен отдельный слой Playbook

Action помогает понять, как правильно выполнить один шаг, а Playbook — какие шаги и в каком порядке нужно выполнить для конкретного процесса. Например, после успешного ревью команда всегда проходит одну и ту же цепочку: проверить MR, замержить изменения, запустить сборку, дождаться результата, оставить комментарий в задаче и изменить ее статус. Playbook описывает этот порядок, но не содержит вызовов API и подробной логики отдельных действий. Он только ссылается на actions.

Это дает несколько преимуществ:

Пример работы LLM-агента в среде разработки
Практический пример выполнения задач агентом
  • Изменения в одном месте распространяются на все процессы. Если мы поменяли правила сборки в actions/ci/build.md, все playbooks, которые используют это действие, получают новую логику.
  • Playbook не превращается в жесткий скрипт. Если разработчик попросил не выполнять один из шагов, агент может пропустить его, сохранив остальные проверки и порядок.
  • Playbook не обязателен. Если готового процесса нет, агент может собрать цепочку из отдельных actions — тогда порядок придумывает он, а знание о том, как правильно, все равно берет из файлов действий.

Playbook нужен там, где порядок шагов важен и должен быть одинаковым у всей команды.

Реклама

Как агент закрывает задачу

Возьмем простую задачу из ежедневной работы. Разработчик пишет: «Замержи ZB-12345». Для этого процесса у нас есть playbook. Агент проходит несколько шагов:

  • Сам находит merge request, связанный с задачей.
  • Проверяет апрувы (у нас в компании нужно два обязательных апрува).
  • Смотрит, что все четыре обсуждения закрыты.
  • Проверяет конфликты.
  • Если все в порядке, он доходит до первого места, где требуется участие человека, — показывает, что собирается сделать мерж в main, и ждет подтверждения.
  • После подтверждения мержит в main.
  • Запускает сборку и дожидается результата.
  • Когда сборка готова, он формирует комментарий для задачи и снова останавливается. В комментарии будет короткая сводка: задача смержена в main, статус и ссылка на сборку, компонент и ветка. Такой формат мы заранее описали в actions/tracker/comment.md, поэтому агент не пытается каждый раз сочинять комментарий заново.
  • Показывает превью и ждет подтверждения.
  • После второго подтверждения он публикует комментарий, переводит задачу в статус «интеграция» и списывает время.

Формат комментария заранее описан в actions/tracker/comment.md, поэтому агент не сочиняет его заново для каждой задачи. В нем будет короткая сводка: задача смержена в main, статус и ссылка на сборку, компонент и ветка. Получается, что человек нужен только в двух местах — там, где агент меняет состояние во внешних системах и действие уже нельзя незаметно отменить. Все остальное, включая чтение задачи и ожидание сборки, проходит автоматически.

Раньше эта цепочка занимала 15–20 минут, а с инструкциями — около пяти. При этом разработчик может изменить отдельный шаг прямо в запросе. Например: «Замержи ZB-12345, но не списывай время». Агент пройдет ту же цепочку, но не будет выполнять последнее действие.

Как мы автоматизировали дежурство

Еще один сценарий применения искусственного интеллекта — разбор ошибок из сервиса мониторинга Sentry. Для этого мы создали отдельный изолированный сценарий со своей специализированной директорией и ограниченными правами, за пределы которых помощник выходить не должен. По простой текстовой команде система выполняет целый комплекс рутинных операций.

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

После этого система автоматически создает задачи на четырех разработчиков с привязкой к текущему спринту, формирует merge request для обновления конфигурации Sentry, чтобы отсечь лишний шум в будущем, и отправляет итоговый отчет в рабочий чат дежурства. Если раньше у специалиста уходило до часа на анализ ошибок, ручное распределение, работу с интерфейсами и оформление задач, то теперь весь процесс занимает 10–15 минут. При этом участие человека сводится к быстрой проверке отчета и ревью сформированного merge request, а создание четырех задач вместо десяти минут теперь отнимает около тридцати секунд.

Как ограничили права агента

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

Мягкие ограничения прописываются непосредственно внутри конкретного действия. Например, инструкция может предписывать сначала показать предпросмотр комментария и только потом ожидать одобрения перед его окончательной публикацией. Подобные правила держатся на том, что языковая модель внимательно читает и неукоснительно выполняет переданные указания.

Жесткие ограничения задаются на уровне конфигурационного файла и никак не зависят от текста самого действия. С помощью настроек доступа можно четко разделить операции на те, которые выполняются самостоятельно, и те, что требуют санкции человека:

  • Получение данных и чтение информации выполняются автоматически.
  • Любые изменения во внешних системах требуют предварительного подтверждения.
  • Проверка текущего статуса сборки происходит без участия человека, а запуск нового билда — только после явного согласия разработчика.

Отдельного внимания заслуживает вопрос обработки конфиденциальной информации. В описанных сценариях персональные данные не задействованы. Если планируется использовать подобные инструменты для бизнес-процессов с ПД, потребуется внедрить дополнительный защитный слой, который будет фильтровать и проверять информацию до того, как она попадет в среду агента.

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

Что сломалось и как это исправили

Практика показала, что на этапе внедрения неизбежно возникают технические трудности и архитектурные просчеты. Первая рабочая версия функционировала стабильно, однако вскоре выявились две серьезные проблемы, которые потребовали доработки.

Сначала выяснилось, что модель находит лазейки и начинает обходить существующие правила. При наличии трехслойной структуры она игнорировала готовые сценарии и инструкции, обращаясь напрямую к MCP-серверу. Такой подход работал быстрее, но полностью разрушал саму архитектуру, поскольку вся ценная экспертиза оставалась в пропущенных текстовых файлах. Для устранения этого упущения разработчики внедрили специальные защитные перехватчики: прямые вызовы сервера блокируются до тех пор, пока система не зафиксирует чтение файла соответствующего действия.

Вторая сложность проявилась при масштабировании инструмента на другие команды. Когда рамки одного отдела расширились, у каждого подразделения начали формироваться собственные регламенты, из-за чего общие и локальные требования смешались. Эту проблему решили с помощью трехуровневой иерархии:

  • common — универсальные корпоративные стандарты компании вроде правил списания рабочего времени.
  • team — специфические требования конкретного отдела, например стандарт оформления merge request.
  • local — персональные настройки и предпочтения отдельного программиста.

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

Что изменилось после автоматизации

Полноценных замеров мы не вели: таймеров на переключения не вешали и клики не считали. Но собрали наблюдения по конкретным процессам, которые наглядно показывают разницу в затратах времени и усилий.

  • Закрытие задачи (цепочка в трех системах): было около десяти переключений и 15–20 минут работы, стало — одна фраза, около пяти минут и подтверждение двух шагов человеком.
  • Дежурство по ошибкам: время сократилось с 50–60 минут до 10–15 минут.
  • Вопрос из чата про баг: раньше требовалось вручную доносить весь контекст — копировать тред, задачу из трекера, приносить всё в модель и объяснять задачу. Теперь достаточно указать, в какой группе идет обсуждение и какая задача с ним связана, а остальное агент соберет сам.
  • Онбординг: раньше первый мерж происходил на третий день, теперь — по регламенту в первый день. Новый сотрудник может не искать коллегу, который объяснит процесс мержа, а попросить агента выполнить его по регламенту и посмотреть, какие шаги тот проходит.
  • Рутина в день: сократилась с 2–3 часов до часа и менее.

Общий стандарт, который не совпадает с реальной работой команды, неизменно начинает мешать и вызывает поток правок в духе «мы тут поправили под себя». Непроверенные скрипты ломали архитектуру, разработчики добавляли множество собственных решений, и система становилась нестабильной. Пришлось закрыть это жесткими тестами — pre-commit и pre-push, которые проверяют целостность архитектуры и прогоняют скрипты. Кроме того, инструкция далеко не всегда описывает всё, что человек держит в голове. Когда негласные правила приходится записывать для агента, выясняется, что половина из них никогда ранее не была сформулирована. Из-за этого инструкции приходится дописывать постфактум, после реальных ошибок агента.

Что нужно, чтобы собрать такой слой у себя

Чтобы развернуть аналогичную систему, потребуются три базовых компонента. Первый — любая агентная среда, в которой комфортно работать. Слой инструкций не привязан к конкретной модели, а средой может выступать Claude Code, Codex или OpenCode. Однако модели необходимо откуда-то вызывать, и на подобных проектах удобно иметь единую точку доступа. В данном случае используется платформа Caila от Just AI, через которую идут обращения к трем с лишним сотням моделей. Это удобно благодаря трем факторам: единый base_url и один ключ на все модели, возможность оперативно сменить модель под конкретную задачу без переписывания обвязки, а также прозрачные расходы с детальной разбивкой по моделям и запросам.

Второй компонент — MCP-серверы к используемым системам. Разрабатывать их с нуля совершенно не обязательно: можно взять готовый скилл-генератор и простыми словами описать необходимые операции. Третий компонент — инструкции в виде обычного текста, хранящиеся прямо в репозитории. Сами текстовые инструкции тоже можно частично генерировать с помощью отдельного скилла, который знает внутреннюю архитектуру и раскладывает описанный процесс по слоям: что должно стать MCP-инструментом, что превратится в action, а что останется playbooks. Разработчик просто описывает процесс словами, изучает получившийся план и утверждает его.

Что касается распространения внутри компании, процесс устроен предельно просто: достаточно клонировать репозиторий и запустить setup-скрипт, который автоматически подключает MCP-серверы и запрашивает выпуск и ввод токенов. На текущий момент четыре команды разработки уже используют эту систему, активно дополняя ее собственными инструкциями и сценариями дежурств. Тестировщики также полностью перешли на этот подход, перенеся инструкции из отдельного стороннего инструмента.

Для тех, кто захочет повторить подобный подход у себя, подготовлен отдельный гайд. Он включает восемь файлов на примере реальной команды разработки — по одному на каждый слой архитектуры, с готовыми шаблонами действий, playbooks и настройками прав. Если вы уже собирали похожий слой на своем проекте, будет интересно сравнить решения — делитесь опытом в комментариях. А если хочется изучить другие сценарии применения LLM в разработке, заходите в профильный чат для разработчиков.

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

Источник: habr.com

Реклама
01.