
Всем привет!
Меня зовут Дмитрий Бутенко, я эксперт-разработчик банка Уралсиб.
Всё началось с рабочего созвона в первой половине февраля, на котором упомянули возможность применять модели ИИ прямо внутри инфраструктуры банка. Поначалу речь шла о работе через JetBrains AI Assistant — точечные запросы, ревью, вопросы по проекту. Вопросов, кстати, было много. Но довольно скоро случился переход на OpenCode, и это открыло принципиально другой уровень: не отдельные запросы к модели, а полноценные агенты, которые сами читают файлы, вносят изменения, итерируются по результату.
О том, какими были эти вопросы и задачи, и о том, что из этого вышло — речь пойдёт ниже.
Два важных уточнения:
-
Этот текст — о пользовательском опыте применения конкретных инструментов для конкретных задач. Вопрос о целесообразности выбора именно этих инструментов остаётся за рамками;
-
Инструменты преднастроены — системные промпты, команды, субагенты. Это влияет на результат, но насколько сильно — отдельная тема, в тексте не рассматривается.
Стек
OpenCode версии 1.2.19 на момент написания
-
Модели: gpt-oss:120b и qwen3.5-27b-claude-4.6-Opus
-
MCP-интеграции: Confluence, GitLab, Jira, TestIT
-
Языки программирования на проектах и фреймворки: Scala/Java/Play framework, PHP/Laravel, PHP/Symfony
Инициализация проекта
Первое, с чем пришлось столкнуться — инициализация проекта командой /init-project. Кастомная команда инициализации, аналог «стандартной» /init, которая создает md-файл в корне проекта с его описанием и освновными деталями. На scala-проекте поведение оказалось неожиданным: при первом запуске модель полностью игнорировала весь scala/java-код, если на это явно не указать вторым сообщением. Со временем и после нескольких обновлений проблема была устранена. PHP-проекты инициализировались без серьёзных затруднений, хотя здесь обнаружился другой нюанс: после анализа проекта модель иногда предлагала создать markdown-файл и зафиксировать изменения, но не показывала, какие именно. Содержимое приходилось запрашивать отдельно.
CRUD на Scala: две модели, разное поведение
На задаче создания нового маршрута со связанными контроллером и middleware обе модели справились, но по-разному.
Примеры промтов:
-
Добавь новый маршрут в файл conf/routes: /v1/packet/:packet_code/options, название метода и контроллер OptionsController.getOptionsByPacketCode, параметры (packet_code: String, promo_code: String). Добавь класс контроллера в src\app\smart\controllers, класс опиши по аналогии с контроллерами рядом;
-
В методе getOptionsByPacketCode контроллера app\smart\controllers\OptionsController добавь следующее: описание бизнес-логики действия.
qwen3.5-27b-claude-4.6-Opus следовал структуре, которая уже была в проекте, и при реализации похожих паттернов требовал меньше уточнений — прослеживалось понимание сложившейся архитектуры.
gpt-oss:120b с задачей тоже справился, но потребовал больше направляющих уточнений. На некоторых задачах с постановкой вида «реализуй новый роут с определенными параметрами» модель рисковала надолго уйти в раздумья — если явно не указать, где находится файл настроек роутов, какой контроллер создать и какие middleware подключить.
Отдельно выделяется задача, которая не поддалась ни одной из моделей: генерация класса на основе java.net.http.HttpClient для отправки формы с multipart/form-data. Несмотря на корректную последовательность вызовов, модели не справились с корректным расчётом размера тела запроса и корректное добавление boundary — код не работал, и никакие итерации его не спасли. В итоге этот фрагмент пришлось переписывать вручную.
Исправление ошибок
Для простых ошибок вроде NPE с полным стек-трейсом или четким упоминанием класса как правило проблем не возникает.
Пример: объясни, с чем может быть связана ошибка и напиши, как можно исправить [вставлен стек-трейс]
Однако, поиск ошибок мог не приводить к результату, если ошибки были связаны с внешними компонентами, а обращения к этим компонентам встречаются в нескольких местах в проекте. Например, ошибки при запросах в БД. Нужно было дополнительно добавлять возможные обстоятельства, из-за чего могла произойти ошибка. Или уточнять у модели, можно ли что-то логировать дополнительно, что позволит локализовать проблему.

