Свой ИИ‑агент по спецификации: пошагово от цели до прода. claude code.. claude code. DevOps.. claude code. DevOps. IT-стандарты.. claude code. DevOps. IT-стандарты. llm.. claude code. DevOps. IT-стандарты. llm. mcp.. claude code. DevOps. IT-стандарты. llm. mcp. Open source.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем. ии-агенты.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем. ии-агенты. промпт-инжиниринг.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем. ии-агенты. промпт-инжиниринг. ревью кода.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем. ии-агенты. промпт-инжиниринг. ревью кода. скилы.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем. ии-агенты. промпт-инжиниринг. ревью кода. скилы. субагенты.. claude code. DevOps. IT-стандарты. llm. mcp. Open source. Spec Kit. Spec-Driven Development. Анализ и проектирование систем. ии-агенты. промпт-инжиниринг. ревью кода. скилы. субагенты. Управление разработкой.

Агента сегодня можно собрать за вечер: длинный промпт, пара инструментов — и он что‑то делает. Сложности начинаются потом: поведение нельзя проверить, любая правка промпта что‑то ломает, а на вопрос «почему он так сделал?» ответа нет.

В этой статье разберём, как спроектировать агента как инженерный объект: со спецификацией, тестами, ограничениями и метриками. Подход собран из Spec‑Driven Development (SDD), моделей зрелости и автономности агентов и практики команд, которые уже внедряли агентов в разработку.

Для кого: разработчики и тимлиды, которые уже работают с Claude Code, Cursor или другим агентом и хотят сделать своего — для конкретной задачи команды.

Сквозной пример: агент‑ревьюер, который проверяет pull request на соответствие спецификации фичи (spec.md) и оставляет отчёт. Он полезен сам по себе, и на нём хорошо видны все слои: чтение данных, действия с последствиями, эскалация к человеку. Примеры файлов даны в формате Claude Code, но подход переносится на любой инструмент.

Что получится в конце: шесть файлов‑артефактов (конституция, спека агента, скилы, эталонные примеры, правила доступа, метрики).

Содержание

Сначала поищите готовое

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

Где искать — от надёжного к шумному:

  1. Официальные каталоги вашего инструмента. Для Claude Code — маркетплейсы плагинов (/plugin) и anthropics/skills.

  2. Поиск по коду GitHub по структуре файлов. У агентов и скилов стандартные пути, поэтому так точнее, чем по описанию: path:.claude/agents review, filename:SKILL.md "spec", path:.agents/skills, или из терминала gh search code "spec compliance" --filename SKILL.md.

  3. Сборники скилов — например, obra/superpowers, garrytan/gstack, addyosmani/agent‑skills. Полезны ещё и тем, что видно, как работа делится между агентами.

  4. Awesome‑списки и статьи — только как источник кандидатов: их часто пишут авторы самих инструментов.

Как отбирать:

Признак

Хорошо

Плохо

Активность

Коммиты за последние 1–3 месяца

Год без изменений

Лицензия

MIT, Apache-2.0

Нет лицензии или ограничения (Commons Clause)

Цель

Одна узкая задача, понятный формат вывода

«Делает всё»

Права

Инструменты ограничены, чтение отделено от действий

Полный доступ, git push и деплой внутри

Проверяемость

Есть тесты или evals самого скила

Только README

Установка

Файлы внутри проекта

Глобальная установка, git‑хуки, демоны, curl | bash

Звёзды — слабый сигнал: среди популярных репозиториев много списков и маркетинга.

Как применять. Чужой скил — это инструкция, которую агент выполнит с вашими правами, то есть по сути код. Прочитайте его целиком, скопируйте в репозиторий и подгоните под свои правила. Проверьте на 10–20 своих примерах и зафиксируйте версию. Ограничители (запреты, лимиты, журнал) почти всегда придётся добавить самостоятельно — как это сделать, описано в шаге 5.

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

Почему агенты ломаются

Большинство самодельных агентов — это промпт, которому дали инструменты. У него нет записанной цели, границ и способа проверить результат. Такое называют agent‑washing: чат‑бот или генератор текста выдают за агента.

Хороший фильтр — пять критериев «настоящего» агента. Их удобно использовать как техническое задание: каждый критерий дальше закрывается конкретным файлом.

Критерий

Чем закрываем

Шаг

Есть явная спецификация задачи и границ действий, а не просто system prompt

agent-spec.md, спецификации скилов

1, 3

Критерии успеха отделены от агента и проверяемы кем‑то другим

Набор эталонных примеров и тесты

4

Есть путь эскалации при выходе за границы уверенности

Раздел «Эскалация» в спеке

3

Уровень автономности назван явно и подтверждён метриками

Уровень R0–R5 в спеке, метрики на запуске

1, 6

Результат воспроизводим и тестируем

Эталонные примеры, журнал действий

4, 5

