Помощник сообщил: «Заявка создана и ответственному отправлено уведомление». Проверка интерфейса показала другое: заявка есть, ответственный не назначен, уведомление осталось черновиком. Красивый финальный текст оказался слабым свидетельством выполненной работы.
В разборе оценки агентов Anthropic различает ход выполнения и итоговое состояние среды. Проверять можно кодом, моделью или человеком, причём эти способы решают разные задачи и требуют подходящих критериев. Anthropic: Demystifying evals for AI agents
Начать с небольшого контракта
Возьмём учебного помощника, который превращает входящее обращение в черновик задачи. Он должен выделить тему, предложить приоритет и сохранить черновик в выбранном проекте. Отправка сообщения человеку в этом сценарии не разрешена.
Успех можно описать без оценки красноречия: создана одна сущность нужного типа, она принадлежит нужному проекту, обязательные поля заполнены, источник сохранён, внешних отправок нет. Если обращение неоднозначно, допустимым результатом становится запрос уточнения вместо выдуманного ответственного.
Такой контракт уменьшает число неявных ожиданий. Команде заранее понятно, какие свойства проверяются автоматически, а где потребуется предметное решение человека.
Собрать примеры, которые меняют решение
В учебном наборе нужны обычное обращение, неполный текст, два похожих запроса, повтор одного сообщения и противоречащая задаче инструкция внутри вложения. Ещё один пример имитирует недоступность инструмента сохранения.
Это не шесть вариантов одного имени. Каждый случай проверяет отдельную границу: извлечение фактов, работу с неизвестным, разделение сущностей, защиту от дублей, недоверенный контекст и поведение при сбое.
Если реальная операция бывает долгой, добавляют остановку и повторный запуск. Иначе помощник может проходить короткие задачи, но дублировать результат после обрыва соединения.
Проверять состояние напрямую
Упрощённый проверяющий код для синтетического результата:
before = {"task-demo-1"}
after = {"task-demo-1", "task-demo-2"}
created = after - before
sent_messages = []
assert len(created) == 1
assert sent_messages == []
Пример иллюстрирует только две проверки. В настоящем наборе изменение связывают с конкретным запуском, проверяют поля, проект и состояние черновика. Простая разница множеств не подходит для общей среды с параллельными пользователями.
Отчёт модели полезен как объяснение, но не как единственный источник истины. Если помощник сказал «сохранил», а запись отсутствует, задача не выполнена. Если сказал «ничего не отправлял», это проверяют по журналу внешних действий, а не повторным вопросом к той же модели.
Отказ — часть правильного поведения
Инструмент может вернуть таймаут после выполненного действия. Повтор должен использовать выбранную защиту от дублей или сначала выяснить состояние операции. Без этого высокий процент успеха на простых примерах будет скрывать дорогие ошибки на сбоях.
Для неоднозначного проекта правильным результатом может быть остановка с конкретным вопросом. Оценщик, который награждает только за наличие готовой задачи, будет подталкивать систему к самовольному выбору. Поэтому допустимые исходы задают отдельно для каждого класса случаев.
Сравнивать версии на одинаковых условиях
Фиксируют набор данных, доступные инструменты и политику разрешений. При смене модели или промпта выполняют тот же набор, сохраняя итоговые состояния и причины отказов. Для стохастического поведения несколько прогонов помогают увидеть разброс, но не доказывают отсутствие всех возможных ошибок.
Полезно отдельно показывать функциональный успех и нарушение ограничений. Средняя оценка способна спрятать редкую неразрешённую отправку среди множества правильно оформленных черновиков. Критичные запреты должны иметь собственный критерий приёмки.
Первый рабочий запуск начинается после такой проверки, с ограниченным контуром и наблюдением за результатом. Цель оценки — понять, на каких задачах автоматизации можно доверять конкретное действие и где системе пока нужен человек.