Изменение поведения API на Laravel: модель делает больше, чем нужно
Задача была такая: упростить алгоритм, который добавляет в архив файлы документов и их подписанные копии, полученные из внешнего сервиса. Оригиналы и подписанные файлы располагались в разных каталогах, при этом пути подписанных документов зависели от путей оригиналов. Суть упрощения: перестать учитывать эту зависимость и просто класть подписанные файлы в свой каталог как есть. Итог — три метода, два цикла, никаких архитектурных изменений.
Представить задачу можно следующим псевдокодом (строки, которые необходимо изменить, отмечены жирным)
zip = new Zip("/path/file.zip");for (doc: documents) { zip->add(getFilePathByDocument(doc), doc->getData())}for (i = 0; i < signedDocuments.lenght; i++) { signedDoc = signedDocuments[i] doc = documents[i] zip->add(getFilePathBySignedDocument(doc, signedDoc), signedDoc->getData())}zip->save()
Модель, как бы ни формулировали промпт, неизменно трогала что-то за пределами обозначенных рамок. Повторные уточнения только усугубляли ситуацию: одни изменения откатывались, но появлялись другие. В какой-то момент модель изменила поведение приватного метода в сервисе и самостоятельно пошла искать по проекту, где ещё он вызывается — чтобы убрать «ненужный» вызов. Всё это раз за разом либо ломало тесты, либо проявлялось во время работы приложения.
Добавление вызовов API на Symfony: аккуратно, но с оговорками
На symfony-проекте обе модели в целом справлялись с задачами по добавлению новых вызовов — вероятно, во многом благодаря более чёткой структуре проекта: разделение на слои, соответствие определенному поведению у классов в одном пространстве имен, строгие соглашения по именованию. Возможно, при повторяющейся структуре модели проще генерировать код, соответствующий уже неоднократно реализованному шаблону. Тем не менее в деталях ошибки случались: например, в аннотациях к модели, описывающих ограничения на свойства (допустимые типы, тип в БД, правила валидации). Как правило, это исправлялось дополнительным промптом, но не снимало необходимости более тщательно просматривать все внесённые изменения.
Dockerfile и Docker Compose: каркас есть, на этом все
Оба инструмента генерировали файлы, похожие на правду. Но в корпоративной среде с настройками проксирования и собственными зеркалами репозиториев результат оказывался непригоден к прямому использованию. Реальная ценность здесь — каркас, от которого можно оттолкнуться, понимая, что доработка вручную всё равно потребуется. Однако, если есть несколько проектов с похожим стеком технологий, то проще взять за основу файлы из соседнего проекта.
Отдельно стоит отметить: при уточняющих вопросах о конкретном образе для одного из stage модель могла неверно интерпретировать запрос. Помогал более детальный вопрос с самого начала.
Исправление падающего теста на Laravel: модель меняет тест вместо кода
Для нетривиального теста — получение всех документов клиента в одном архиве — модель нашла часть проблем, связанных с изменившимися сигнатурами методов. Тест действительно нетривиальный: из-за связности существующих классов пришлось много мокать и создавать тестовые реализации интерфейсов.
Несмотря на это, до конца модель задачу не решила. Примечательно другое: тесты проверяли ожидаемое количество файлов в архиве, и модель решила изменить сам тест, а не тестируемую функциональность — и продолжала это делать до тех пор, пока в промпте явно не запретили трогать файлы тестов.
Помощник
Очень хорошо модели показали себя в режиме «планирования»: модель работает в режиме только на чтение, как правило анализируя проект и отвечая на вопросы по нему, или на какие-то более общие вещи. Например, объяснение синтаксических конструкций, scala в моем случае, вывод связей классов в приложении, примеры использования архитектурных паттернов с привязкой к фреймворку и т.д. Разработчику, который не знаком с какими-то особенностями проекта это существенно снизит время на онбординг в проект.
Недостатки самого инструмента
Несколько слов об использовании OpenCode в Windows. При запуске в PowerShell или CMD недоступна вставка из буфера обмена. В MSYS2 OpenCode не запускается вовсе, поэтому единственным рабочим вариантом остаётся терминал внутри IDE — который приходится откреплять в отдельное окно. Вставка медиаконтента в промпт не работает, распознавание изображений тоже недоступно. И иногда появляются артефакты, похожие на те, что на изображении ниже.
Итоги
Модели уверенно справляются с рутинными задачами: создание новых эндпоинтов, генерация миграций, описание моделей по бизнес-требованиям. По мере усложнения задачи растёт и необходимое описание желаемого результата — и вот здесь начинаются проблемы. Модель может уйти в ложном направлении или изменить больше кода, чем нужно. В итоге время тратится не на решение, а на исправление результата уточняющими промптами или откатами с повтором. Буквально приходится подводить модель к решению: сначала обозначить рамки, потом требования, потом общий алгоритм. Иногда проще решить задачу самостоятельно, чем всё это расписывать.
Зато роль помощника модель отыгрывает хорошо. В тех ситуациях, когда решение частично понятно и нужно уточнить какие-то детали или описать гипотезы в общих чертах модель сильно экономят время.
Собрав собственные кейсы, стало интересно, каким возможным опытом делились коллеги из других компаний. И буквально здесь же нашлась пара похожих примеров: один и два. Из чего-то более масштабного с более формализованной методологией есть исследование IBM Research на 669 сотрудниках: наиболее стабильный прирост от AI-ассистента дают задачи на понимание чужого кода.
Наблюдается один и тот же паттерн: локальные модели берут рутину, помогают разобраться в незнакомом коде и служат удобным собеседником для проектирования. Сложные многошаговые задачи с размытыми границами — если для «сервисных» моделей обычная задача, то для локальных пока зона риска, которую можно с разной степенью эффективности закрывать сменой модели, системных промптов, дополнительным обогащением, через, например, RAG.
ссылка на оригинал статьи https://habr.com/ru/articles/1053432/