Учебный пример того, что бывает без этих критериев, — инцидент Replit в июле 2 025 года. Во время объявленной пользователем «заморозки кода» агент удалил продовую базу, а затем неверно сообщил, что откат невозможен (AI Incident Database, № 1152). Запрет существовал только как текст, а единственной проверкой агента был сам агент.

Архитектура агента за один взгляд

Свой ИИ‑агент по спецификации: пошагово от цели до прода - 1

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

Шаг 1. Одна цель, режим и уровень автономности

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

Для нашего примера:

Цель. Для каждого требования FR/NFR из spec.md сказать, реализовано ли оно в PR, и найти поведение в коде, которого нет в спеке.

Дальше выбираем режим и уровень разрешений. Удобна шкала R0–R5 из whitepaper «AI‑Disrupt PDLC» (Сбер, v2.0, раздел 4.3): она описывает, что агенту можно делать в конкретной среде.

Уровень

Что разрешено

Когда применим

R0

Только чтение

Прод без проверенных evals

R1

Только предложения, решает человек

Критичные пути прода

R2

Действия в ветке с ревью PR

Стандартная разработка

R3

Автоматическое слияние при прохождении evals

Стандартизированные шаблоны

R4

Несколько сессий с контрольными точками

Долгие проверенные сценарии

R5

Полная автономия

Только изолированная песочница

Уровень задаётся не агенту целиком, а среде: один и тот же агент может быть R1 в проде, R3 в ветке и R5 в песочнице. Чем критичнее задача и выше риск, тем ниже уровень.

Новый агент стартует на R1–R2, даже если цель — R4. Каждую ступень нужно пройти и подтвердить метриками, а не задекларировать: «перепрыгивание уровней» — одна из самых частых ошибок внедрения.

Наш ревьюер работает в ассистирующем режиме на R1: он готовит отчёт, а решение о мерже принимает человек. Агент не может ни одобрить, ни отклонить PR.

Шаг 2. Конституция и три уровня промпта

Один длинный промпт, который правят целиком, — главный источник регрессий. Разделите его по тому, как часто меняется каждая часть:

Уровень

Что внутри

Как часто меняется

Где живёт

1. Конституция

Роль, границы, неприкосновенные правила

Редко, через код‑ревью

Тело описания агента

2. Контекст

Спека фичи, конституция проекта, дифф

На каждый запуск; подгружается, а не пишется руками

Файлы репозитория, MCP

3. Инструкция

Конкретная задача этого вызова

Каждый вызов

Запрос пользователя или CI

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

В Claude Code агента можно описать как сабагента — markdown‑файл с фронтматтером. Тело файла — это и есть конституция агента:

---
name: spec-reviewer
description: Checks a pull request against the feature spec (specs/<feature>/spec.md) and returns a compliance report. Use after implementation, before human review. Read-only.
tools: Read, Grep, Glob
model: sonnet
maxTurns: 20
---

# Роль
Ты — ревьюер соответствия спецификации. Ты не оцениваешь стиль и не предлагаешь рефакторинг.

# Входные данные
Вызывающий передаёт тебе два пути:
- SPEC — файл спецификации, например specs/010-pager/spec.md
- PACKAGE — пакет для ревью (коммиты + дифф), собранный scripts/review-package.sh
Если одного из путей нет или файл не читается — остановись и сообщи об этом.

# Границы
- Только чтение. Не меняй код, тесты и спеку.
- Не одобряй и не отклоняй PR — решение за человеком.
- Каждое утверждение подкрепляй ссылкой file:line из пакета.

# Как работать
1. Прочитай SPEC и выпиши все требования FR-xxx и NFR-xxx / SC-xxx.
2. Прочитай PACKAGE один раз.
3. Для каждого требования поставь статус: implemented / partial / not_implemented /
   needs_human (нельзя проверить по диффу).
4. Отдельно перечисли поведение в диффе, которого нет ни в одном требовании.
5. Найди не менее пяти конкретных расхождений или явно объясни, почему их нет.

# Эскалация
Верни только раздел «Эскалация» без статусов, если:
- в SPEC есть [NEEDS CLARIFICATION];
- дифф затрагивает больше 30 файлов.

# Формат ответа
## Статусы
| Требование | Статус | Где (file:line) | Комментарий |
## Незаявленное поведение
- file:line — что делает код
## Вопросы к автору
- ...

Обратите внимание на поле tools: ревьюер физически не получает инструментов записи. Запрет «не меняй код» дублируется не текстом, а настройкой — к этому принципу мы вернёмся в шаге 5.

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

Шаг 3. Спецификация агента и его скилов

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

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

Что проверяет ревьюер: spec.md фичи. Вот как такой файл выглядит в реальном проекте: pamburus/hl — просмотрщик логов на Rust (около 3,3 тыс. звёзд), фичи которого ведутся через Spec Kit. Ниже — дословные фрагменты specs/010-pager/spec.md (коммит fbfb7f6, MIT, © 2 020 Pavel Ivanov); […] — мои пропуски. В полном файле 9 пользовательских историй, 71 требование и три сессии уточнений.

# Feature Specification: Pager Integration and Configuration

