JavaRush /Курсы /Claude code /Output contract агента

Output contract агента

Claude code
12 уровень , 3 лекция
Открыта

1. Фраза «проверь это» даёт мутный результат

Когда люди впервые начинают работать с агентами, рука сама тянется к коротким командам: «проверь diff», «посмотри тесты», легендарное «review this». Кажется, что умный агент сам всё поймёт. Разбирается он, к сожалению, не в том, что вам нужно, а в том, что проще выдать убедительным текстом.

Представьте типичную сцену в Commerce OS. Вы трогаете refund flow, где логика возвратов завязана на суммы, статусы заказа и ограничения по времени. Отдаёте reviewer-агенту: «проверь текущий diff». В ответ: «Код в целом выглядит нормально, возможно, стоит добавить пару тестов и проверить edge cases». Агент не глупый — вы не задали ему форму результата. Он не знает, возвращать ли замечания по severity, указывать ли file:line, отделять ли гипотезы от фактов, можно ли редактировать код и что делать, если diff накрыл половину модуля.

Посмотрите на разницу между двумя запросами:

Плохо:
Проверь этот diff.
Лучше:
Проверь текущий diff в auth и billing flows.
Код не редактируй.
Сфокусируйся на пропущенных тестах, совместимости API и крайних случаях.
Верни замечания по severity с file:line, evidence и предложенными проверками.
Если diff больше 500 строк — остановись и попроси разбить change.

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

Агент без output contract очень похож на коллегу, который на вопрос «ну как там ревью?» отвечает: «в целом нормально, но есть нюансы». Формально разговор состоялся, а пользы примерно как от прогноза погоды в стиле «где-то будет что-то среднее между солнцем и апокалипсисом».

2. Output contract против Session Handoff Note

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

Output contract — это договор о результате, который агент должен вернуть. Не о личности, не о «стиле работы», не о красивом тексте — именно о результате. Вы заранее решаете, что обязано быть в ответе, где доказательства, как помечается неопределённость, что считается нарушением границ и когда агент обязан остановиться.

Для сравнения удобно смотреть так:

Артефакт Главный вопрос Когда используется Что в нём главное
HANDOFF_NOTE.md / Session Handoff Note «Что происходит с задачей сейчас?» Когда вы передаёте работу другой сессии или человеку Текущее состояние, решения, открытые вопросы, следующий шаг
Output contract агента «Можно ли принять этот результат?» Когда subagent закончил свою роль и вернул output Формат результата, evidence, scope, uncertainty, stop conditions

Session Handoff Note вы уже встречали раньше — он нужен, чтобы не потерять контекст длинной задачи между сессиями. Output contract нужен для другого: посмотреть на результат reviewer- или tester-агента и сказать одно из трёх — «беру в работу», «вернись и уточни», «нарушены границы, не принимаю».

Это различие особенно полезно помнить в Workflow Kit. agents/reviewer.md и agents/tester.md — не просто файлы с ролью, а артефакты, обязанные возвращать результат в предсказуемом формате. Если reviewer пишет свободное эссе, а tester — «тесты добавлены», у вас не инженерный процесс, а литературный кружок с элементами shell-скриптов.

3. Из чего состоит хороший output contract

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

Вот удобная структура, которая тянет и reviewer, и tester, если подкрутить детали под роль:

Секция Зачем она нужна Что вы проверяете
summary Даёт короткую рамку результата Понял ли агент задачу и scope
findings Содержит замечания или предложения Есть ли у замечаний severity и привязка к коду
evidence Доказывает каждое важное утверждение Есть ли file:line, команда, лог, diff
tests/checks run Показывает, что реально запускалось Есть ли команды и exit codes, а не «вроде запускал»
uncertainty Отделяет факты от предположений Есть ли пометки [hypothesis]
changed files Показывает, нарушил ли агент границы роли Для reviewer — должно быть пусто
next step Делает результат применимым Понятно ли, что делать дальше
stop conditions Ограничивает вред при нештатной ситуации Остановился ли агент там, где должен

На практике это может выглядеть так:

