К этапу с CTO. Свои проекты называть «pet-проект с бэкендом, ботами и пайплайном обработки медиа», без деталей. Их контекст: React SPA, Webpack 5 с Module Federation, Zustand и TanStack Query, своя дизайн-система, 20–30% legacy на JSX, Java-бэк, API-first со Swagger, Sentry, Strapi, релизы по четвергам, нет лида и ревью, внутренние модели слабые, внешние разрешены только для инкапсулированных задач.
Harness — это всё, что стоит вокруг модели: правила, чек-листы, хуки, инструменты, права, тесты, память и метрики. Семь из восьми слоёв не зависят от того, какая модель внутри, поэтому ускорение команде даёт harness, а не выбор модели. А защита от утечек строится так, что секрет физически не может попасть в контекст внешней модели: вопрос не в доверии модели, а в том, что утекать нечему.
Это одна страница, которую агент видит в начале каждой сессии, а человек читает при онбординге. В других командах такие вещи держит в голове лид: на чём пишем, что запрещено, как оформляем. У них лида нет и ревью нет, поэтому правила обязаны существовать текстом, иначе каждый агент и каждый новый человек будет писать «как рядом», а рядом лежит legacy на JSX.
Для их витрины в этот файл ложатся пять вещей. Новый код только на TypeScript, legacy на JSX не плодить. Интерфейс собирается только из компонентов дизайн-системы, сторонние пакеты не тянуть, потому что после 2022 года они всё равно не пройдут в прод. Типы генерируются из Swagger по API-first, руками контракт не описывать. Секреты, внутренние хосты и названия внутренних сервисов не попадают ни в код, ни в промпты. И чек-лист релиза четверга, который заменяет второго человека там, где ревью нет.
Скилл — это записанный алгоритм задачи, которая повторяется. Агент получает его вместо того, чтобы каждый раз придумывать порядок действий заново. Импровизация всегда хуже готового чек-листа, потому что чек-лист уже содержит грабли, на которые кто-то наступал.
У них двенадцать-пятнадцать продуктов на одних «рельсах» и постоянное «допилить напильником», это и есть типовая работа. Первый скилл «добавить продукт на витрину»: контракт из Swagger, типы, стор, экраны из дизайн-системы, фиче-флаг, тесты, чек-лист релиза. Второй «перевести legacy-раздел с JSX на TS»: снять типы с контракта, включить strict по файлу, тесты до и после, ни одного any. Третий «разобрать ошибку из Sentry»: найти release и sourcemap, понять, какой микрофронт, воспроизвести, написать тест на регрессию, починить. Четвёртый «новый микрофронт»: shared-зависимости Module Federation, singleton для React и дизайн-системы, контрактный тест на версии. Знание Андрея, который ушёл в другую команду, превращается в текст, который исполняется одинаково у любого агента и любого человека.
Хук — это код, который срабатывает на событие: перед отправкой запроса модели, после правки файла, перед коммитом. Ключевое отличие от промпта: промпт модель может проигнорировать, хук нет. Для телекома это самый важный слой, потому что именно здесь живёт защита от утечек.
Перед отправкой контекста внешней модели хук прогоняет регулярные выражения по токенам, ключам, внутренним доменам и названиям сервисов, и если что-то совпало, запрос не уходит. После правки файла хук запускает линтер, tsc и проверку, что нет импортов вне дизайн-системы и нет новых JSX-файлов. На каждое сообщение хук по ключевым словам подсказывает нужный скилл. Перед коммитом gitleaks и тесты затронутого модуля.
Инструменты определяют, что агент физически может делать: читать файлы, запускать тесты, ходить в Jira. Правило простое: у внутреннего агента инструменты минимальные и по задаче, у внешней модели инструментов с доступом внутрь нет вообще.
Внутреннему агенту в их проекте нужны генератор типов из Swagger, тест-раннер, tsc и линтер, а также Jira, Confluence и Sentry только на чтение через MCP. Внешняя модель получает файловую песочницу и тест-раннер, и ничего больше: ни сети в периметр, ни базы, ни VPN. Даже если модель «захочет» сходить внутрь, у неё нет чем.
Каждый агент работает в своём git worktree или контейнере, в своей ветке по GitFlow. Деструктивные операции только с подтверждением. Два агента никогда не работают в одной рабочей копии: это конфликт HEAD и случайный захват чужих файлов, я на это наступал. Внешние модели работают в чистой папке, где нет .env, внутренних пакетов и git-истории. Крон-агенты бегут в контейнере с whitelist из одного-двух инструментов.
Это то, как агент узнаёт, что сделал не то. Без этого слоя агент оптимизирует «выглядит правильно». Основа: тест пишется до кода и становится тем, что агент обязан сделать зелёным. Дальше tsc и линтер после каждой правки, а не в конце. Для их микрофронтов отдельно нужен контрактный тест на shared-зависимости Module Federation, чтобы версии React и дизайн-системы совпадали у всех. Для интерфейса скриншот через headless-браузер и сравнение, а не «должно работать».
И одно правило, которое я вынес из инцидента: интеграция считается покрытой только тестом, который реально пересекает границу, то есть зовёт настоящий API или бутит фреймворк. Зелёные unit-тесты по обе стороны моста не доказывают, что мост работает.
Память — это файлы решений, которые агент читает между сессиями: почему Zustand, а не Redux, какой формат ошибок в интерцепторе, какие грабли у Strapi, почему нельзя тянуть пакет X. Один файл на одно решение, с полями «что», «почему» и «как применять». Пишется сразу после инцидента, а не «когда будет время». В сессию грузится только индекс, тела файлов по запросу, поэтому по токенам это дёшево.
Для них это особенно ценно, потому что Андрей сам сказал: истина в коде, а вики аналитиков расходится с продуктом. Память агента и есть недостающая документация, которая обновляется по факту, а не по расписанию.
CTO хочет ускорить команду. Без цифр нельзя показать, что ускорили. Поэтому каждый прогон агента пишет лог: какие инструменты вызвал, что изменил, сколько стоило, и шлёт алерт при сбое. А процесс измеряется метриками до и после: время от тикета до мержа, доля PR, вернувшихся на доработку, инциденты после четверга, часы, потраченные на ревью. Токены здесь не метрика, метрика это время до результата и переделки.
Принцип один: секрет никогда не должен оказаться в контексте модели, потому что всё, что попало в контекст, может уйти в лог, в кэш или в ответ. Защита строится не обещанием разработчика быть внимательным, а архитектурой, в которой утечке неоткуда взяться. Путь задачи выглядит так:
Токены и ключи живут в переменных окружения и в хранилище секретов, например Vault или CI secrets. Агент запускается в окружении, где нужных переменных нет, если они не нужны его задаче. Код читает значение через process.env, а сам агент значения не видит. В pre-commit и в CI стоит gitleaks: секрет в коде не проходит.
Каждая задача попадает в одну из трёх зон, и зона определяет, какой модели её можно отдать.
| Зона | Что в ней | Кому можно |
|---|---|---|
| Красная | Бизнес-логика продуктов, внутренние API, креды, данные клиентов, интеграции с партнёрами | Только внутренняя модель или человек |
| Жёлтая | Код без доменных названий: компонент, стор, хук, тесты, типы по обезличенному контракту | Внешняя модель после обезличивания |
| Зелёная | Чистые функции, алгоритмы, конфиги сборки, вопросы «как работает X» | Внешняя модель свободно |
Обезличивание значит сформулировать задачу как изолированный модуль: «таблица с фильтрами по такому-то интерфейсу», а не «экран скоринга партнёрского банка». Названия продуктов и партнёров заменяются нейтральными, и это делает разработчик до того, как задача ушла наружу.
Даже обезличенную задачу перед отправкой внешней модели проверяет программа: регулярные выражения по форматам токенов и ключей, по внутренним доменам и IP, по названиям внутренних сервисов и продуктов. Если что-то совпало, запрос не уходит, а разработчик видит, что именно сработало. Это детерминированный код без единого токена, покрыт тестами, список паттернов лежит в репозитории и пополняется после каждого инцидента.
Внешняя модель получает только файловую песочницу и тест-раннер. Ни сети в периметр, ни базы, ни Jira, ни VPN. Это же защищает от prompt injection: даже если в данных, которые модель читает, спрятана инструкция «сходи туда-то», ей нечем это сделать.
Агент, который ходит в Jira или Sentry, получает отдельный сервисный токен только на чтение, с ограниченным сроком и своим именем, чтобы в логах было видно, что делал именно он. Токен выдаётся окружением при запуске и в файлы проекта не попадает. Ротация по расписанию. Личный токен разработчика агенту не даётся никогда.
Всё, что уходит за пределы песочницы, то есть коммит в общую ветку, комментарий в Jira, публикация или деплой, проходит через явный approve. Агент готовит, человек нажимает. Критичное, вроде доступов, денег и миграций, человек читает сам, а не по сводке агента.
Каждый вызов внешней модели логируется: кто, какая задача, какие файлы были в контексте, сколько стоило. Раз в неделю выборочная проверка логов тем же фильтром. Если что-то нашли, это новый паттерн в фильтр и тест на него.