**Feature Branch**: `010-pager`
**Created**: 2025-01-15
**Status**: Draft
**Input**: User description: "Add feature describing how pager is handled, with configurable pager profiles, priority-based selection, and role-specific arguments for view and follow modes"

## Clarifications
[…]
### Session 2026-02-15

- Q: How should the application execute the pager program to prevent security vulnerabilities? → A: Execute pager directly from PATH without shell, validate it's executable before spawning
- Q: What should the user experience be when the specified pager program is not found or cannot be executed? → A: Write error to stderr, fall back to direct stdout (disable paging)
[…]
- Q: What exit code should the application use when the pager crashes or is killed unexpectedly? → A: Exit with code 141 (SIGPIPE convention, matching broken pipe)
[…]

## User Scenarios & Testing *(mandatory)*
[…]
### User Story 3 - Graceful Exit When Pager Closes (Priority: P1)

When a user closes the pager (e.g., pressing 'q' in less), the application should detect the pager exit and terminate gracefully without error messages or hanging processes.

**Why this priority**: Critical for user experience - users expect quitting the pager to cleanly exit the application. Hanging or error messages create confusion and frustration.

**Independent Test**: Can be tested by running the application with large input, closing the pager, and verifying the application exits with status code 0.

**Acceptance Scenarios**:

1. **Given** the application is running with output piped to a pager, **When** the user quits the pager normally, **Then** the application process terminates within 1 second with exit code 0
2. **Given** the application is in follow mode with a pager enabled via profile configuration, **When** the user quits the pager, **Then** the application stops monitoring and exits cleanly
3. **Given** the pager crashes or is killed unexpectedly, **When** the application detects the abnormal exit, **Then** the application writes the error message "hl: pager killed" to stderr, resets ANSI color/formatting codes, restores terminal echo mode, and exits with code 141
4. **Given** the user quits the pager while the application is still writing output, **When** the write to pager's stdin fails with broken pipe error, **Then** the application stops processing and exits gracefully with exit code 0 without logging an error
[…]

### Edge Cases
[…]
- How should SIGPIPE be handled when user quits pager early?
  - Ignore SIGPIPE signal, treat write errors (broken pipe) as normal termination condition, exit gracefully with status code 0
[…]

## Requirements *(mandatory)*

### Functional Requirements
[…]
- **FR-002**: System MUST launch a pager automatically when stdout is a TTY, no output file is specified, and paging mode is "auto" (default)
- **FR-003**: System MUST provide a `--paging` command-line option accepting values `auto`, `always`, or `never` with `auto` as the default
[…]
- **FR-004a**: System MUST disable paging when output is explicitly directed to a file via `--output` or `-o` option
[…]
- **FR-005**: System MUST execute the pager program directly from PATH without shell interpretation to prevent command injection vulnerabilities
[…]
- **FR-005b**: System MUST validate that the specified pager executable exists and has execute permissions before attempting to spawn the process
[…]

## Success Criteria *(mandatory)*

### Measurable Outcomes
[…]
- **SC-001a**: Pager interface appears immediately (within 100ms) after application launch when paging is enabled
- **SC-002**: Application exits within 1 second of pager termination in 100% of normal cases
[…]
- **SC-006**: Test coverage for pager-related code must not be less than the current test coverage on the target branch

Что здесь происходит — по блокам:

  • Шапка (Feature Branch, Status, Input) связывает спеку с веткой и сохраняет исходную постановку задачи словами автора.

  • Clarifications — журнал вопросов и ответов шага Clarify с датами сессий. Решение не теряется в чате, а превращается в требование: ответ про запуск «without shell» стал FR-005, про проверку исполняемости — FR-005b, про код 141 — сценарием 3 в User Story 3.

  • User Story несёт три вещи, которых нет в обычном тикете: причину приоритета (Why this priority), независимый тест (Independent Test) и сценарии приёмки Given/When/Then с числами (1 секунда, коды выхода 0 и 141, точный текст ошибки).

  • Edge Cases фиксируют поведение в нештатных ситуациях — именно там агент чаще всего «додумывает».

  • Functional Requirements в форме «System MUST…» с номерами. Это не EARS, но главное свойство то же: каждое требование можно проверить и на него можно сослаться по номеру. Именно эти номера ревьюер ставит в свою таблицу статусов.

  • Success Criteria — измеримые результаты (100 мс, 1 секунда в 100% случаев, покрытие не ниже текущего).

Чего в этой спеке нет: гипотезы бизнес‑результата и карты валидации человеком. Для работы с агентами в команде их стоит добавить.

Именно с таким файлом ревьюер сверяет дифф. Если в PR пейджер стал запускаться через sh -c, это нарушение FR-005. Если появилась новая опция, которой нет ни в одном требовании, — это незаявленное поведение. Оба случая встретятся в эталонном примере в шаге 4.

Теперь сам агент.

Спека нашего ревьюера (docs/agents/spec-reviewer.md):

# Агент: spec-reviewer