## Формат вывода
- summary: 3–5 предложений, без воды
- findings: severity, file:line, evidence, recommendation
- tests/checks run: команда + exit code
- uncertainty: отдельный блок с [hypothesis]
- changed files: список или none
- next step: одно ясное действие для разработчика

Точные названия разделов и синтаксис agent file в текущей версии Claude Code могут отличаться — это нормально. Важно не поле summary само по себе, а принцип: результат устроен так, чтобы его можно было проверить, а не только прочитать.

Ещё один полезный способ смотреть на контракт — разделить поля на жёсткие и мягкие.

Тип поля Пример Чем хорош
Жёсткое orders/refund/RefundPolicy.java:87, ./gradlew test, exit code 1, changed files: none Его можно проверить почти механически
Мягкое severity: major, risk: regression in refund flow, recommendation: add integration test Требует человеческого суждения

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

4. Запрос агенту под контракт

Даже хороший контракт бесполезен, если вы ставите задачу в стиле «ну посмотри». Он срабатывает только тогда, когда запрос сам сформулирован как инженерное задание: границы, фокус, запрет на лишнее, ожидаемый формат.

С reviewer-агентом это видно особенно наглядно. Плохо:

Проверь код после моих изменений.

Нормально:

Проверь текущий diff по refund flow в Commerce OS.
Код не редактируй.
Сфокусируйся на regressions, пропущенных тестах и совместимости API.
Верни findings по severity с file:line, evidence и suggested checks.
Если diff больше 500 строк — остановись и попроси разбить change.

Почему это работает лучше? Потому что здесь зафиксированы сразу пять вещей. Во-первых, scope: refund flow, не весь проект. Во-вторых, границы роли: не редактировать код. В-третьих, фокус внимания: regressions, tests, API. В-четвёртых, формат результата: severity, file:line, evidence. В-пятых, условие остановки: diff слишком большой — не геройствовать.

С tester-агентом картина похожая, но акценты другие: ему мало просто сказать «проверь тесты» — лучше сформулировать запрос так, чтобы было понятно, что он пишет только тесты, а production-код не трогает.

