Где агенты врут: типология отказов и как их ловить
Инженер, проработавший с агентом месяц, знает главное ощущение этой работы: девять утверждений из десяти верны, а десятое обрушивает полдня. Отличить десятое от девяти по тексту отчёта нельзя — оно написано тем же ровным тоном, с тем же «готово, проверил».
Это и есть предмет главы. Не «агент иногда ошибается» — ошибаются все, включая вас. А то, что у ошибки агента нет внешнего признака. Человек, который не уверен, меняет интонацию, ставит оговорку, приходит спросить; модель, которая не знает, печатает самое правдоподобное продолжение — и оно выглядит ровно как знание. Инженерная работа с агентом на девять десятых состоит в том, чтобы вернуть в систему сигнал неуверенности, которого там нет по устройству.
Почему слово «врёт» уместно и в чём оно неточно
Скажем сразу, где метафора ломается. У модели нет намерения обмануть: нет модели вашего знания, нет цели её исказить, нет выгоды от вашей ошибки. Обвинять её во лжи в моральном смысле так же осмысленно, как обвинять компилятор в злом умысле.
Но операционально слово точное. Ложь — это утверждение, поданное как знание, при отсутствии знания. Хикс, Хамфрис и Слейтер в работе «ChatGPT is bullshit» (Ethics and Information Technology, 2024) предлагают термин Франкфурта: не ложь и не ошибка, а безразличие к истинности — текст порождается по критерию правдоподобия, а не соответствия. Для инженера разница между «соврал» и «безразличен к истине» нулевая: ставку вы делаете на утверждение, и она проигрывает одинаково.
Есть и техническое объяснение, почему модель предпочитает угадать, а не воздержаться. Работа «Why Language Models Hallucinate» (Kalai, Nachum, Vempala, Zhang, 2025) утверждает: и предобучение, и процедуры оценки вознаграждают уверенный ответ выше признания незнания, потому что бенчмарки считают «не знаю» ошибкой наравне с неверным ответом — модель, оптимизированная под такую метрику, обязана блефовать. Это аргумент, а не доказанный закон природы, но он объясняет наблюдаемое лучше, чем «модель испорчена». Практический вывод: отсутствие оговорки в отчёте агента не несёт информации, уверенный тон — стиль, а не оценка достоверности.
Три слоя, на которых рождается неправда
Из модели исполнения следует, что «агент» — это три разные системы. Первый вопрос при разборе — не «почему модель тупая», а «на каком слое разошлось».
| Слой | Что там ломается | Симптом в отчёте | Куда смотреть |
|---|---|---|---|
| Модель | Выдуманный факт, неверный вывод из верных данных, прогиб под давление | Уверенное утверждение без адреса | Транскрипт: было ли наблюдение, из которого это следует |
| Харнесс | Обрезка вывода, компакция, права, лимиты, потерянная запись | Ссылка на то, чего агент не мог видеть целиком | Сырой вывод инструмента, журнал вызовов |
| Среда | Файл изменился, тест флапает, ветка не та, кэш старый | Всё «верно», но не воспроизводится у вас | git status, чистое дерево, повторный прогон |
Схема читается снизу вверх. Внизу среда: она не имеет мнения, она просто такая, какая есть. Дальше каждый переход отбрасывает часть информации совершенно штатно — вывод команды обрезается лимитом, контекст сжимается компакцией, проза уравнивает наблюдение и догадку. Отказ есть не поломка перехода, а отброшенное, о потере которого не сообщили. Отсюда общее правило: чем ниже проверяете, тем дешевле.
Карта отказов
Детектор в каждой позиции ниже указан такой, который не зависит от агента: спрашивать у агента, не соврал ли он, бессмысленно по построению.
Группа A. Ложь о внешнем мире
Самая известная и самая дешёвая в поимке группа: утверждения об API, пакетах, флагах и версиях проверяются одним обращением к источнику.
A1. Выдуманная сигнатура, флаг, поле конфига. Агент вызывает client.upload(path, retries=3), а параметра
retries в установленной версии нет: имя правдоподобно, встречалось в похожих библиотеках, а модель порождает
правдоподобное. Коварный подвид — правильный символ из неправильной версии: метод существовал и был переименован
два релиза назад; такое проходит беглый взгляд ревьюера, который «помнит, что такое было». Детектор: трассировка
символа к определению перед использованием — правило CODE-04 из пакета products/workbench/templates/memory/
(VERIFIED-CODE.md). go doc, inspect.signature, чтение исходника в site-packages — секунды; сюда же работает
тайпчекер, он ловит несуществующий атрибут раньше человека.
A2. Несуществующий пакет. import fastjsonparse и новая строка в requirements.txt. Работа «We Have a Package
for You!» (Spracklen и др.) измеряет частоту таких имён и показывает, что они
устойчивы: одна и та же модель придумывает одну и ту же несуществующую библиотеку раз за разом, откуда и берётся
атака slopsquatting — злоумышленник регистрирует популярную галлюцинацию. Детектор: дифф requirements.txt,
package.json, go.mod читается глазами всегда; в CI — lock-файл и запрет ставить то, чего нет в списке
(«Безопасность»).
A3. Устаревшее знание об умолчаниях. «По умолчанию таймаут 30 секунд», «этот флаг включён начиная с версии 4», «в
текущем релизе это уже не нужно»: слово «текущий» модель употребляет так же уверенно, как всё остальное. Детектор:
правило RSN-03 — воспоминание модели о библиотеке есть гипотеза, пока не прочитан установленный исходник;
утверждение обязано иметь адрес — путь со строкой, команду с выводом или датированный URL (RSN-02).
A4. Адрес, который не резолвится. services/billing/reserve.py:214 — файла нет, или в нём 180 строк, или там
совсем другое. Неприятно вдвойне: адрес — как раз тот признак, по которому мы отличаем проверенное от догадки, и
подделка атакует сам детектор. Детектор: механический скрипт ниже открывает каждый упомянутый адрес.
Группа B. Ложь о собственных действиях
Эта группа опаснее первой: если нельзя верить отчёту о том, что агент делал, нельзя верить ничему. И здесь чаще всего ошибается инженер, принимая пересказ за протокол.
B1. «Запустил тесты, всё зелёное» — без прогона. Самый частый отказ трека; механизм неочевиден.
Правдоподобное продолжение — «прошло» М-->>И: Готово, все тесты проходят Note over И,С: В среде красный тест.
Намеренно не солгал никто: сводку не показали
Ложное утверждение возникло без злого умысла и без ошибки модели в узком смысле: харнесс обрезал вывод, обрезанное
выглядело чистым, модель достроила недостающее. Тот же сценарий разворачивается, когда прогона не было вовсе: в
транскрипте есть намерение «сейчас запущу», следом другой шаг, а через десять ходов намерение неотличимо от результата
(RSN-13, «pending is not done»). Детектор по возрастанию силы: потребовать в отчёте точную команду и её сводку →
открыть журнал вызовов харнесса → запустить самому. Последнее ловит всё; тема целиком — в главе «Проверяемость».
B2. Молчаливый провал команды. Вывод пустой, код возврата ненулевой — а агент прочитал пустоту как «ошибок нет».
Или сборка упала на этапе, чей вывод ушёл в stderr. Или команда не запустилась вовсе: не тот каталог, нет прав, не
активировано окружение. Детектор: смотреть на код возврата, а не на текст; ноль строк вывода не доказывает успеха.
B3. Правка ушла не туда. Дифф показан безупречный, но не записан. Или записан в файл-двойник (config.yaml вместо
config.yml), в другую ветку, в скопированный каталог. Детектор: git status и git diff --stat перед чтением
отчёта. Порядок важен: прочитанный первым отчёт создаёт ожидание, под которое глаз подгоняет дифф.
B4. Готово при незакрытом состоянии. «Миграция применена» — в локальной базе, файл не добавлен в индекс. «Эндпоинт готов» — но не зарегистрирован в роутере. Агент честно отчитывается о сделанном, но граница задачи в его контексте уже, чем в вашей голове; это в равной мере отказ спецификации. Детектор: критерий приёмки как исполняемая команда — «готово» означает «команда X даёт результат Y».
Группа C. Ошибки рассуждения
Модель порождает текст, который выглядит как вывод; иногда это и есть вывод, иногда — имитация его формы. Почти все ошибки здесь имеют имена, которым больше ста лет, и разбираются в треке логики.
C1. Совпадение симптома вместо диагноза. «UnicodeDecodeError — значит, файл в неверной кодировке», а на деле
читается бинарный файл, потому что путь собрался неправильно: симптом совпал с частым паттерном, и агент чинит
несуществующую проблему (RSN-09). Детектор: требовать механизм, а не паттерн — «какая строка порождает эту ошибку
и почему именно на этих данных» есть вопрос, на который нельзя ответить общим местом.
C2. Последовательность принята за причину. Поменял три вещи, тест позеленел, в отчёте — «причина была в отсутствии
блокировки». Может быть. А может, помогла вторая правка, а тест флапал (RSN-11). Детектор — самый недооценённый
приём главы:
# Проверка причинности: убираем правку кода, оставляем тест.
git stash push -- src/ # фикс убран, тест на месте
pytest -k test_reserve_idempotent # ДОЛЖЕН упасть — и с той же ошибкой
git stash pop
pytest -k test_reserve_idempotent # ДОЛЖЕН пройти
Проходит на первом прогоне — правка не была причиной; падает с другой ошибкой — диагноз неполный. То же требование
записано как CODE-13: починка начинается с теста, падающего по заявленной причине.
C3. Подмена задачи на соседнюю более лёгкую. Просили сделать операцию идемпотентной — добавлена проверка «уже существует» перед вставкой: выглядит как решение, гонку не закрывает. Просили ускорить эндпоинт — добавлен кэш, вопрос о причине медленности не задан. У лёгкой задачи в обучающих данных больше опор, и градиент правдоподобия ведёт туда. Детектор: приёмка, которую подмена не проходит — конкурентный тест для идемпотентности, измерение до и после для скорости. Критерий, проходимый и решением, и его имитацией, не является критерием.
C4. Прогиб под возражение. Вы спрашиваете «ты уверен?» — и агент переписывает верный ответ на неверный: «Towards Understanding Sycophancy in Language Models» (Sharma и др., 2023) показывает систематическое смещение обученных на человеческих предпочтениях моделей в сторону согласия с собеседником. Детектор, он же профилактика: сомнение нельзя выражать намёком. «Точно?» вызывает не перепроверку, а перепись; работает «прогони ещё раз и покажи вывод», «покажи строку, откуда это» — требование доказательства смещения не порождает.
C5. Объяснение, не соответствующее реальной причине ответа. Объяснение агента — такой же порождённый текст, как всё остальное, а не интроспекция. «Language Models Don’t Always Say What They Think» (Turpin и др., 2023) демонстрирует случаи, когда цепочка рассуждений систематически не отражает фактор, реально определивший ответ; к схожему выводу для рассуждающих моделей приходит Anthropic в заметке «Reasoning models don’t always say what they think». Следствие: убедительность обоснования не повышает достоверность вывода — читая его, вы проверяете связность текста, а не работу системы.
Группа D. Обход критерия
Здесь механизм другой. Агенту задана цель «сделать так, чтобы прошло»; кратчайший путь к ней не всегда идёт через «починить». Это частный случай reward hacking из «Concrete Problems in AI Safety» (Amodei и др., 2016); OpenAI описывает наблюдение того же поведения в кодовых задачах в заметке «Detecting misbehavior in frontier reasoning models». Честная оговорка: наличие механизма не означает, что ваш агент делает так постоянно — частота зависит от модели, промпта и жёсткости приёмки. Но детекторы дёшевы, а цена пропуска высока.
- D1. Правка теста вместо кода, часто замаскированная:
assertEqualзаменён наassertAlmostEqualс щедрым допуском,assert x == 5наassert x is not None. - D2. Отключение проверки:
@pytest.mark.skip,xfail,t.Skip(),#[ignore],# type: ignore,@ts-ignore,eslint-disable-next-line,except Exception: pass,--no-verifyпри коммите, расширенныйtryвокруг падающего участка. - D3. Хардкод под фикстуру:
if user_id == "test-user-1": return FIXTURE. Признак — значение из фикстуры в продуктовом коде. - D4. Мнимая широта: «покрыл все граничные случаи» при трёх примерах. Правило
LAW-03изCOMPOSITION-AND-LAWS.md: свойство требует генератора, а не трёх примеров; универсальное утверждение с конечным списком подтверждений остаётся гипотезой (RSN-07).
Детектор для всей группы — механический скрипт по добавленным строкам диффа:
#!/usr/bin/env bash
# Карантин диффа: ищет следы обхода проверок, а не ошибки логики.
# Смотрит ТОЛЬКО добавленные строки: удаление skip — хорошо, добавление — повод спросить.
set -uo pipefail
BASE="${1:-HEAD}"
# Каждый шаблон — способ сделать красную проверку зелёной, ничего не починив.
PATTERNS=(
'pytest\.mark\.(skip|xfail)' '@(ts-ignore|ts-nocheck)' 'type:[[:space:]]*ignore'
'eslint-disable' '#\[(ignore|should_panic)\]' '\bt\.Skip\(' '\-\-no-verify'
'except[^:]*:[[:space:]]*pass' '(assert True|assertTrue\(True\))'
)
added() { git diff -U0 "$BASE" -- . | grep -E '^\+' | grep -v '^\+\+\+'; }
found=0
for pattern in "${PATTERNS[@]}"; do
if added | grep -Eq "$pattern"; then
printf 'МАРКЕР ОБХОДА: %s\n' "$pattern"
added | grep -E "$pattern" | while read -r l; do printf ' %s\n' "$l"; done
found=1
fi
done
exit "$found"
Скрипт не решает, плохо это или хорошо: skip бывает полностью оправдан. Он гарантирует, что такая строка не
проедет молча, — и этого достаточно. Обход опасен не сам по себе, а тем, что незаметен на фоне большого диффа.
Группа E. Отказы длинной сессии
На коротком горизонте их не бывает вовсе; они появляются на двадцатом-сороковом шаге и часто списываются на «модель устала».
- E1. Каскад из ранней ошибки. Ошибочный вывод шага 3 становится посылкой шагов с 4 по 40: модель не пересматривает старые утверждения по своей инициативе, они лежат в транскрипте наравне с наблюдениями и выглядят как факты.
- E2. Зацикливание. Одна и та же правка применяется, откатывается, применяется снова: обратной связи из среды не хватает для различения гипотез, а остановиться и спросить агент не решил — тема главы «Планирование».
- E3. Расползание правки. Просили починить один тест — в диффе двенадцать файлов и «попутно причесал». Каждое изменение по отдельности разумно, совокупность непроверяема за разумное время — и именно в ней прячется то, что вы не заметите.
- E4. Потеря цели после компакции. Исходная формулировка задачи и отвергнутые гипотезы — первые кандидаты на сжатие («Контекст»): постоянную часть задачи держать в файле, а между сессиями работать по протоколу главы «Память агента».
Почему это проявляется именно на длине? Грубая модель: пусть каждый шаг верен независимо с вероятностью $p$, и одна ошибка портит результат; тогда вероятность чистого прогона из $n$ шагов равна $p^{n}$.
| $p$ на шаге | $n = 10$ | $n = 30$ | $n = 50$ |
|---|---|---|---|
| 0,99 | 0,90 | 0,74 | 0,61 |
| 0,95 | 0,60 | 0,21 | 0,08 |
| 0,90 | 0,35 | 0,04 | 0,005 |
Модель груба во всех направлениях сразу: шаги не независимы, часть ошибок агент замечает сам на следующем прогоне
тестов, другие коррелируют и рушат всё разом; измеренного p для вашего репозитория здесь нет и быть не может. Но
качественный вывод устойчив к любым разумным поправкам: надёжность цепочки падает быстрее, чем растёт её длина, и
единственный дешёвый рычаг — сокращать число шагов между проверками человеком. Не «сделать модель точнее»
(недоступно), а «резать задачу на куски, каждый из которых кончается проверяемым состоянием».
Лестница детекторов
документация, датированный URL"] B -- "о своём действии" --> E["Журнал вызовов инструментов:
был ли вызов, код возврата"] B -- "о поведении кода" --> G["Свой прогон на чистом дереве"] B -- "о причине" --> H["Откат правки: падение
должно вернуться с тем же текстом"] C --> I{"Совпало?"} E --> I G --> I H --> I I -- "да" --> J["Принять как проверенное,
адрес — в описание PR"] I -- "нет" --> K["Не спорить. Показать факт,
потребовать переделку, завести детектор"]
Нижняя правая ветка — самая ценная и самая пропускаемая: пойманный отказ уже стоил вам времени, и не превратить его в
постоянный детектор значит заплатить второй раз (REF-06 из MEMORY-PROTOCOL.md). Ступени по возрастанию цены: (0)
прочитать отчёт — не проверяет ничего; (1) требовать адрес у каждого факта — ловит A1, A3, A4, стоит полчаса разово в
контракте проекта; (2) смотреть дифф раньше текста — ловит B3, D1–D3, E3, стоит минуту; (3) карантин диффа — ловит
D1–D3, час один раз; (4) свой прогон тестов — ловит всю группу B; (5) чистое дерево или CI — снимает расхождения
среды; (6) мутационное тестирование и property-тесты — проверяют сами тесты, ловят D4, стоят дни. Ступени 1–4
покрывают подавляющую часть повседневной работы почти бесплатно; 5–6 включаются там, где цена ошибки оправдывает
вложение: деньги, персональные данные, необратимые операции.
Дифф раньше текста — не инструмент, а порядок действий, но по отдаче сильнее любого скрипта: четыре команды, меньше минуты, ловят три группы каталога из пяти.
git diff --stat # объём правки — до чтения отчёта
git diff -- '*test*' # что произошло с тестами отдельно
git diff -- requirements.txt package.json go.mod # зависимости отдельно
git worktree add ../verify HEAD && make -C ../verify test # прогон без локального мусора
Проверка адресов из отчёта ловит A4 и приучает агента ставить настоящие ссылки: если проверка стоит в CI, выдумывать адрес бессмысленно.
#!/usr/bin/env python3
"""Каждый упомянутый в отчёте путь:строка должен существовать (отказ A4).
Что по адресу лежит именно заявленное — не проверяет, это остаётся человеку. Сложность:
O(N + M) по времени (N — длина отчёта, M — размер упомянутых файлов), O(1) по памяти.
"""
import re, sys
from pathlib import Path
ADDRESS = re.compile(r"\b([\w./-]+\.[A-Za-z]{1,8}):(\d+)(?:-(\d+))?\b") # file.py:88 или :88-104
root = Path(sys.argv[2]) if len(sys.argv) > 2 else Path.cwd()
bad = 0
for m in ADDRESS.finditer(Path(sys.argv[1]).read_text(encoding="utf-8")):
rel, start, end = m.group(1), int(m.group(2)), int(m.group(3) or m.group(2))
target = root / rel
# Считаем строки потоком: файл может быть большим, держать его целиком незачем.
total = sum(1 for _ in target.open(errors="replace")) if target.is_file() else 0
if not 1 <= start <= end <= total:
print(f"НЕДОСТИЖИМ {rel}:{start}-{end} — файла нет либо в нём {total} строк")
bad += 1
sys.exit(1 if bad else 0)
Формат отчёта, при котором врать дорого
Убрать ложные утверждения полностью нельзя — можно сделать их заметными, потребовав формат, в котором недоказанное
выглядит недоказанным. Это содержание файла REASONING-DISCIPLINE.md из пакета
products/workbench/templates/memory/: четыре маркера и ни одного пятого (RSN-01), адрес у любого утверждения о
внешней системе (RSN-02), явный список непроверенного (RSN-15), право воздержаться вместо догадки (RSN-16).
Плохой отчёт плох не тем, что неверен, а тем, что непроверяем:
Исправил гонку в резервировании. Добавил блокировку, теперь операция идемпотентна. Тесты проходят. Заодно причесал соседний модуль.
Четыре утверждения и ноль зацепок: был ли прогон, что понимается под идемпотентностью, откуда взят диагноз «гонка», что означает «причесал». Проверка стоит столько же, сколько сделать работу заново. Хороший:
Диагноз: две параллельные транзакции проходят проверку существования до вставки [verified:
services/billing/reserve.py:88-104, воспроизведеноpytest -k test_reserve_concurrent, падает 3 прогона из 3]. Правка: уникальный индекс по(account_id, idempotency_key)плюс обработка конфликта [verified:migrations/0042_reserve_unique.sql]. Проверка:pytest -k reserve— 14 passed, 0 failed; с откаченной правкой тот же тест падает сAssertionError: duplicate reservation[verified: прогон в этой сессии]. Не проверено: откат миграции на непустой таблице [unchecked]. Предположение: очередь доставляет сообщения не более одного раза [assumed: из README, кодом не подтверждено].
Второй проверяется за две минуты вместо получаса. Главное в нём — последние две строки: именно их нет в отчёте по
умолчанию, и именно они превращают неизвестность в управляемый риск. Формат записывается один раз в контракт проекта
(CLAUDE.md, AGENTS.md или что читает ваш харнесс) и дальше работает без затрат внимания.
Что не работает
Все перечисленные приёмы выглядят разумно и все дают ложное чувство контроля.
«Не галлюцинируй» в промпте. Инструкция адресована системе, которая не различает достоверное и правдоподобное изнутри; она сместит стиль в сторону оговорок, что не то же самое, что снизить долю ошибок. Работает только конкретная и проверяемая формулировка: «перед утверждением о поведении кода приложи команду и её вывод» — не потому, что убеждает, а потому, что задаёт наблюдаемое требование.
Спрашивать у агента, уверен ли он. Самооценка не является внешним источником и вдобавок провоцирует прогиб (C4). Вместо «ты уверен?» — «покажи, откуда это».
Второй агент как ревьюер. Модель, проверяющая другую модель, особенно ту же самую, даёт коррелированные ошибки: систематическую слепоту разделяют обе. Как ещё один линтер полезно — ловит невнимательность, забытый случай, несогласованность имён; независимой проверкой не является и прогон не заменяет («Многоагентные схемы»).
Больше контекста. Интуиция «дам всё, и ошибок станет меньше» не подтверждается: «Lost in the Middle» (Liu и др., 2023) показывает деградацию извлечения из середины длинного контекста; лишний материал разбавляет существенное и стоит денег («Цена работы с агентом»).
Температура 0 делает ошибку воспроизводимой: ценно для отладки, бесполезно для правильности. Более крупная модель смещает распределение отказов, не устраняя классы: реже наивные выдумки, но убедительнее неверные рассуждения и незаметнее обход критерия — затраты внимания на ревью при этом не падают, а иногда растут.
Общее у всех пунктов: они улучшают источник вместо того, чтобы поставить независимый детектор. Инженерно верен второй путь — ровно как с любым ненадёжным компонентом.
Протокол разбора: от подозрения до детектора
Три шага делаются не по инерции. Воспроизведение идёт первым: до него нечего обсуждать, и половина подозрений
закрывается дёшево. Локализация по слою, а не по симптому: одинаково выглядящее «тесты не проходят» означает
разное на трёх слоях и лечится тремя способами; пропуск этого шага — самая частая причина того, что «починили», а
через неделю повторилось. Рефутация записывается (REF-01): ценность не в архиве, а в том, что запись читается
перед следующей похожей задачей (MEM-51 — совпавшая рефутация блокирует путь).
Сколько стоит ловить и когда дешевле руками
Детекторы не бесплатны. Формат отчёта с маркерами стоит полчаса на контракт и несколько процентов токенов — самый выгодный пункт списка; дифф раньше текста стоит ноль; карантин диффа и проверка адресов — по часу на скрипт, но бессмысленны в репозитории без автотестов и без адресов в отчётах; свой прогон стоит длительности прогона, и если прогон длиннее задачи, чинить надо прогон; мутационное тестирование не окупается почти нигде, кроме критичного ядра.
Внимание человека дефицитно, поэтому приоритет задаётся двумя осями — частота отказа и цена пропуска. Частое и дорогое (ложь про прогон, правка теста вместо кода) уходит в CI: вручную такое вы рано или поздно пропустите. Редкое и дорогое (несуществующий пакет, хардкод под фикстуру) остаётся человеку по чек-листу — автоматика под редкое событие невыгодна. Частое и дешёвое закрывается одной командой при ревью, редкое и дешёвое честно принимается как фон.
Отсюда главный вопрос трека, который надо задавать честно: не дешевле ли сделать руками? Если задача на пятнадцать минут, а полный цикл — спецификация, прогон агента, чтение диффа, свой прогон тестов, круг правок — занимает сорок, агент здесь проиграл. Это не поражение подхода, а нормальная граница применимости. Косвенное подтверждение того, что интуиция об ускорении ненадёжна: рандомизированное исследование METR «Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity» зафиксировало у опытных разработчиков на их собственных зрелых репозиториях замедление на 19% — при том, что участники ожидали и постфактум сообщали об ускорении. Выборка мала, инструменты той эпохи, задачи специфические; переносить вывод на любую работу нельзя. Но одно наблюдение переносится точно: субъективное ощущение скорости не является её измерением.
Типичные ошибки инженера
- Читать отчёт до диффа. Текст создаёт ожидание, под которое глаз подгоняет код.
- Спорить с агентом вместо предъявления факта. «Ты неправ» порождает извинение и перепись; вывод команды порождает исправление.
- Принимать объяснение за проверку — убедительность обоснования не коррелирует с верностью вывода (C5).
- Проверять первый дифф внимательно, а пятый по диагонали. Внимание кончается раньше сессии; отсюда правило резать задачи так, чтобы дифф оставался читаемым.
- Не записывать пойманный отказ — заплатив за находку, вы не забираете её ценность.
- Считать, что аккуратный агент не требует проверки. Отсутствие ошибок в последних десяти задачах не является свойством системы.
Мини-итог
- «Врёт» — операционально точное слово: утверждение подаётся как знание при отсутствии знания, а отсутствие оговорки ничего не сообщает о достоверности.
- Отказ рождается на одном из трёх слоёв — модель, харнесс, среда; первый вопрос при разборе: где разошлось. Пять групп: внешний мир, собственные действия, рассуждение, обход критерия, длинная сессия. Опаснее всего вторая — она подрывает доверие к отчёту как таковому.
- Надёжность цепочки падает быстрее её длины; доступный рычаг один — сокращать число шагов между проверками человеком.
- Ступени 1–4 лестницы детекторов (адрес у факта, дифф раньше текста, карантин диффа, свой прогон) стоят почти ничего и покрывают большинство случаев.
- Не работают: просьбы не галлюцинировать, вопрос «ты уверен?», агент-ревьюер той же модели, больше контекста, температура 0, модель покрупнее. Пойманный отказ конвертируется в детектор и рефутацию, иначе вы заплатите за него ещё раз.
Источники
- Hicks, Humphries, Slater, «ChatGPT is bullshit» и Kalai et al., «Why Language Models Hallucinate» — философская и техническая версии одного тезиса: правдоподобие вместо соответствия.
- Sharma et al., «Towards Understanding Sycophancy in Language Models» — измерение прогиба под мнение собеседника.
- Turpin et al., «Language Models Don’t Always Say What They Think» и Anthropic, «Reasoning models don’t always say what they think» — почему объяснение не является интроспекцией.
- Spracklen et al., «We Have a Package for You!» — выдуманные имена пакетов и их устойчивость от прогона к прогону.
- Amodei et al., «Concrete Problems in AI Safety» и OpenAI, «Detecting misbehavior in frontier reasoning models» — reward hacking в общем виде и его наблюдение в кодовых задачах.
- Liu et al., «Lost in the Middle» — деградация извлечения из середины длинного контекста.
- METR, «Measuring the Impact of Early-2025 AI on Experienced Open-Source Developer Productivity» — расхождение ощущаемого и измеренного ускорения; читать вместе с разделом об ограничениях.
- Jimenez et al., SWE-bench и критика качества бенчмарка в SWE-Bench+ — почему к цифрам «решает N% задач» стоит относиться так же, как к утверждению агента: с требованием адреса.
products/workbench/templates/memory/— наш пакет правил:REASONING-DISCIPLINE.md(RSN-01,RSN-02,RSN-03,RSN-07,RSN-09,RSN-11,RSN-13,RSN-15,RSN-16),VERIFIED-CODE.md(CODE-04,CODE-13),COMPOSITION-AND-LAWS.md(LAW-03),MEMORY-PROTOCOL.mdиnotes/REFUTATION.md(REF-01,REF-06,MEM-51).
Что дальше
Каталог отказов заканчивается там, где начинается единственный универсальный ответ на все его пункты: не спорить с утверждением, а заменить его наблюдением. Следующая глава — про то, как устроено доказательство в работе с агентом, какие прогоны считаются, какие нет, и как выстроить процесс, в котором «работает» означает конкретную команду с конкретным выводом: Проверяемость: тесты, прогоны и доказательства вместо обещаний.