## Цель
Для каждого требования из spec.md сказать, реализовано ли оно в PR,
и найти поведение, которого нет в спеке.

## Режим и разрешения
Ассистирующий, R1: агент только предлагает, решение о слиянии — за человеком.

## Входные данные (только чтение)
- specs/<фича>/spec.md — из репозитория
- Пакет для ревью — scripts/review-package.sh <BASE> <HEAD> <файл>
- Описание PR — gh pr view <номер> --json title,body (токен только на чтение)
- constitution.md проекта

## Выход
Отчёт по шаблону: таблица требование → статус → file:line;
незаявленное поведение; вопросы к автору.

## Действия (скилы)
- post-review-comment — опубликовать отчёт комментарием в PR
  (вызывает оркестратор, не сам ревьюер)

## Запрещено
- Менять файлы, делать коммиты, одобрять / отклонять / сливать PR
- Читать .env и secrets/

## Эскалация к человеку
- spec.md содержит [NEEDS CLARIFICATION]
- Дифф больше 30 файлов
- Требование нельзя проверить по диффу → статус needs_human, а не догадка

## Ограничения
- maxTurns: 20 в определении субагента
- В CI: claude -p ... --max-turns 30 --max-budget-usd 2

Пакет для ревью собирает детерминированный скрипт scripts/review-package.sh. Это упрощённая версия скрипта review-package из obra/superpowers (MIT, © 2 025 Jesse Vincent) — оригинал приведён в разделе про superpowers ниже. Убрана привязка к файлу плана, добавлен лимит на число файлов:

#!/usr/bin/env bash
# scripts/review-package.sh BASE HEAD OUTFILE
# Based on obra/superpowers skills/subagent-driven-development/scripts/review-package
# (MIT License, Copyright (c) 2025 Jesse Vincent)
set -euo pipefail

