
Скил выглядит как готовая инструкция: вы дописали в SKILL.md правило, агент один раз сделал как надо, и правка кажется рабочей. Но один удачный прогон ничего не доказывает. Агент мог вообще не загрузить скил, мог загрузить и проигнорировать правило, а мог выполнить его без пользы для результата.
19 октября Sergii Makarevych (@sermakarevich) опубликовал в X большую статью «How to write and test agent skills with evals». Он собрал опубликованные исследования скилов, и выводы у них трезвые. В бенчмарке SWE-Skills-Bench 39 из 49 публичных скилов для разработки не подняли долю решённых задач вообще, средний прирост составил 1,2%, а расход токенов вырос местами на 451%. Сам Макаревич исходит из того, что скил ломается двумя разными способами, и по одному итоговому результату их не различить. Либо агент не делает написанного (плохой текст), либо делает, а результат не лучше (плохая идея).
Проверка скила называется эвалом. Как скилы устроены и подгружаются в Claude Code, мы разбирали в отдельной статье. Здесь речь о том, как измерить, что правка в SKILL.md меняет поведение агента.
Первый вопрос: загружается ли скил. Агент видит в контексте только имя и описание скила и сам решает, открывать ли его тело. Макаревич приводит данные, что в зависимости от модели скилы открываются в 11–72% случаев, а с ростом числа скилов в списке модель всё чаще выбирает не тот. Если скил не загрузился, всё остальное измерять бессмысленно: вы получаете прогон без скила, только с лишними токенами.
Второй вопрос: выполняет ли агент то, что написано. Это проверяется по логу действий, а не по ответу. Если скил требует сначала написать падающий тест, в логе должна быть запись тестового файла, потом запуск тестов с ненулевым кодом выхода, и только потом правка исходника. Макаревич советует проверять каждое правило скила отдельной проверкой в коде, без судьи-модели.
Третий вопрос: стал ли результат лучше. Для этого нужна проверка, которую агент не видит: скрытые тесты, эталонный ответ, рубрика для судьи. Рядом с результатом стоит записывать цену: токены, время, число ходов.
Из пары второго и третьего ответов получается решение. Агент правило не выполняет, значит переписывайте формулировку. Выполняет, а результат не меняется, значит идея не работает на этой модели и правило стоит убрать.
Начинать стоит с двух-трёх случаев. Так советует руководство Evaluating skill output quality на agentskills.io: сначала посмотрите на первый прогон, потом расширяйте набор. Промпты должны быть такими, какими их пишет живой человек: с путями к файлам, названиями колонок, опечатками и разной степенью подробности. Там же советуют хотя бы одним случаем проверить край: кривой вход или двусмысленную просьбу.
Для проверки загрузки нужны и отрицательные примеры. skill-creator для этого просит 8–10 промптов, на которых скил должен сработать, и 8–10, на которых не должен. Отрицательные промпты полезны только почти совпадающие: те же слова, но другая задача. Просьба написать функцию Фибоначчи для скила про PDF ничего не проверяет. Вот наш пример для воображаемого скила changelog, который пишет раздел CHANGELOG по коммитам:
# должен сработать
допиши раздел Unreleased в CHANGELOG.md по коммитам после v2.3.0, только то, что заметят пользователи
перед релизом глянь git log и собери changelog, у нас формат Keep a Changelog
# не должен сработать
почему после мержа упал changelog.test.ts?
переименуй CHANGELOG.md в HISTORY.md и поправь ссылку в READMEЕсли скил лежит в плагине, в Claude Code с версии 2.1.269 есть команда claude plugin eval. Каждый прогон идёт в свежей изолированной неинтерактивной сессии, где загружен только ваш плагин. Каждый случай по умолчанию прогоняется три раза с плагином и три раза без него. В итоге вы получаете две оценки, WITH и W/OUT, и их разницу Δ, то есть вклад плагина. Если случай проходит на 1.0 и без плагина, дело не в нём.
Набор случаев можно не писать руками. Команда claude plugin eval init открывает сессию, в которой Claude читает плагин, расспрашивает вас, каким должен быть хороший результат, предлагает промпты и проверки, пробует их и записывает файлы. Раскладка из документации выглядит так (имена случаев наши):
my-plugin/
├── .claude-plugin/plugin.json
├── skills/changelog/SKILL.md
└── evals/
├── unreleased-from-log/
│ ├── prompt.md
│ └── graders/
│ ├── criteria.md
│ └── skill-fired.md
└── ignores-test-failure/
├── prompt.md
└── graders/
└── skill-silent.mdВ prompt.md лежит сам промпт и лимиты прогона. Каждый прогон стартует в пустой папке, поэтому всё нужное для задачи кладите в промпт или готовьте скриптом из case.yaml:
---
max_turns: 10
allowed_tools: [Read, Glob, Grep, Skill]
---
Вот коммиты после v2.3.0: "feat: экспорт в CSV", "refactor: вынес парсер", "fix: дата в отчёте по UTC", "ci: кеш pnpm". Допиши раздел Unreleased для CHANGELOG.md, только то, что заметят пользователи.Каждый файл в graders/ отдельная проверка. Документация советует давать случаю одну проверку на результат и одну на путь к нему. Результат здесь проверяет судья-модель по нашей рубрике, а путь проверяет tool_used: вызывал ли агент тул Skill с нужным именем.
---
type: llm
---
PASS if the answer is an Unreleased section with the CSV export and the UTC date fix, and nothing about refactoring or CI.
FAIL if it lists every commit or mentions the parser refactoring.---
type: tool_used
tool: Skill
input_match: '"skill"\s*:\s*"(?:[\w-]+:)?changelog"'
---Для отрицательного случая та же проверка с min: 0, max: 0 и arm: both: скил не должен вызываться ни в одном прогоне. Проверку вызова скила Claude Code сам исключает из оценки обеих веток, иначе ветка без плагина всегда проваливала бы её и раздувала Δ. Запуск и быстрая итерация по одному случаю:
claude plugin eval .
claude plugin eval . --case unreleased-from-log --runs 1 --ablation noneСамая частая первая находка, по документации, это Δ около нуля и проваленная проверка tool_used: Skill. Значит, на естественных формулировках агент скил не выбирает, и править надо поле description.
Если скил личный или проектный, документация Claude Code предлагает на время контрольного прогона выключить его значением "off" в настройке skillOverrides. Само сравнение автоматизирует плагин skill-creator. Он ставится из официального маркетплейса:
/plugin install skill-creator@claude-plugins-officialДальше достаточно попросить, например, evaluate my changelog skill with skill-creator. Случаи хранятся в evals/evals.json рядом со скилом, у этого формата своя схема, и claude plugin eval её не читает:
{
"skill_name": "changelog",
"evals": [
{
"id": 1,
"prompt": "допиши раздел Unreleased в CHANGELOG.md по коммитам после v2.3.0",
"expected_output": "Раздел Unreleased только с пользовательскими изменениями",
"files": []
}
]
}Для каждого случая skill-creator в одном ходе запускает двух субагентов: со скилом и без него. Если вы улучшаете существующий скил, базой служит не пустой прогон, а копия старой версии, которую он снимает до правки. Он записывает токены и время каждого прогона, проверяет утверждения по результатам и сводит всё в benchmark.json со средним и стандартным отклонением. Потом отдельный проход ищет то, что прячут средние: утверждения, которые проходят и без скила, и случаи с большим разбросом. Результаты открываются в HTML-просмотрщике, где вы оставляете фидбек, а следующая итерация его читает.
Для описания скила есть отдельный цикл. Скрипт делит промпты на обучающие 60% и проверочные 40%, прогоняет каждый промпт три раза, предлагает новое описание до пяти раз и выбирает лучшее по проверочной части, чтобы не подогнать описание под примеры.
Когда нужно понять, лучше ли новая версия старой, skill-creator отдаёт два результата независимому судье под метками A и B, не говоря, какая версия какая. Строже всего ослепление описано в плейбуке eval из набора pstack Лорен Тан. Она пишет, что прогоняет эвалы для своих скилов, чтобы знать, что они меняют поведение агента к лучшему.
По её правилам агент-кандидат не должен догадаться, что его проверяют. В папках, файлах и промпте нет слов вроде eval, test, judge, benchmark, а задача выглядит как обычная просьба пользователя. Кандидата не просят перечислить, какие скилы он применил, потому что самоотчёту верить нельзя: что агент на самом деле открыл, видно по транскрипту и по форме кода. Судья знает, что судит, но видит ответы под нейтральными метками, без названий моделей. Если сравниваются два варианта, один судья оценивает оба набора за один проход по одной шкале. В конце человек сам читает каждый ответ, и расхождение с судьёй означает предвзятость модели или нечёткую рубрику. Как устроен pstack целиком, мы рассказывали в статье о нём.
Агент недетерминирован, поэтому один прогон почти ничего не говорит. claude plugin eval по умолчанию делает три прогона, а судья по рубрике голосует трижды и засчитывает проход при двух голосах из трёх. Макаревич приводит исследование, где библиотека скилов дала прирост 2,8 пункта, но доверительный интервал пересёк ноль, то есть прирост неотличим от шума.
Вторая ловушка в длине. В исследовании Signal or Noise для части моделей такой же по длине, но нерелевантный текст воспроизводил большую часть потерь от скила. Поэтому Макаревич советует третью ветку: блок осмысленного постороннего текста того же размера. Если скил обгоняет прогон без скила, но проигрывает собственному контролю по длине, полезных идей в нём нет. Готовой опции для такой ветки в claude plugin eval нет, её придётся собрать самим.
Правка скила, обновление модели или библиотеки могут молча сломать то, что работало. Документация предлагает гонять набор в CI, закрепив обе модели, чтобы смену модели не приняли за регрессию плагина:
claude plugin eval . \
--trust-plugin \
--json results.json \
--threshold 0.8 \
--model claude-sonnet-5 \
--judge-model claude-haiku-4-5 \
--no-publish \
--max-cost-usd 20Команда завершится с кодом 1, если хоть один случай набрал меньше порога, и с кодом 2, если кончился бюджет. Δ на код выхода не влияет, его нужно смотреть в отчёте самому. Макаревич предлагает перезапускать эвалы после каждого обновления модели.
Эвал дорогой, поэтому сначала стоит убрать очевидно лишнее. Мэтт Покок в списке типичных ошибок называет слишком длинные скилы, а его скил /retro разбирает транскрипт сеанса и среди прочего ищет инструкции, которые ничего не меняют в поведении агента. Подробнее о его наборе в статье о скилах Покока. Такой разбор даёт кандидатов на удаление, а эвал подтверждает: уберите одно правило, оставьте остальное и прогоните набор снова. Если результат не упал, правило лишнее. Так Лорен Тан сократила pstack на 10%, по её словам без потерь в поведении.
Каждый прогон и каждый вызов судьи это настоящий запрос к модели за ваши лимиты или деньги. Набор из пяти случаев при трёх прогонах на ветку даёт 30 прогонов агента и ещё по три вызова судьи на каждую проверку llm в каждом прогоне. Отсюда советы документации: длинный результат проверять регулярным выражением по файлу, судью оставлять для коротких ответов, а на частых запусках обходиться проверками без судьи и --ablation none.
Не всё раскладывается на проверки. skill-creator прямо пишет, что скилам с субъективным результатом, вроде стиля текста или дизайна, тесты часто не нужны, и их лучше смотреть глазами. На наш взгляд, эвал окупается для скилов, которые срабатывают на каждой задаче или раздаются команде. Личный скил, который вы вызываете раз в неделю, проще проверить, прочитав пару транскриптов.
Начните с малого: два промпта, на которых скил должен сработать, два почти совпадающих, на которых не должен, проверка на вызов скила и одна на результат. Этого хватит, чтобы увидеть, загружается ли скил и меняет ли он хоть что-то.


