TL;DR
BLACKSWAN — трёхэтапная процедура предохранительной проверки действий ИИ-агента (Expect → Suspect → Test), которая перехватывает любой вызов инструмента, меняющий состояние внешней среды (запись в базу, перевод денег, оформление заказа, удаление), и целенаправленно ищет опровержения его правильности до того, как действие будет выполнено.
Обычные методы проверки агентов страдают от предвзятости подтверждения: они спрашивают «выполнены ли условия для запуска этого действия?» и ищут факты в его поддержку. Но ошибочное действие легко проходит любую такую проверку: например, получив задачу «раздели вчерашний счёт за ужин между участниками», агент сверяет сумму чека и список гостей в календаре, убеждается, что всё сходится, и выставляет счета — упуская, что один из приглашённых отменил встречу сообщением в мессенджере. А если попросить модель придумывать сомнения и тут же проверять их в одном общем цикле рассуждений, она подстраивает гипотезы под уже видимые данные и выдвигает только те опасения, которые легко отмести.
BLACKSWAN решает обе проблемы за счёт жёсткого разделения ролей во времени: сначала агент формулирует локальное ожидание (Expect) — что именно изменит данный шаг; затем заранее, до любых новых запросов к среде, регистрирует список проверяемых подозрений (Suspect) с привязкой каждого подозрения к конкретной переменной или параметру кода; и только после этого запускает проверку (Test) безопасными запросами на чтение, выполняя действие лишь тогда, когда ни одно подозрение не подтвердилось.
Схема метода
Проверка включается только перед действиями, меняющими состояние среды (write-действиями); безопасные действия на чтение выполняются сразу. Этапы Expect и Suspect изолированы от этапа Test (выполняются отдельными шагами до начала проверочных запросов):
ДЕЙСТВИЕ АГЕНТА (a_t): Если только чтение (read-only) → Выполнить сразу
Если меняет среду (write) → Перехватить и запустить BLACKSWAN:
ШАГ 1 — EXPECT (Ожидание): Контекст + код действия a_t → Локальное утверждение κ_t (какой конкретный результат даст этот шаг для задачи пользователя)
ШАГ 2 — SUSPECT (Пререгистрация подозрений): Контекст + a_t + κ_t → Набор пар S_t = {(s_i, z_i)} (конкретная гипотеза ошибки s_i + элемент кода/параметр z_i, через который она влияет на действие)
ШАГ 3 — TEST (Попытка опровержения): Инъекция списка S_t в диалог → Чтение прошлых наблюдений и запуск read-only запросов → Вердикт по каждой гипотезе: true (ошибка подтверждена) | false (опровергнута) | deferred (нельзя проверить до выполнения)
ШАГ 4 — РЕШЕНИЕ: Все s_i ∈ {false, deferred} → Выполнить исходное действие a_t
Хотя бы одно s_i == true → Заблокировать a_t и сгенерировать исправленное действие a'_t с учётом найденных фактов
Пример применения
Задача: ИИ-агент в корпоративном контуре селлера на Ozon и в CRM «Битрикс24» получил от руководителя задачу: «Верни клиенту деньги за вчерашний проблемный заказ со статусом брака и отправь уведомление». Агент нашёл первый вчерашний заказ клиента и подготовил вызов API возврата средств create_refund(order_id=yesterday_orders[0].id, amount=order.total_price).
Промпт (протокол перехвата и проверки BLACKSWAN для инструкции агента или оркестратора):
Ты — модуль предохранительной верификации действий ИИ-агента по методу BLACKSWAN (Conjecture & Refutation).
Твоя задача — не искать подтверждения тому, что действие верное, а попытаться ОПРОВЕРГНУТЬ его перед выполнением любого вызова, меняющего данные (write).
Задача пользователя: "Верни клиенту деньги за вчерашний проблемный заказ со статусом брака и отправь уведомление."
Перехваченный write-вызов (a_t):
```python
orders = get_client_orders(client_id=4821, date="yesterday")
target_order = orders[0]
refund_sum = target_order["total_price"]
create_refund(order_id=target_order["id"], amount=refund_sum)
send_message(client_id=4821, text=f"Оформили возврат {refund_sum} руб. по заказу {target_order['id']}")
orders[0], target_order["total_price"]).
- s_i: конкретное условие в среде, при котором из-за элемента z_i действие окажется ошибочным (например: у клиента вчера было несколько заказов, и бракованным является не orders[0]; в заказе бракован только один товар, а не вся сумма total_price; возврат по этому заказу уже был оформлен ранее в тикете поддержки).
true — наблюдения подтверждают ошибку;
- false — наблюдения полностью исключают это подозрение;
- deferred — проверить без фактического запуска write-вызова невозможно.
Правило решения:
- Если ВСЕ подозрения получили статус false или deferred → разреши запуск исходного кода a_t.
- Если ХОТЯ БЫ ОДНО подозрение получило статус true → заблокируй a_t и напиши исправленный код a'_t, устраняющий найденное противоречие.
**Результат:**
На первом шаге модель зафиксирует ожидание (возврат полной стоимости первого вчерашнего заказа). На втором — выделит привязанные к коду узкие места: индекс `orders[0]` (может быть не тем заказом), поле `total_price` (частичный брак вместо полного возврата) и статус обращения в чате поддержки. На третьем шаге агент сформирует проверочные запросы на чтение деталей заказа и сообщений клиента, выставит вердикты `true/false/deferred` по каждому пункту и при обнаружении расхождения перепишет вызов возврата на точный ID бракованной позиции.
---
### Почему это работает
У языковых моделей при работе с инструментами есть хроническая слабость — **туннельное зрение и инерция траектории**. Когда агент уже построил план и написал черновик вызова API, любая проверка в духе «проверь, правильно ли выбраны параметры» опирается на ту же самую картину мира, которая породила ошибку. Модель проверяет те факты, которые уже лежат в её контексте (например, что заказ существует и сумма положительная), видит, что всё сходится, и смело нажимает «Выполнить». Неучтённый контекст — отмена в соседнем канале связи, второй однотипный заказ за тот же день, скрытое ограничение в профиле — остаётся за кадром, потому что агент не искал то, что может сломать его гипотезу.
В то же время LLM отлично справляются с **критическим анализом конкретного кода и точечной проверкой фактов**, если задать им правильный вектор поиска и жёсткие рамки. Когда задача ставится по принципу Карла Поппера — не подтвердить правоту, а **найти «чёрного лебедя» (факт-опровержение)**, — модель переключается из режима оправдания своего черновика в режим целенаправленного аудита.
**BLACKSWAN** превращает этот принцип в надёжную механику с помощью **двух ключевых ограничений**:
1. **Привязка подозрений к элементам кода `(s_i, z_i)`:** Модель не имеет права генерировать размытые страхи вроде «вдруг мы что-то забыли». Каждое подозрение обязано ссылаться на конкретную переменную, срез массива (`yesterday_orders[0]`, `dates[0]`) или аргумент API. Это заставляет модель проверить происхождение каждого значения в коде.
2. **Пререгистрация гипотез до начала проверок (Preregistered Suspicions):** Как в строгой науке гипотезы регистрируют до сбора данных, этап **Suspect** выполняется строго до того, как агент сделает хотя бы один проверочный запрос к среде. Если смешать выдвижение подозрений и их проверку в один цикл, модель начинает хитрить и выдвигает только те сомнения, ответ на которые уже знает. Изоляция этапа обязывает этап **Test** дать явный вердикт (`true`, `false` или `deferred`) по каждому зарегистрированному подозрению, не позволяя «забыть» неудобную гипотезу.
**Рычаги управления методом:**
- **Фильтр перехвата** → включайте **BLACKSWAN** только на действиях записи (`write` / `POST` / `DELETE` / отправка сообщений / оплата), пропуская чтение без проверок — это бережёт токены на безопасных шагах.
- **Статус `deferred`** → сохраняйте третий вариант вердикта для технических рисков, которые нельзя проверить заранее (например, временный сбой внешнего сервера), чтобы агент не зависал в бесконечных попытках проверить непроверяемое.
- **Глубина подозрений** → ограничьте число пар `(s_i, z_i)` до 2–4 самых критичных переменных вызова, чтобы агент проверял только существенные допущения.
---
### Шаблон промпта
Этот шаблон можно встроить в системную инструкцию агента (`CLAUDE.md`, `AGENTS.md`), оформить как перехватывающий хук (`PreToolUse`) или использовать в цепочке автоматизации перед выполнением ответственных действий:
```xml
ПРАВИЛО ПЕРЕХВАТА: Перед выполнением любого действия, меняющего состояние среды ({список_опасных_действий}), ОСТАНОВИ выполнение и пройди 3 шага верификации:
ШАГ 1 — EXPECT (Локальное ожидание):
Запиши черновик действия `a_t`. До любых новых проверок сформулируй `κ_t`: какой именно локальный эффект произведёт `a_t` и как он решает задачу `{задача_пользователя}`.
ШАГ 2 — SUSPECT (Пререгистрация фальсификаторов):
Опираясь только на текущий контекст, `a_t` и `κ_t`, выпиши список проверяемых подозрений `S_t = {(s_1, z_1), ..., (s_k, z_k)}`:
- `z_i`: конкретная переменная, индекс, фильтр или параметр в `a_t`.
- `s_i`: конкретный сценарий, при котором `z_i` приведёт к неверному результату или нарушит неявный контекст задачи.
ВАЖНО: Не запускай никаких инструментов на этом шаге! Сначала зафиксируй полный список `S_t`.
ШАГ 3 — TEST (Проверка наблюдениями и вердикт):
Ответь на запрос: "Я подозреваю, что выполнение этого действия ошибочно по следующим причинам: {S_t}. Пожалуйста, проверь по фактам, имеет ли место каждая из них."
Используй уже собранные наблюдения или вызови безопасные инструменты ТОЛЬКО НА ЧТЕНИЕ ({инструменты_чтения}), чтобы проверить каждое `s_i`.
Вынеси вердикт `v_t(s_i)` для каждого пункта:
- `true` — найдены факты, подтверждающие ошибку `s_i`;
- `false` — факты опровергают подозрение `s_i`;
- `deferred` — проверить до фактического запуска `a_t` невозможно.
ПРАВИЛО ЗАПУСКА:
- Если для ВСЕХ `s_i` вердикт `false` или `deferred` → выполни `a_t`.
- Если ХОТЯ БЫ ДЛЯ ОДНОГО `s_i` вердикт `true` → отмени `a_t`, напиши исправленное действие `a'_t` с учётом найденных фактов и повтори проверку.
Что подставлять в плейсхолдеры:
- {список_опасных_действий} — типы операций, где ошибка стоит дорого: запись в БД, изменение файлов, отправка писем/сообщений, финансовые транзакции, закрытие задач.
- {задача_пользователя} — исходное поручение человека.
- {инструменты_чтения} — доступные агенту безопасные команды (GET-запросы, поиск по логам/почте/чатам, git status, SELECT).
🚀 Быстрый старт — вставь в чат:
Вот шаблон протокола верификации агентов BLACKSWAN. Адаптируй под мою задачу: [твоя задача].
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит, какие действия в вашей системе меняют внешнее состояние (write-вызовы), какие безопасные инструменты чтения доступны агенту для проверки и какие типичные ошибки из-за неполного контекста он допускает — потому что для работы метода нужно чётко разделить мутирующие команды и проверочные read-only зонды.
Оригинал из исследования
В оригинальной реализации исследователи разделяют генерацию подозрений и их проверку: после того как этапы Expect и Suspect сформировали список привязанных к коду подозрений $S_t = {(s_1, z_1), \dots, (s_k, z_k)}$, невыполненное действие $a_t$ добавляется в историю, а на вход агенту подаётся специальное пользовательское сообщение, запускающее фазу Test:
Task: "By when should everything from yesterday's order arrive?"
# Proposed write action (a_t):
orders = show_orders(sort_by="-created_at", page_limit=20)
yesterday_orders = [o for o in orders if created_on(o) == yesterday]
order = yesterday_orders[0]
dates = [parse(i["expected_delivery_at"]) for i in order["order_items"]]
answer = dates[0].strftime("%d-%m")
complete_task(answer=answer)
# Code-grounded suspicions (S_t):
- (s_1, yesterday_orders[0]): Was there another order placed yesterday besides yesterday_orders[0]?
- (s_2, i["expected_delivery_at"]): Is any order item missing an expected delivery date?
- (s_3, dates[0]): Should the final answer be the latest delivery date among items (max(dates)) rather than dates[0]?
# User-role message injected for TEST stage (o_t):
"I'm suspicious of executing this action for the following reasons: S_t. Please verify whether each of them is the case."
# Verdict rules (v_t):
v_t(s_i) = true if observations confirm s_i
v_t(s_i) = false if observations dismiss s_i
v_t(s_i) = deferred otherwise
If ∀ s_i ∈ S_t : v_t(s_i) ∈ {false, deferred} => execute a_t
If ∃ s_i ∈ S_t : v_t(s_i) = true => withhold a_t and draft a'_t
Контекст: Авторы показали на примере из бенчмарка AppWorld, как привязка подозрений к элементам кода (yesterday_orders[0] и dates[0]) заставляет агента заметить классическую логическую ошибку: чтобы ответить на вопрос «к какому числу приедет всё из вчерашнего заказа?», нужно брать самую позднюю дату доставки среди всех позиций, а не нулевой элемент списка dates[0].
Ограничения
⚠️ Рост расхода токенов и числа вызовов API: Из-за дополнительных шагов выдвижения гипотез и проверочных запросов на чтение метод увеличивает объём генерируемых токенов и стоимость API-вызовов примерно в полтора-два с половиной раза по сравнению с базовым агентом без проверок.
⚠️ Не ловит ошибки в задачах без изменения среды: Поскольку перехват срабатывает только перед действиями записи (
write), метод не проверяет чисто аналитические рассуждения, если в конце нет явного вызова финального действия или сохранения ответа.
⚠️ Зависимость от наличия read-only инструментов: Чтобы этап Test мог опровергнуть подозрение фактами, среда должна предоставлять агенту безопасные способы чтения состояния (поиск, просмотр списков, чтение сообщений) без побочных эффектов.
Как исследовали
Команда протестировала BLACKSWAN на трёх агентных средах с совершенно разным устройством инструментов: флагманском бенчмарке AppWorld (457 API в 9 симулированных приложениях, 168 обычных и 417 повышенной сложности задач challenge, где проверяется прохождение до 22 юнит-тестов на задачу и отсутствие побочных повреждений базы данных), онлайн-магазине WebShop (500 тестовых задач с кликами и поиском) и текстовой среде ALFWorld. В качестве базовых моделей взяли Qwen3.5-27B (в режимах с включённым и выключенным размышлением thinking), а также проверили переносимость на компактной Qwen3-4B-Thinking-2507 и крупных MoE-моделях MiniMax M2.7 и GLM-5.3-Flash, сравнивая свой метод с базовым ReAct, методом предварительного накопления плейбуков ACE и новейшим методом подтверждающей верификации ACCORD (который тоже делает read-only запросы перед записью, но ищет подтверждения, а не опровержения). Результаты оказались разгромными: на самом трудном сплите AppWorld Challenge метод BLACKSWAN превзошёл сильнейший бейзлайн на +14.9 процентных пункта с включённым режимом размышлений (84.7% выполненных задач против 69.8% у ACCORD† и 58.4% у ReAct) и на +25.2 п.п. без режима размышлений (81.5% против 56.3% у ACE, 55.0% у ACCORD и 48.0% у ReAct). Удивительнее всего то, что BLACKSWAN с выключенным режимом thinking (81.5%) уверенно обогнал все конкурирующие методы с включённым thinking (максимум 69.8%), а при полном отсутствии обучающих примеров в промпте (0-shot) выиграл у всех бейзлайнов, которым дали по 3 детальных примера — доказав, что правильное направление проверки (поиск опровержений) важнее объёма «размышлений» модели; кроме того, на WebShop метод дал прирост +12.7 п.п. (50.8% против 38.1% у ReAct), а абляция (Таблица 3) подтвердила, что вынесение подозрений в отдельный пререгистрированный шаг даёт 81.6% успеха против 72.7% при проверке «в уме» и 76.0% при поиске подтверждений.
Адаптации и экстраполяции
💡 Адаптация для вайб-кодинга и ИИ-разработки (Claude Code / Cursor): Защита от поломки кодовой базы перед редактированием файлов и миграциями
Вставьте облегчённую версию протокола в
CLAUDE.mdилиAGENTS.md, чтобы агент перед любым массовым рефакторингом, удалением кода или изменением схемы БД сначала пытался опровергнуть свой патч:## Правило BLACKSWAN перед изменением кода и конфигурации Перед применением патча к существующим файлам, изменением схемы БД или запуском деплоя выполни 3 шага: 1. **EXPECT:** Опиши в 1 предложении, какое именно поведение изменит этот патч. 2. **SUSPECT:** Выпиши 3 пары `(подозрение, символ_кода)`: какая функция, импорт или внешний вызов сломается из-за этого изменения (например, «вызов `parse_stem` в `agent_push.py` передаёт 3 аргумента вместо 2»). 3. **TEST:** Проверь каждое подозрение через `grep` / чтение связанных файлов и поставь вердикт `true | false`. Применяй правку только тогда, когда все подозрения получили статус `false`.
Ресурсы
- Работа: Action Verification through Conjecture and Refutation for Language Model Agents (arXiv:2611.02950v1, ноябрь 2026)
- Бенчмарки и базовые фреймворки: AppWorld (Trivedi et al., 2024), WebShop (Yao et al., 2022), ALFWorld (Shridhar et al., 2021), ACE (https://github.com/ace-agent/ace)
- Авторы и институты: Minhyeon Oh, Chiyeong Heo, Geonwoo Noh, Jangwon Son, Jungseul Ok (Pohang University of Science and Technology — POSTECH), Hoyoung Kim (National AI Research Lab)