if [ $# -ne 3 ]; then
  echo "usage: review-package.sh BASE HEAD OUTFILE" >&2
  exit 2
fi
base=$1; head=$2; out=$3
max_files=${MAX_FILES:-30}

git rev-parse --verify --quiet "$base" >/dev/null || { echo "bad BASE: $base" >&2; exit 2; }
git rev-parse --verify --quiet "$head" >/dev/null || { echo "bad HEAD: $head" >&2; exit 2; }
git merge-base --is-ancestor "$base" "$head" || { echo "HEAD is not a descendant of BASE" >&2; exit 3; }
[ "$(git rev-list --count "${base}..${head}")" -gt 0 ] || { echo "empty commit range" >&2; exit 3; }

files=$(git diff --name-only "${base}..${head}" | wc -l | tr -d ' ')
[ "$files" -le "$max_files" ] || { echo "too many files: $files > $max_files, escalate to a human" >&2; exit 4; }

mkdir -p "$(dirname "$out")"
{
  echo "# Review package: ${base}..${head}"
  echo; echo "## Commits";       git log --oneline "${base}..${head}"
  echo; echo "## Files changed"; git diff --stat "${base}..${head}"
  echo; echo "## Diff";          git diff -U10 "${base}..${head}"
} > "$out"
echo "wrote $out: $files file(s)"

Как запустить. В интерактивной сессии Claude Code достаточно попросить: «Use the spec‑reviewer subagent. SPEC=specs/010-pager/spec.md PACKAGE=.review/pr-412.diff». В CI — так (нужны полная история, например fetch-depth: 0, и токен GH_TOKEN с правами на чтение PR):

PR=412
git fetch origin "pull/$PR/head"
BASE=$(gh pr view "$PR" --json baseRefOid -q .baseRefOid)
HEAD=$(gh pr view "$PR" --json headRefOid -q .headRefOid)
scripts/review-package.sh "$BASE" "$HEAD" ".review/pr-$PR.diff"

claude -p "Use the spec-reviewer subagent. SPEC=specs/010-pager/spec.md PACKAGE=.review/pr-$PR.diff. Print only the report." 
  --max-turns 30 --max-budget-usd 2 > ".review/pr-$PR.md"

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

И скил для единственного действия с последствиями (.claude/skills/post-review-comment/SKILL.md):

---
name: post-review-comment
description: Publishes a saved spec-reviewer report as a comment on a pull request. Use only when the report file already exists.
argument-hint: <pr-number> <report-file>
allowed-tools: Bash(${CLAUDE_SKILL_DIR}/scripts/post_review_comment.sh *)
---

Опубликуй отчёт одной командой:

`${CLAUDE_SKILL_DIR}/scripts/post_review_comment.sh <номер PR> <файл отчёта>`

- Не вызывай `gh` напрямую и не меняй аргументы скрипта.
- Если скрипт завершился с ошибкой — покажи её человеку и остановись.
- Верни ссылку на комментарий, которую напечатал скрипт.

Скрипт рядом со скилом (.claude/skills/post-review-comment/scripts/post_review_comment.sh, не забудьте chmod +x):

#!/usr/bin/env bash
# Публикует отчёт spec-reviewer комментарием к PR. Только комментарий: без approve, review и merge.
set -euo pipefail

pr="${1:?usage: post_review_comment.sh <pr-number> <report-file>}"
report="${2:?usage: post_review_comment.sh <pr-number> <report-file>}"

[[ "$pr" =~ ^[0-9]+$ ]] || { echo "PR number must be numeric: $pr" >&2; exit 2; }
[ -s "$report" ] || { echo "report file is missing or empty: $report" >&2; exit 2; }

size=$(wc -c < "$report")
[ "$size" -le 65000 ] || { echo "report is too large: $size bytes (max 65000)" >&2; exit 2; }

gh pr comment "$pr" --body-file "$report"

Действие завёрнуто в скрипт сознательно. Логику, которая должна быть предсказуемой (валидация, формат, вызов API), пишем детерминированным кодом. LLM оставляем то, где нужны анализ и формулировка.

Сам ревьюер этот скил не вызывает: у него есть только Read, Grep и Glob. Он возвращает отчёт, а публикует его оркестратор — основная сессия или шаг CI. Так анализ и действие разнесены по разным исполнителям с разными правами.

MCP, API или CLI: через что агенту работать с внешними системами

MCP — не единственный путь. Если агент умеет запускать команды в терминале (Claude Code, Codex CLI, Cursor в агентном режиме и другие), он может работать через обычные CLI‑инструменты: gh, glab, kubectl, aws, psql, jq. Наш скил публикации так и устроен: внутри вызов gh pr comment.

Способ

Сильные стороны

Слабые стороны

Когда выбирать

MCP‑сервер

Типизированные инструменты, авторизация на стороне сервера, работает даже там, где нет терминала

Описания инструментов занимают контекст; нужен сервер и его сопровождение

Чтение данных из систем без CLI; агенты без доступа к командной строке

API через свой скрипт

Полный контроль: валидация входов, формат вывода, повторы

Скрипт нужно писать и тестировать

Действия с последствиями, где нужна предсказуемость

CLI‑инструмент

Ничего не нужно разворачивать; модели хорошо знают популярные CLI; вывод легко фильтровать через --json и jq

Широкие права по умолчанию; CLI работает под вашими учётными данными

Агент с терминалом и распространённый инструмент с хорошим CLI

Правила для работы через CLI:

  • Разрешайте конкретные команды, а не весь инструмент. Доступ к терминалу — самое широкое из прав агента. В Claude Code правила задаются по префиксу команды: разрешить Bash(gh pr view *) и Bash(gh pr diff *), запретить Bash(gh pr merge *) (см. шаг 5).

  • Отдельные токены. CLI берёт тот токен, под которым он авторизован. Для агента задайте свой токен через переменную окружения (для gh — GH_TOKEN) с минимальными правами, а не личную сессию разработчика.

  • Неинтерактивный режим и машинный вывод. Используйте флаги вроде --json, --yes, --no-pager и ограничивайте объём (--limit, head): длинный вывод тратит контекст, а интерактивный запрос повесит агента.

  • Вывод — это данные, а не инструкции. Текст issue, комментария или лога может содержать попытку prompt injection. Запреты в настройках доступа страхуют и от этого.

  • Действия с последствиями заворачивайте в скрипт. Агент вызывает scripts/post_review_comment.sh, а не собирает команду gh сам. Тогда разрешить можно ровно один скрипт, а его логика проверяется обычными тестами.

Типичная схема для нашего ревьюера: чтение PR через gh pr view --json и gh pr diff (или MCP с read‑only токеном), единственное действие — через скрипт‑скил, всё остальное запрещено настройками.

Шаг 4. Критерии приёмки и эталонные примеры

Агент не должен оценивать сам себя. Разметку «правильного ответа» делает человек заранее, а сравнение выполняет скрипт. Это тот же принцип, что и в SDD: критерии приёмки закодированы в тестах, а не описаны словами.

Критерии приёмки ревьюера (добавляются в спеку агента):

  • WHEN требование реализовано и покрыто тестом, THE агент SHALL поставить статус «реализовано» со ссылкой на код и тест.

  • IF в диффе нет кода для требования, THEN THE агент SHALL поставить «не реализовано», а не «частично».

  • IF код добавляет поведение, которого нет в спеке, THEN THE агент SHALL перечислить его в разделе «незаявленное поведение».

  • IF spec.md содержит [NEEDS CLARIFICATION], THEN THE агент SHALL остановиться и эскалировать, не выставляя статусы.

Набор эталонных примеров. Возьмите 10–20 уже смерженных PR из своего репозитория, для которых есть спека, и разметьте их вручную. Добавьте несколько «ловушек»: PR с лишним поведением, PR без тестов, спеку с [NEEDS CLARIFICATION].

# evals/spec-reviewer/case-007.yaml
pr: 412                         # PR с доработкой пейджера
spec: specs/010-pager/spec.md
expected:
  FR-003: implemented
  FR-004a: implemented
  FR-005: not_implemented       # пейджер запускается через sh -c
  undeclared:
    - "новая опция --pager-timeout"   # в спеке нет такого требования
must_escalate: false

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

Отдельно проверьте эскалации: whitepaper «AI‑Disrupt PDLC» выделяет их в самостоятельный класс evals. В набор включаются неоднозначные случаи, и проверяется, что агент останавливается, а не угадывает. Качество ревьюера измеряется долей совпадений с человеком; whitepaper ставит цель не ниже 80–85%.

И ещё одно наблюдение EPAM: проверяющий агент без явной установки склонен к оптимизму и одобряет почти всё. Добавьте в конституцию ревьюера состязательную установку: «найди не менее пяти конкретных расхождений или обоснуй, почему их нет».

Результат каждого запуска складывайте в пакет доказательств (Evidence Bundle): отчёт, результаты evals, журнал вызовов и расход токенов. С ним человек проверяет не «на глаз», а по фактам.

Если один и тот же пример валится и приходится в третий раз править промпт, остановитесь: скорее всего, неточна сама спека агента или цель.

Шаг 5. Ограничители: правила в коде, а не в промпте

Запрет в промпте — это просьба, которую модель может проигнорировать. Настоящие ограничения проверяются снаружи решения агента и физически блокируют действие. Это называют Policy as Code.

От правил стоит отличать агентов‑защитников (Guardian) — агентов, которые проверяют других агентов. Их зрелость whitepaper «AI‑Disrupt PDLC» (раздел 4.5) описывает шкалой T1–T5:

Уровень

Что делает агент‑защитник

T1 · Ревью

Смотрит вывод агента и готовит отчёт для человека

T2 · Верификация

Активно проверяет тестами и evals, выносит pass/fail

T3 · Перенаправление

Отправляет рискованные действия на одобрение человеку

T4 · Блокировка

Сам останавливает рискованные действия

T5 · Исправление

Сам исправляет нарушения, например публикует PR с исправлением

Наш spec‑reviewer — это и есть Guardian уровня T1 для агентов, которые пишут код. Но и самому ревьюеру нужны внешние правила: любой агент с реальными правами должен работать под запретами, которые проверяются вне его решения. Подтверждения на каждый шаг — плохая замена таким запретам: по данным Anthropic, которые приводит whitepaper, после 20 и более запросов за сессию точность подтверждений падает с 85% до 55%. Решение — уменьшать число запросов: ставить жёсткие запреты и объединять низкорисковые действия в пакетные подтверждения.

Для нашего ревьюера в Claude Code такие запреты задаются в .claude/settings.json проекта:

{
  "permissions": {
    "allow": [
      "Bash(gh pr view *)",
      "Bash(gh pr diff *)",
      "Bash(scripts/review-package.sh *)"
    ],
    "deny": [
      "Read(./.env)",
      "Read(./secrets/**)",
      "Bash(git push *)",
      "Bash(gh pr merge *)",
      "Bash(gh pr review *)"
    ]
  }
}

Даже если конституцию кто‑то случайно изменит, одобрить или смержить PR агент не сможет. Точный синтаксис правил сверяйте с документацией вашей версии инструмента; для сложных проверок используются хуки, которые срабатывают перед вызовом инструмента.

Остальные ограничители:

  • Отдельные учётные данные. Агент работает не под вашим токеном: у MCP — токен только на чтение, у скрипта публикации — токен только на комментарии.

  • Лимит шагов. В неинтерактивном запуске ограничьте число ходов агента (в Claude Code — флаг --max-turns), чтобы он не зациклился.

  • Бюджет. Лимит расходов и алерты у провайдера модели; остановка по расходу, даже если агент работает «корректно».

  • Журнал. Каждый запуск сохраняет вход, вызовы инструментов и результат — например, как артефакт CI. Без этого расследовать ошибку агента нечем.

Шаг 6. Запуск и метрики

Запускаем агента рядом с обычным процессом, а не вместо него. На R1 ревьюер пишет отчёт, а человек проводит своё ревью как обычно и отмечает, где агент ошибся.

До запуска снимите baseline: среднее время до первого ревью PR, долю PR, вернувшихся на доработку из‑за несоответствия требованиям, число дефектов «не то поняли» после релиза.

Метрика

Что показывает

Как считать

Outcome Validation Rate

Доля отчётов, с которыми ревьюер‑человек согласился без правок

Отметка «верно / неверно» под каждым отчётом

Ложные «реализовано»

Самая опасная ошибка агента

Разметка человека + эталонный набор

Доля эскалаций

Слишком мало — агент угадывает; слишком много — бесполезен

Журнал запусков

Время до первого ревью и доля доработок

Реальный эффект для команды

Сравнение с baseline

Стоимость на PR

Окупается ли агент

Биллинг провайдера / число PR

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

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

Любое изменение агента (новая версия промпта, другая модель) проверяйте на эталонном наборе и по метрикам, а не по ощущению «стало вроде лучше». Инциденты и ошибки агента возвращайте в его спеку и в набор примеров — так спека со временем становится точнее.

Пример из открытого проекта: obra/superpowers

Ближе всего к описанному ревьюеру — навык subagent‑driven‑development из репозитория obra/superpowers (лицензия MIT, около 299 тыс. звёзд на октябрь 2026). В нём один субагент реализует задачу из плана, а другой проверяет дифф на соответствие спецификации. Репозиторий найден среди проектов GitHub с самыми популярными файлами AGENTS.md.

Что в статье

Как в superpowers

Совпадает

Одна цель: соответствие спеке + незаявленное поведение

Раздел Spec Compliance: Missing / Extra / Misunderstood

да

Ревьюер только читает

Ревью read‑only, рабочее дерево и ветку трогать запрещено

да

Анализ и действие у разных исполнителей

Контроллер действует, ревьюер только возвращает отчёт

да

Состязательная установка

«Не доверяй отчёту исполнителя», каждое замечание с file:line

да

Эскалация вместо догадки

Статус ⚠️ «нельзя проверить по диффу»; 4 условия остановки (необратимое, безопасность, действие вне ветки, сломанный план)

да

Пакет доказательств и журнал

Скрипт review-package и журнал progress.md со всеми решениями

да

Лимит шагов и бюджет

Не более 5 раундов исправлений на задачу; самая дешёвая подходящая модель для каждой роли

да

Проверка самого агента на примерах

Тесты навыков через субагентов (tests/claude-code, writing-skills)

частично

Запреты настройками доступа (deny)

Запреты только текстом в промпте

нет

Публикация отчёта в PR и метрики

Отчёт остаётся внутри сессии, метрик качества нет

нет

Полностью совпадают 7 из 10 элементов и ещё один частично. Не хватает того, что в статье вынесено из промпта наружу: запретов в настройках и метрик.

Ниже — дословные фрагменты из репозитория (коммит 5 bf4e78, MIT, © 2 025 Jesse Vincent); […] — мои пропуски. Полные файлы: task‑reviewer‑prompt.md и scripts/review‑package.

Промпт ревьюера задачи (task-reviewer-prompt.md, фрагменты):

# Task Reviewer Prompt Template

Use this template when dispatching a task reviewer subagent. The reviewer
reads the task's diff once and returns two verdicts: spec compliance and
code quality.

**Purpose:** Verify one task's implementation matches its requirements (nothing
more, nothing less) and is well-built (clean, tested, maintainable)
[…]
    Your review is read-only on this checkout. Do not mutate the working
    tree, the index, HEAD, or branch state in any way.
