TL;DR
Если агент со скилом выдал правильную цифру, это ещё не значит, что он сделал всё правильно. Внутри трассы вызовов (журнала: какие инструменты агент вызвал, с какими аргументами и в каком порядке) часто видны нарушения. Авторы предлагают проверять не только результат, но и процесс: нужные ли инструменты вызваны, с теми ли аргументами, в нужном ли порядке, с полным ли охватом. Эталон для сравнения считается отдельно от агента, а не берётся из его же ответа.
Главная находка: почти все прогоны, где итоговая цифра сошлась, содержали хотя бы одно отклонение в процессе. Агент пропускал обратное чтение данных из базы, вызывал инструменты не с тем охватом и дублировал вызовы. Он сдавал «правильный» результат, а по дороге ломал правила, которые вы прописали в скиле. Если проверять только итог, такие отклонения не видны. Они вылезут позже, когда данные чуть изменятся, а ответ уже «случайно правильный» не получится.
Метод состоит из пяти стадий: записать вход и трассу, посчитать эталон независимо, развернуть шаблонные проверки в конкретные, прогнать проверки, свести каскад ошибок к первопричинам. Шаблонные проверки используют плейсхолдеры (подстановки, которые подтягивают ожидаемые значения в момент проверки), поэтому набор тестов переживает смену данных, модели и версии скила.
Схема метода
СТАДИЯ 1: Записать входные параметры + вытащить трассу вызовов → лог запуска
СТАДИЯ 2: Посчитать эталон отдельным путём (не через агента) → ожидаемые значения
СТАДИЯ 3: Развернуть шаблонные проверки с плейсхолдерами → конкретные проверки на этот запуск
СТАДИЯ 4: Прогнать проверки (итог + процесс) → пройдено / провалено
├─ инструменты: нужные вызваны, лишних нет
├─ аргументы: даты, фильтры, числа
├─ порядок: получить → сохранить → прочитать обратно → посчитать → записать
└─ охват: ничего не пропущено, ничего не вызвано с чужим значением
СТАДИЯ 5: Свести каскад провалов к корневым причинам → короткий список «что чинить»
В статье стадии 2–5 реализованы кодом, а гибкие проверки отдавались узкому LLM-судье. В чате или у агента без кода можно воспроизвести логику стадий 3–5. Она показана ниже в шаблоне.
Пример применения
Задача: В компании в Claude Code работает скил «Распределение расходов Yandex Cloud по продуктовым командам». Он тянет данные биллинга по трём кластерам, пишет промежуточные данные в таблицу, читает их обратно, считает долю каждой команды (CPU 40%, память 40%, запросы 20%) и записывает итог. Вы только что сократили SKILL.md, потому что он «слишком длинный». Итоговая сумма сходится. Нужно понять, не сломался ли процесс.
Промпт:
Ты аудитор процесса агента. Тебе дают журнал вызовов скила и эталонные
значения, посчитанные отдельно. Ты проверяешь, ЧТО агент делал,
а не только какое число получилось.
$clusters = [prod-msk, prod-spb, stage]
$date_from = 2026-05-01
$date_to = 2026-05-15
$expected_calls_per_cluster = 1
$expected_total_rub = 4 820 000
$teams = 9
- id: tools_required
check: вызваны get_billing, stage_data, read_back, write_result
- id: tools_irrelevant
check: нет вызовов инструментов вне списка разрешённых
- id: args_dates
check: у каждого вызова get_billing даты = $date_from..$date_to
- id: scope_clusters
check: get_billing вызван ровно по каждому из $clusters, по $expected_calls_per_cluster раз
- id: order
check: порядок get_billing → stage_data → read_back → allocate → write_result
- id: readback_done
depends_on: tools_required
check: после stage_data был read_back, и данные для расчёта взяты из него
- id: allocation_matches
depends_on: readback_done
check: расчётные доли совпадают с записанными, сумма = $expected_total_rub
1. Для каждого тест-кейса: найди в журнале подтверждение, приведи цитату вызова.
2. Отметь PASS или FAIL.
3. Если кейс с depends_on провален из-за провала зависимости — пометь
CASCADE, не считай отдельной ошибкой.
4. Итог проверяй отдельно от процесса: даже если сумма верна, провал
в процессе остаётся провалом.
Таблица: id | PASS/FAIL/CASCADE | цитата из журнала.
Затем: «Корневые причины» (только FAIL без CASCADE) и «Итог сошёлся: да/нет».
Не предлагай исправления, пока не выведена таблица.
Журнал вызовов:
{журнал}
Результат: Модель выдаст таблицу с вердиктом по каждой проверке и цитатой из журнала. Отдельно будет список корневых причин, где каскадные провалы свернуты в одну строку. Отдельная строка покажет, сошёлся ли итог. Если новая короткая версия скила пропускает обратное чтение, это будет видно как провал readback_done и каскад на allocation_matches, хотя сумма может быть верной.
Почему это работает
Слабость. Агент идёт к цели по своему усмотрению на неоднозначных шагах. Если спецификацию сократили, обновили модель или сменили оболочку агента (Claude Code, Codex), он может принять другое решение: пропустить шаг, вызвать лишний инструмент, сузить охват. Итоговая цифра при этом может сойтись, а проверка «ответ верный?» это одобрит.
Сильная сторона. У каждого шага остаётся след в трассе, и по нему можно проверять правила: был ли вызов, с какими аргументами, до или после другого. Такие проверки точнее, чем «ответ выглядит правдоподобно». Эталон считается независимо от агента, поэтому ему нельзя «подыграть».
Как метод использует это. Проверки формулируются как шаблоны с подстановками. Один набор работает на любых данных, моделях и версиях спецификации. Зависимости между проверками (depends_on) сворачивают десяток симптомов в две-три причины: в статье в среднем 6 проваленных проверок на запуск сводились к 2–3 корням, примерно на 58% меньше работы на диагностику.
Рычаги управления:
- Список проверок → добавь свои инварианты (порядок, охват, запрет инструментов) под конкретный скил.
- depends_on → чем точнее цепочки зависимостей, тем короче список первопричин.
- Плейсхолдеры → вынеси даты, список кластеров, суммы наружу, и тест не придётся переписывать при смене данных.
- Строгость проверки → точное сравнение для чисел и структуры, гибкая оценка (LLM-судья) только там, где формулировки допускают варианты, например эквивалентные запросы SQL.
- Источник эталона → считай его отдельным путём, а не просьбой к другой модели «а как правильно».
Шаблон промпта
Ты аудитор процесса агента. Тебе дают журнал вызовов скила и эталонные
значения, посчитанные отдельно. Ты проверяешь, ЧТО агент делал,
а не только какой итог получился.
{эталонные_значения: список подстановок вида $имя = значение}
- id: {id_проверки_1}
check: {что_должно_быть_в_журнале: инструмент / аргумент / порядок / охват}
- id: {id_проверки_2}
depends_on: {id_проверки_1}
check: {что_проверяем}
- id: итог
check: {финальное_значение} = $эталон
1. Для каждого тест-кейса найди в журнале подтверждение и процитируй вызов.
2. Отметь PASS или FAIL.
3. Если кейс с depends_on провален из-за зависимости — отметь CASCADE.
4. Итог проверяй отдельно: верный итог не отменяет провал процесса.
Таблица: id | PASS/FAIL/CASCADE | цитата.
Затем «Корневые причины» (FAIL без CASCADE) и «Итог сошёлся: да/нет».
Журнал вызовов агента:
{журнал}
Что подставлять:
- {эталонные_значения} считай отдельно от агента: скриптом, в таблице или руками. Не проси сам же агент вычислить эталон.
- {что_должно_быть_в_журнале} бери из своего SKILL.md: каждое «обязательно», «сначала», «не вызывай» становится проверкой.
- {журнал} бери из лога сессии агента (в Claude Code это история вызовов инструментов).
🚀 Быстрый старт — вставь в чат:
Вот шаблон аудита процесса агента. Адаптируй под мой скил: {опиши скил в двух-трёх предложениях}.
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, какие шаги в скиле обязательны, в каком порядке и какие инструменты разрешены. Ещё она спросит, чем считать эталон. Эти ответы нужны, чтобы превратить правила из SKILL.md в проверяемые тест-кейсы с зависимостями.
Ограничения
⚠️ Нужна инфраструктура для полного метода: в статье эталон считался отдельным скриптом по живым API, а трасса снималась из логов оболочки. Без кода и доступа к данным вы воспроизведёте только логику проверки (шаблон выше), а не полный автоматический конвейер.
⚠️ Отклонение ≠ подтверждённый дефект: проверки написаны авторами заранее. Провал показывает, что агент отошёл от задуманного процесса, но не доказывает, что это навредило. Авторы сами говорят, что серьёзность отклонений не оценивали.
⚠️ Нельзя сказать «.txt хуже .md»: две версии спецификации различались сразу по формату, длине и содержанию. Это чувствительность к полной правке, а не эффект формата.
⚠️ Один контекст и малые выборки: одна компания, один портфель из девяти приложений, по десять прогонов на ячейку. Доверительные интервалы для сравнения версий не скорректированы на множественные сравнения, авторы называют их разведочными.
⚠️ Долгосрочная устойчивость не проверена: тесты переиспользовались при смене модели, оболочки и версии спецификации. Реальная эволюция API во времени остаётся задачей на будущее.
⚠️ Судья — не истина: LLM-судья применялся точечно и совпал с оценкой авторов в 57 случаях из 60. Это снижает риск, но не убирает его.
⚠️ Текст материала обрезан: в доступном тексте нет окончания раздела результатов (чувствительность к версии спецификации разобрана не до конца) и общих выводов.
Как исследовали
Авторы из IBM взяли два рабочих скила корпоративной системы, которая распределяет выручку и затраты между девятью приложениями по CPU, памяти и числу вызовов. Каждый скил прогнали с двумя версиями инструкции (полная SKILL.md и сокращённая Skill.txt), в двух оболочках агента (Claude Code и Codex), на трёх моделях, по 10 прогонов на ячейку: всего 240 запусков. Идея была простой: сначала оценить, сошёлся ли итог, а потом проверить 104 (выручка) и 80 (продуктивность) шаблонных правил процесса. Эталон считался отдельно, через те же живые API, но по независимому пути. Так проверка не зависела от того, что «думает» сама модель.
Результат неприятный. Итог сошёлся в 175 запусках из 240. Но в 162 из них (около 93%) были отклонения процесса. Во всех 120 запусках скила по выручке итоговая цифра была верной, и во всех нашлось что-то не то. Чтобы отмести версию «просто слишком строгий набор проверок», авторы расширили «итог» до семи проверок финального состояния. Отклонения в траектории остались у 151 из 164 прошедших. Они также убрали проверку на «лишние инструменты», самую спорную: картина не изменилась.
Любопытно, как поведение зависит от конфигурации. Сокращение спецификации почти не повлияло на GPT-5.6-Sol в Claude Code (около −1 п.п.), но у других пар модель-оболочка просадка доходила примерно до 10–13 п.п. Одна и та же правка инструкции может быть безвредной в одной связке и ломающей в другой. Практический вывод: после любой правки скила, смены модели или оболочки прогоняй проверки процесса, а не только итога.
Адаптации и экстраполяции
🔧 Техника: добавь в первый шаг скила строку про журнал → получишь материал для проверки
В статье стадия 1 — одна строка, добавленная в первый шаг скила. Агент записывает все разобранные входные параметры в структурированный лог, чтобы потом сверить, что он понял задачу так, как вы её задали. В SKILL.md это может выглядеть так:
Шаг 1. Разбери входные параметры (период, список кластеров, сумма)
и ЗАПИШИ их в run_log.json до начала любых вызовов инструментов.
Экстраполяция (из вывода статьи о чувствительности к правкам спецификации, не проверялась авторами в таком виде):
Я меняю SKILL.md: {что меняю}. Вот журналы 5 запусков ДО правки и 5 ПОСЛЕ.
Сравни траектории: какие шаги пропадают, появляются, меняют порядок?
Для каждого отличия укажи, к какому правилу из скила оно относится.
{журналы}
Ресурсы
- Работа: Continuous Process-Level Evaluation for Evolving Enterprise AI Agent Skills — Ngoc Phuoc An Vo (IBM), Aarya Doshi (Georgia Institute of Technology), Vadim Sheinin (IBM). NeurIPS 2026, воркшоп Continual Learning for Enterprise AI Agents (CLEA).
- Связанные работы из статьи: AgentEval (Guo et al., 2026, граф зависимостей проверок), GroundEval (Flynt, 2026, детерминированная проверка вместо LLM-судьи), Huang et al., 2025 (ошибки эталонов, сгенерированных LLM, на HumanEval), Lightman et al., 2024 (пошаговый контроль в математических рассуждениях).
