Егор Урванов

Harness engineering на практикеКак превращать ошибки ИИ-агента в правила окружения (HDD)

Как превращать ошибки ИИ-агента (Claude Code, Codex) в правила его окружения: петля «ошибка → правило», направляющие и датчики, три слоя проверок, связь со спеками и пять первых шагов в своём проекте.

Harness engineering (харнесс-инжиниринг) — настройка среды вокруг ИИ-агента: инструкций, инструментов, прав и проверок. Harness-Driven Development (HDD) — рабочий метод на его основе: каждая ошибка агента становится правилом этой среды.

Петля HDD

Петля работает так. Агент получает задачу и делает результат. Датчики (тест, линтер, ревью) проверяют результат. Если всё прошло, задача закрыта. Если датчик нашёл ошибку, человек не просто исправляет результат, а меняет окружение агента, то есть харнесс: дописывает строку в инструкцию, добавляет тест или хук. Следующая задача идёт уже с этим правилом, и такая ошибка не повторяется.

Задача → агент → результат → датчики → ошибка → правило в харнессе → следующая задачахарнессЗадачаАгентРезультатДатчикиНовое правилоинструкция · тест · хукделаетпроверитьпрошлоошибкабольше не повторится

Принцип Митчелла Хашимото: если агент ошибся, харнесс меняют так, чтобы эта ошибка не повторилась Faros

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

ОДНА ОШИБКА · агент правит код и не запускает тестыЧТО МЕНЯЕМКАК ЧИНИМГДЕ ЖИВЁТ ИСПРАВЛЕНИЕЗАПУСК АГЕНТА1234① Промптслова запросаДописать в запрос:«запусти тесты после правки»Только в этом запросе:следующий запрос начнётся заново✓✗✗✗② Контекстчто знает модельЗаписать в инструкцию проекта:«после правки запускай тесты»В файле инструкций: модель читает,но выполнять не обязана✓✓~✓③ Харнесссреда вокруг агентаПоставить хук: тесты запускаютсясами после каждой правкиВ среде: выполняется без участиямодели и блокирует результат при сбое✓✓✓✓✓ тесты запущены · ~ модель может пропустить · ✗ забыто

Этапы по Faros и marmelab

Таблица показывает одну и ту же ошибку (агент правит код и не запускает тесты) и три способа её исправить. Промпт: дописать «запусти тесты после правки». Это действует только для одного запроса, следующий начнётся заново. Контекст: записать то же в файл инструкций проекта. Модель это читает, но может пропустить. Харнесс: поставить хук, который сам запускает тесты после каждой правки. Он выполняется без участия модели, поэтому исправление держится во всех следующих запусках.

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

Устройство харнесса: 3 × 3

Три домена контура и три контекста в каждом — девять канонов. У каждого канона ровно один домен и один контекст.

→скилл → спека своего домена·направление проверяет скрипт на коммит
snapshotтаблица, обновляется по факту нового измерения
liveпротокол, каждый раз заново, без хранения

Матрицу удобно читать как три вопроса. Ожидание: каким должен быть результат (например, «после правки тесты проходят»). Наблюдение: каким он получился на самом деле, это записывает датчик. Луп: сравнивает одно с другим и решает, что делать. В каждой из трёх строк есть три вида опоры: спека (что должно быть верно), скилл (как действовать) и память (на что опереться). Слова «домен» и «канон» здесь только названия: домен — строка матрицы, канон — одна клетка, например спека Ожидания. Нижняя схема показывает направление связей: Ожидание и Наблюдение подаются на вход Лупа, а он выдаёт либо патч (поправить действие), либо пересмотр правил. Обратной ссылки на Луп нет, поэтому домены не запутываются друг в друге. Режимы памяти: snapshot — таблица, которая обновляется при новом измерении; live — данные берут из живой системы (например, через MCP) каждый раз заново и не хранят.

Вывод
В этом примереКонтур раскладывается на Ожидание, Наблюдение и Луп, у каждого свои спека, скилл и память. Луп читает два других домена, они Луп не читают.
В общем случаеЭто контур отрицательной обратной связи: заданное значение сравнивается с измеренным, и меняется что-то только при расхождении. Жёсткое направление ссылок не даёт доменам запутаться друг в друге, а повтор одного понятия в двух доменах дефектом не считается.
Что сделатьРазложите файлы своего харнесса по девяти клеткам и проверьте, что ни один файл Ожидания или Наблюдения не ссылается на Луп.

Двойная петля

Двойная петля отвечает на вопрос, что именно менять после ошибки. Возьмём ту же ошибку: агент не запустил тесты. В одинарной петле вы напоминаете агенту, он запускает тесты, а правила остаются прежними. В двойной вы спрашиваете, какое правило допустило ошибку, и меняете его: теперь тесты запускает хук после каждой правки. Идея пришла из теории обучения организаций (Крис Аргирис и Дональд Шён): одинарная петля исправляет действие, двойная пересматривает правила, из которых действие вытекало. Википедия: Double-loop learning.

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