[…]
    ## Do Not Trust the Report

    Treat the implementer's report as unverified claims about the code. It
    may be incomplete, inaccurate, or optimistic. Verify the claims against
    the diff. Design rationales in the report are claims too: "left it per
    YAGNI," "kept it simple deliberately," or any other justification is the
    implementer grading their own work. Judge the code on its merits — a
    stated rationale never downgrades a finding's severity.
[…]
    ## Part 1: Spec Compliance

    Compare the diff against What Was Requested:

    - **Missing:** requirements they skipped, missed, or claimed without
      implementing
    - **Extra:** features that weren't requested, over-engineering, unneeded
      "nice to haves"
    - **Misunderstood:** right feature built the wrong way, wrong problem
      solved
[…]
    If a requirement cannot be verified from this diff alone (it lives in
    unchanged code or spans tasks), report it as a ⚠️ item instead of
    broadening your search.
[…]
    ## Output Format

    ### Spec Compliance

    - ✅ Spec compliant | ❌ Issues found: [what's missing/extra/misunderstood,
      with file:line references]
    - ⚠️ Cannot verify from diff: [requirements you could not verify from the
      diff alone, and what the controller should check — report alongside the
      ✅/❌ verdict for everything you could verify]

Пояснение:

  • Purpose задаёт одну цель и сразу её границы: «nothing more, nothing less» — и недоделка, и лишнее считаются ошибкой.

  • read‑only — ревьюеру запрещено трогать рабочее дерево, индекс, HEAD и ветки. Здесь это запрет текстом; в нашем агенте то же самое закреплено настройкой tools: Read, Grep, Glob.

  • Do Not Trust the Report — состязательная установка: отчёт исполнителя и его обоснования — непроверенные утверждения, и они не снижают серьёзность замечания.

  • Spec Compliance — три категории: Missing (не сделано или заявлено без реализации), Extra (незаявленное поведение) и Misunderstood (сделано не то или не так). В нашем агенте они соответствуют статусам not_implemented, разделу «Незаявленное поведение» и partial.

  • ⚠️ Cannot verify — эскалация вместо догадки: если требование нельзя проверить по диффу, ревьюер не расширяет поиск, а передаёт вопрос контроллеру. У нас это статус needs_human.

