Перейти к основному содержимому

Предрелизная валидация агентов — это задача инъекции отказов

Чистый трейс доказывает лишь то, что агент справился с запущенными вами случаями. Готовность означает инъекцию отказов, которые породит продакшен, и наблюдение за путём восстановления.

Close-up of a futuristic robotic toy against a gradient background, symbolizing innovation and technology.

Почему просмотр трейса — это не валидация

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

Когда команда просматривает трейс и объявляет агента валидированным, она валидирует выбранный ею набор сценариев, а не среду, с которой агент столкнётся. Проходят те случаи, которые кто-то догадался запустить. Падают в продакшене, по определению, те, которые никто не догадался запустить. Трейс не может их содержать.

Это важно, потому что гейты согласования часто строятся на демонстрационных запусках. Стейкхолдер наблюдает, как агент выполняет задачу, видит чистый трейс и подписывает. Риск, который должен был быть снят на гейте, вместо этого переносится в окно развёртывания, где его дороже наблюдать и труднее откатить. Гейт не снизил риск; он его переместил.

Валидация должна быть активным процессом. Вы не читаете поведение агента и не выводите из него готовность. Вы возмущаете среду и наблюдаете, выдерживает ли путь восстановления агента. Это инъекция отказов, и для агентов это единственная форма валидации, которая даёт свидетельства об отказах, которых вы ещё не видели.

Классы отказов, которые стоит инжектировать

Инъекция отказов для агентов — это не обобщённый chaos-эксперимент. Значение имеют отказы, взаимодействующие с планированием агента, использованием инструментов и памятью. Практичный стартовый набор:

  • Таймауты инструментов. Зависимый API перестаёт отвечать в пределах бюджета таймаута агента. Агент должен решить, повторять ли запрос, переключаться на запасной вариант или прерываться, и он не должен фиксировать план, предполагающий, что результат пришёл.
  • Частичные ответы и дрейф схемы. Инструмент возвращает усечённый payload, или поле меняет тип либо исчезает. Агенты, разбирающие вывод инструмента с неявными допущениями, либо падают, либо, что хуже, молча неверно интерпретируют результат.
  • Истечение учётных данных в середине запуска. Токен истекает после того, как план зафиксирован, но до финальной записи. Агент должен выявить отказ, а не повторять запрос с устаревшими учётными данными или продолжать без авторизации.
  • Отказы в правах доступа после фиксации. Вызов инструмента отклоняется по причинам авторизации, а не доступности. Это иной путь восстановления, чем таймаут, и часто он наступает после того, как агент уже сообщил пользователю, что задача выполняется.
  • Противоречивые инструкции от двух инструментов. Два источника расходятся в одном и том же факте. Агент должен обнаружить конфликт, а не выбрать последний прочитанный.
  • Устаревший контекст, противоречащий свежему retrieval. Кэшированное значение в контексте агента конфликтует со свежим чтением. Агент должен предпочесть свежий источник и обновить своё состояние, а не согласовывать оба в правдоподобный, но неверный ответ.

Detailed view of an aircraft parking brake lever with selective focus in a cockpit.

Что измерять

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

  • Время восстановления. Сколько — по стенным часам или в ходах модели — требуется агенту, чтобы достичь стабильного состояния после отказа. Восстановление, занимающее больше времени, чем собственный дедлайн задачи, — это не восстановление.
  • Шаги, потреблённые на восстановление. Сколько вызовов инструментов и циклов планирования тратится на отказ. Агент, который восстанавливается, но сжигает весь свой бюджет шагов, не оставляет ёмкости на задачу.
  • Терминальное состояние. Завершается ли запуск в безопасном состоянии. Безопасно означает, что побочные эффекты либо зафиксированы корректно, либо не зафиксированы вовсе, и пользователю сообщено, что именно. Запуск, завершающийся частичной записью и сообщением об успехе, — это отказ, независимо от того, насколько изящно он восстановился.
  • Дивергенция траектории. После каждой инжектированной ошибки сравните запланированную траекторию с исполненной. Дивергенция не обязательно плоха, но неизмеренная дивергенция — плоха. Если агент молча меняет план, вы потеряли способность рассуждать о его поведении.

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

Конкретный механизм: харнесс инъекции отказов

Механизм, делающий это воспроизводимым, — это харнесс, располагающийся между агентом и его инструментами. Это не мок. Это прокси, способный применить набор отказов к живым или записанным ответам инструментов.

class FaultInjector:
    def __init__(self, faults, seed):
        self.faults = faults
        self.rng = random.Random(seed)

def wrap(self, tool):
        def call(*args, **kwargs):
            fault = self._select(tool.name)
            if fault == "timeout":
                raise ToolTimeout(tool.name)
            if fault == "schema_drift":
                return self._mutate_schema(tool(*args, **kwargs))
            if fault == "partial":
                return self._truncate(tool(*args, **kwargs))

![White / light blue / purple / dark blue sail; without harness or cover bag; 18ft. 5 1/2in. leading edge long; aluminum and dacron; 1974. In ](/media/delta-wing-phoenix-vi-b-jr-dpla-ee46b416c4-b3f7b0.jpg)

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

## Делая это воспроизводимым

Набор отказов, который не версионируется, — это разовый тест. Набор отказов, который версионируется, — это актив.

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

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

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

## Вопрос валидации

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

Валидация — это не чтение. Это инъекция.
ПоделитьсяXLinkedInПостоянная ссылка5 мин чтения

Связанное чтение

На какие вопросы это отвечает

Why is reading an agent's trace not enough to validate it?

A trace only shows the cases someone chose to run. It cannot contain the failures the environment will produce, so a clean trace validates the scenario set, not the agent's readiness for production.

Which fault classes should be injected first?

Start with tool timeouts, partial responses and schema drift, credential expiry mid-run, permission denials after a plan is committed, conflicting instructions from two tools, and stale context that contradicts fresh retrieval.

What should be measured after each injected fault?

Recovery time, steps consumed by recovery, whether the run terminates in a safe state, and the divergence between the planned and executed trajectory.

How do you keep fault injection repeatable?

Version the fault set alongside the agent, re-run it on every prompt or tool change, and convert each newly discovered production failure into a new fixture rather than a postmortem paragraph.