Луп применяется и к себе: каждый прогон заканчивается остаточным риском, статус «готово» он не ставит.

Менять правила после каждой жалобы опасно: харнесс начнёт расползаться от случайных правок. Поэтому Луп применяет четыре проверки. Если поправки лишь затыкают дыры и ничего нового не предсказывают, их заменяют одним правилом. Если жалоб несколько, сначала проверяют тестом, есть ли у них общая причина. Новое правило принимают, только если с ним старые случаи по-прежнему объясняются. Правило без внешней проверки отбрасывают, но записывают, что и почему отброшено. Подпись под карточками значит, что Луп применяется и к самому себе: прогон не ставит «готово», а заканчивается указанием остаточного риска.

Вывод
В этом примереСерия подгонок, жалобы, новое правило и внешняя проверка — четыре проверяемых принципа, по которым Луп решает, чинить действие или менять правила.
В общем случаеОдинарная петля исправляет результат в рамках старых правил. Двойная меняет сами правила, и делает это по проверяемым принципам: так харнесс учится, но не расползается от случайных правок.
Что сделатьКогда одна и та же правка повторяется третий раз, остановитесь и спросите, какое правило её вызывает. Меняйте правило, только если оно объясняет и старые случаи.

Направляющие и датчики

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

Деление по Martin Fowler: Harness engineering

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

Три слоя проверок

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

Зрелость слоёв по Martin Fowler

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

Раньше — дешевле

Любая проверка срабатывает в какой-то момент, и чем раньше, тем дешевле исправить ошибку. На схеме четыре момента: до работы агента (инструкции и спеки), при записи файла (хуки и линтер), в CI (автоматическая сборка и тесты при отправке кода в репозиторий) и на ревью человеком. Значки $ показывают растущую цену ошибки.

Тесты запускают движки вроде QUnit, Jest и Vitest. Чем они отличаются и когда какой брать, разобрано в статье Vitest или Jest: что выбрать для JavaScript-проекта и когда хватит QUnit. Правила поведения, которые обычными тестами не проверить, ищет модель на Quint.

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

Где нужен человек

Харнесс берёт на себя рутинные проверки: стиль, типы, тесты, границы модулей. Человек решает то, что формальной проверкой не закрыть: архитектуру, продуктовые вопросы и новые правила. Цифры на схеме показывают пример соотношения: 36 проверок у харнесса и 6 у человека.

«Хороший харнесс оставляет человека в контуре и направляет его внимание туда, где оно важнее всего» — пересказ Martin Fowler

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

HDD и спеки

Спека и харнесс дополняют друг друга. Спека отвечает на вопрос «что должно получиться», харнесс проверяет, что получилось именно это. На схеме спека задаёт нужный результат, харнесс проверяет его, и код принимают по результатам проверок, а не чтением каждой строки.

«Спеки задают целевое состояние, харнесс — систему контроля» — Loiane Groner. Про спеки — доклад Spec-Driven Development на практике

Вывод
В этом примереСпека отвечает на вопрос «что строим», харнесс — «как убедиться, что построили».
В общем случаеБез спеки харнессу нечего проверять, без харнесса спека остаётся документом. Вместе они позволяют принимать код агента по проверкам, а не по чтению каждой строки.
Что сделатьДля каждого требования из спеки запишите, какой тест или проверка подтвердит его выполнение.

С чего начать

Харнесс не нужно проектировать целиком. Начните с пяти шагов: два первых настраивают окружение сразу, три остальных запускают петлю «ошибка → правило». Файл прогресса нужен, когда задача длиннее одной сессии: в нём список фич со статусом, и новая сессия агента продолжает с того же места.

  1. 1
    Файл инструкций для агента
    AGENTS.md или CLAUDE.md в корне проекта: как собирать, как тестировать, что нельзя
  2. 2
    Линтер и тесты после каждой правки
    хук, который агент запускает сам, до того как отдать результат
  3. 3
    Журнал ошибок агента
    каждая исправленная вручную ошибка — строка с причиной
  4. 4
    Ошибка → правило
    раз в неделю перенести записи журнала в инструкции, тесты или хуки
  5. 5
    Файл прогресса для долгих задач
    список фич со статусом и история коммитов, чтобы новая сессия продолжила с того же места Anthropic
Вывод
В этом примереПять шагов: два настраивают харнесс сразу, три запускают петлю «ошибка → правило».
В общем случаеХарнесс не проектируют целиком заранее. Он растёт из реальных ошибок агента в вашем проекте, и через несколько недель агент перестаёт повторять самые частые из них.
Что сделатьСегодня создайте файл инструкций и журнал ошибок. Через неделю перенесите первые записи журнала в правила.
Термины и деление на слои — по источникам, ссылки на них стоят в подписях под схемами.
© 2026 Егор Урванов