Скрипт пакета для ревью (scripts/review-package, полностью):

#!/usr/bin/env bash
# Generate a review package: commit list, stat summary, and the net
# diff with extended context, written to a file the reviewer reads in one
# call. Using the recorded per-task BASE (not HEAD~1) keeps multi-commit
# tasks intact.
#
# Usage: review-package PLAN_FILE BASE HEAD [OUTFILE]
# Default OUTFILE: <repo-root>/.superpowers/sdd/<plan-basename>/review-<base7>..<head7>.diff
# (named per range, so a re-review after fixes gets a distinct fresh file).
set -euo pipefail

if [ $# -lt 3 ] || [ $# -gt 4 ]; then
  echo "usage: review-package PLAN_FILE BASE HEAD [OUTFILE]" >&2
  exit 2
fi

plan=$1
base=$2
head=$3
[ -f "$plan" ] || { echo "no such plan file: $plan" >&2; exit 2; }

git rev-parse --verify --quiet "$base" >/dev/null || { echo "bad BASE: $base" >&2; exit 2; }
git rev-parse --verify --quiet "$head" >/dev/null || { echo "bad HEAD: $head" >&2; exit 2; }

# Range guards (exit 3): a wrong-branch HEAD yields a range that is empty or
# not rooted at BASE; either would silently produce a bogus review package.
git merge-base --is-ancestor "$base" "$head" || { echo "HEAD is not a descendant of BASE: ${base}..${head}" >&2; exit 3; }
[ "$(git rev-list --count "${base}..${head}")" -gt 0 ] || { echo "empty commit range: ${base}..${head}" >&2; exit 3; }

if [ $# -eq 4 ]; then
  out=$4
else
  # Invoke via bash rather than direct exec: some extractors (Python zipfile)
  # strip Unix exec bits when unpacking marketplace packages (#2040).
  dir=$("${BASH:-bash}" "$(cd "$(dirname "$0")" && pwd)/sdd-workspace" "$plan")
  out="$dir/review-$(git rev-parse --short "$base")..$(git rev-parse --short "$head").diff"
fi

{
  echo "# Review package: ${base}..${head}"
  echo
  echo "## Commits"
  git log --oneline "${base}..${head}"
  echo
  echo "## Files changed"
  git diff --stat "${base}..${head}"
  echo
  echo "## Diff"
  git diff -U10 "${base}..${head}"
} > "$out"

commits=$(git rev-list --count "${base}..${head}")
echo "wrote ${out}: ${commits} commit(s), $(wc -c < "$out" | tr -d ' ') bytes"

Пояснение: скрипт — детерминированная часть, которую не доверяют модели. Проверки диапазона («Range guards») не дают собрать пакет с чужой ветки или пустой: такой пакет дал бы ревьюеру ложную картину без какой‑либо ошибки. Всё, что читает ревьюер, — список коммитов, статистика и дифф с 10 строками контекста — лежит в одном файле, и он читает его один раз. Упрощённая версия для нашего агента без привязки к плану — в шаге 3.

Предохранитель и журнал. Контроллер даёт не более пяти раундов «исправление + повторное ревью» на задачу. Раунды 1–3 ведёт прежний исполнитель, 4–5 — новый исполнитель на более сильной модели. После пятого раунда оставшиеся замечания разбираются и фиксируются решением. Каждый шаг записывается в журнал плана, например так:

# SDD ledger — plan: specs/010-pager/plan.md
Task 3: fix round 2/5 (2 addressed, 1 open — FR-005b нет проверки прав на запуск; commits a1b2c3d..e4f5a6b)
Task 3: Ruling: код выхода 141 берём из Clarifications спеки, не из плана — спека главнее — если неверно, правка в одной функции
Task 3: complete

Чтобы довести пример до схемы из статьи, добавьте к нему три вещи. Первая — deny‑правила в .claude/settings.json из шага 5: сейчас запрет менять ветку держится только на тексте промпта. Вторая — скил публикации отчёта в PR. Третья — учёт метрик из шага 6, размечая итог ревьюера (Approved / Needs fixes) как верный или неверный.

Типичные ошибки

Ошибка

Чем опасна

Что делать

Один агент на все задачи

Поведение нельзя проверить и ограничить

Несколько маленьких агентов с одной целью каждый

Запреты только в промпте

Агент может их проигнорировать

Дублировать настройками доступа и хуками

Агент оценивает сам себя

Самоотчёт вместо проверки

Разметка человеком и эталонный набор

Сразу высокая автономность

Ошибки попадают в прод до того, как их заметят

Старт на R1, повышение по метрикам

Один длинный промпт без версий

Любая правка ломает что‑то ещё, откатить некуда

Три уровня, git, ревью, эталонный набор

Метрики объёма

Иллюзия продуктивности

Доля результатов без переделки

Заключение

Собственный агент — это не промпт, а набор артефактов: цель и уровень автономности, конституция, спека со скилами, эталонные примеры, ограничители в коде и метрики. Каждый артефакт живёт в репозитории, проходит ревью и меняется так же, как код. Тогда на вопрос «почему агент так сделал?» есть ответ, а его изменение можно проверить.

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

Источники и что почитать

Автор: SaTeLlit12

Источник