Подготовь тестовое покрытие для текущего diff в auth flow.
Production-код не меняй.
Если нужны изменения, ограничься файлами в tests/**.
Верни список сценариев, команды запуска, exit codes и отмеченные [hypothesis].
Если падают больше пяти нерелевантных тестов — остановись и отчитайся.

Обратите внимание: хороший запрос почти всегда опирается на уже существующий output contract, даже не цитируя его целиком. Вы не изобретаете формат заново, а активируете заранее описанную роль. В этом и есть сила Workflow Kit: контракт живёт в agents/reviewer.md или agents/tester.md, а сессионная постановка лишь заземляет его в конкретный diff.

5. Приёмка или отклонение результата

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

Приёмка делегированной работы обычно сводится к трём решениям:

Решение Когда подходит Что делаете дальше
Принять Есть evidence, scope соблюдён, границы роли не нарушены, следующий шаг понятен Берёте findings в работу или фиксируете отсутствие проблем
Вернуть на уточнение Идея полезная, но не хватает доказательств, ясности или маркировки гипотез Просите переформатировать output по контракту
Отклонить Нет evidence, были неожиданные edits, нарушены stop conditions или границы роли Не используете результат и пересобираете задачу заново

Хороший reviewer-output в Commerce OS может выглядеть примерно так:

### находки
- major — orders/refund/RefundPolicy.java:87
  evidence: условие допускает amount == 0, а теста на нулевой refund нет
  recommendation: добавить regression test на zero-amount case

### прогнанные тесты/проверки
- ./gradlew test --tests RefundPolicyTest → exit code 0

### изменённые файлы
- none

Здесь почти всё на месте: severity, конкретная строка, evidence, рекомендация, команда, подтверждение, что reviewer ничего не менял. Такой результат можно принимать.

А вот пример, который стоит вернуть:

### находки
- Возможно, здесь есть проблемы с refund flow.
- Стоит ещё посмотреть тесты.
- В целом код выглядит рискованно.

Почему вернуть, а не сразу выбросить? Потому что, возможно, агент действительно что-то заметил, но не оформил результат по контракту. Нет file:line, нет evidence, нет severity, непонятно, что запускалось. В работу как есть — нельзя.

А если reviewer внезапно вернул changed files с production-кодом, хотя роль была read-only, — это уже повод не «уточнять», а отклонять результат как нарушение границ.

Наглядно весь процесс выглядит так:

flowchart TD
    A[Агент вернул результат] --> B{Есть evidence?}
    B -- нет --> C[Вернуть на уточнение или отклонить]
    B -- да --> D{Соблюдён scope и role boundaries?}
    D -- нет --> E[Отклонить]
    D -- да --> F{Гипотезы помечены явно?}
    F -- нет --> G[Вернуть на уточнение]
    F -- да --> H{Следующий шаг понятен?}
    H -- да --> I[Принять в работу]
    H -- нет --> G

Смысл этой схемы простой: вы принимаете не умное впечатление, а структурированный артефакт.

6. Гипотезы помечаем, а не прячем в уверенный тон

Одна из самых неприятных ловушек при работе с агентами — не явная ошибка, а неотмеченная неопределённость. Агент пишет очень уверенно, и только потом выясняется, что половина выводов была догадкой. Поэтому в контракте есть отдельный блок uncertainty, а гипотезы помечаются явно — маркером [hypothesis].

Плохой вариант выглядит так:

- major: refund flow ломается из-за stale cache в billing service

Проблема в том, что это звучит как установленный факт. А где доказательство — лог, трассировка вызова, тест? Может быть, агент просто увидел похожий паттерн и достроил картину.

Гораздо честнее так:

- [hypothesis] possible regression in refund flow
  evidence: прямого подтверждения в diff не найдено
  why suspect: billing cache читается до проверки refund status
  needed check: прогнать integration test на stale status

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

Особенно это важно для tester-агента. Он часто работает на стыке существующего тестового набора, новых сценариев и неполного знания о проекте. Если он не умеет честно сказать «здесь я предполагаю» — он начнёт закреплять свои догадки в тестах. А это уже тот редкий случай, когда автоматизация ломает систему не громко, а очень вежливо и документированно.

7. В Workflow Kit: reviewer и tester

Чтобы всё это не осталось на уровне абстракции, давайте заземлим тему в артефактах Workflow Kit — именно там контракт перестаёт быть красивой идеей и становится частью поддерживаемого файла agents/reviewer.md или agents/tester.md.

Для reviewer контракт может быть таким:

## Формат вывода
- summary: 3–5 предложений
- findings: severity, file:line, evidence, recommendation
- tests/checks run: команда + exit code
- uncertainty: помечать как [hypothesis]
- changed files: none
- next step: одно ясное действие

А для tester — немного иным:

## Формат вывода
- summary: какое поведение покрывается
- proposed tests: файл + сценарий
- commands run: команда + exit code
- changed files: только tests/**
- uncertainty: помечать как [hypothesis]
- stop conditions: при массовых нерелевантных падениях остановиться

Разница между ними не косметическая. Reviewer по роли должен остаться read-only, поэтому changed files у него обязаны быть пустыми. Tester может менять тестовые файлы, но именно тестовые, а не production-логику. Иначе получится классический сюжет: «агент починил тесты», переписав поведение системы под тест, а не наоборот.

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

Точные имена разделов, поля frontmatter и формат agent file могут меняться от версии к версии Claude Code — это не страшно. Страшно другое: когда у агента нет явного договора о результате, а значит, нет и нормальной инженерной приёмки. Когда reviewer и tester возвращают одинаково устроенный, читаемый, проверяемый output, вопрос «можно ли это принять» решается по полям контракта, а не по тому, насколько уверенно написан ответ. Договор о результате — это то, что превращает делегирование из ставки на удачу в предсказуемую операцию с чёткой приёмкой.

1
Задача
Claude code, 12 уровень, 3 лекция
Недоступна
Явный output contract для reviewer
Явный output contract для reviewer
1
Задача
Claude code, 12 уровень, 3 лекция
Недоступна
Структурированный review через read-only субагента reviewer
Структурированный review через read-only субагента reviewer
Комментарии
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