Сцену стоит узнать в лицо, поэтому начнём с неё. Вы дописали игру, счёт после перезапуска обнуляется, и вы спрашиваете агента:
Почему после перезапуска теряется счёт?Ответ приходит спокойный и складный:
Счёт в проекте уже сохраняется, просто запись нигде не включена.
Достаточно поменять одну настройку, и результат переживёт перезапуск.Вы идёте проверять. Ни настройки, ни сохранения счёта в проекте нет и не было - ни строчки, ни намёка. Ответ читался как разбор вашего кода, а был предположением о том, как обычно устроены такие проекты.
И ведь ни паузы, ни оговорки перед этим не прозвучало. Интонация ровно та же, что у всех предыдущих ответов, которые оказались верными. Инструмент при этом исправен, и модель не стала хуже, чем была вчера.
Причина в том, как ответ вообще появляется. Модель не достаёт готовый факт из хранилища - она подбирает вероятное продолжение вашего текста, кусок за куском. А вероятное и верное это разные вещи, особенно когда речь про ваш проект, которого модель не видела. Придуманные, но правдоподобные подробности принято называть галлюцинациями.
Дальше - где расставлены ловушки, почему у ошибки всегда спокойный тон и какие три проверки закрывают большую часть таких случаев.
Что модель видит в вашем запросе
Ловушка тут самая простая из всех: кажется, что модель смотрит на ваш проект. На самом деле она смотрит только на то, что ей передали, а передают ей вот что:
- Встроенные знания. Закономерности, которые закрепились в параметрах модели при обучении. Не карточки с фактами и ссылками, а числа, поэтому даже знакомый факт модель может воспроизвести неточно. И у них есть граница по времени: про библиотеку, которая вышла позже, модель знает ровно столько, сколько ей показали.
- Текущий разговор. Ваш запрос, история переписки, файлы, которые агент прочитал, вывод команд, которые он запустил.
- Память приложения. То, что сохранено в отдельные файлы и подкладывается в разговор в начале следующей сессии. В Claude Code это
CLAUDE.md, который пишете вы, и auto memory, куда агент записывает заметки сам. - Внешние источники. Документация, поиск, база данных, файлы проекта - всё, чего в обучающих данных могло не быть или что с тех пор изменилось.
Три последних приходят одним и тем же путём: чтобы повлиять на ответ, они должны оказаться в текущем разговоре. Сама по себе модель в проект не заглядывает.
Отсюда следствие, которое стоит перестроить в голове один раз. Файл, который никто не открывал, для модели не существует. Пока его текст не попал в разговор, вопрос "где у нас обрабатывается авторизация" честнее читать как "как обычно называют такой файл в подобных проектах". Ответ вы получите в обоих случаях, и выглядеть он будет одинаково.
Рядом живёт ловушка помельче, зато обидная. Прочитанный файл остаётся в разговоре таким, каким его прочитали. Вы поправили строку у себя в редакторе, а в истории разговора лежит старая версия. Claude Code отметит, что файл изменился, но перечитает ли его агент, решает уже модель. Правили руками посреди разговора - надёжнее прямо попросить перечитать.
Claude Code сначала читает проект и запускает команды, а отвечает потом. В ответе обычно видно, какие файлы он открыл и что запускал. Если ответ про ваш код появился раньше, чем агент хоть что-то прочитал, вы смотрите на предположение о типичном проекте, а не на разбор вашего.
Почему формулировка меняет результат
Из всего, что попадает в разговор, ваш запрос - единственное, что вы пишете сами. Поэтому мелочи в нём и решают: переставили пару слов, добавили уточнение - ответ поехал в другую сторону. Это не каприз инструмента.
Тут легко запутаться, поэтому проговорю отдельно. Один и тот же запрос дважды тоже даёт разные ответы: в ответ уходит не обязательно самый вероятный вариант продолжения, у генерации есть настройки, которые задают, насколько охотно берётся вариант пониже. Напрашивается вопрос: если ответ и так гуляет, при чём здесь мои слова. Разница в том, что именно гуляет. Разброс между одинаковыми запросами это шум вокруг одного и того же выбора: формулировки разойдутся, направление останется прежним. А слова в запросе двигают само направление, и делают это устойчиво.
Расплывчатая просьба работает хуже всего. Она оставляет модели выбор, а выбирает модель самое вероятное вообще - усреднённое по всему, что она видела. Возьмите простое "сократи текст". На сколько - на процент, на треть, вдвое? Что можно выбросить, а что трогать нельзя? Ни на один из этих вопросов в просьбе ответа нет, значит, отвечать будет модель, и формально она окажется права. А "сократи описание на 30%" или "сократи описание до 300 символов" не оставляют ей выбора там, где выбор ваш.
Хорошо видно на паре запросов про одно и то же. "Почини сортировку" оставляет открытым всё: какой список, по какому полю, что вообще считать поломкой. А вот вторая формулировка не оставляет открытым почти ничего:
В списке заказов даты идут от старых к новым, нужно наоборот.
Сначала покажи файл и строку, где задан порядок сортировки, потом предлагай правку.Она длиннее ровно настолько, насколько первая требовала догадки. И заодно делает половину проверки за вас: агент приносит место в коде ещё до того, как вы о нём спросили.
Вывод простой: чем меньше в запросе свободы, тем меньше в ответе догадки. Речь не про волшебные заклинания, а про обычную вещь - либо рамку задаёте вы, либо её выберут за вас.
Уверенный тон не равен факту
А вот и главная ловушка. У модели нет отдельной интонации для "это я точно знаю" и отдельной для "это я сейчас достроил": обе фразы собираются одним и тем же способом и выходят одинаково спокойными. Связь тут не то чтобы нулевая, но пользы от неё нет: уверенность у модели завышена всегда, поэтому по тону вы не отличите проверенное от достроенного.
В обычном тексте странное утверждение царапает глаз, и вы притормаживаете сами. В коде эта защита не срабатывает: имена выглядят правильно, конструкции знакомые, а настоящий метод библиотеки от собранного по аналогии на глаз не отличить, если не знаешь библиотеку наизусть. Поэтому промах чаще всплывает не при чтении, а при запуске.
Имя к тому же редко бывает выдумано с нуля. В разборе сгенерированного кода, где искали ссылки на несуществующие библиотеки, больше трети таких имён оказались склейкой двух настоящих. Отсюда и ощущение достоверности: части имени вы где-то видели, просто не в этом сочетании.
Четыре случая, которые узнаются с первого раза, если знать, что искать:
| Как это выглядит | Что произошло | Чем ловится |
|---|---|---|
| у команды назван флаг, которого у неё нет | модель собрала строку по привычной форме, поэтому флаг и выглядит настоящим | справка команды или её документация |
| назван файл, функция или поле конфига, которых в проекте нет | имя выглядит типичным для такого проекта, но проект никто не читал | поиск по проекту, просьба показать строку |
| уверенно рассказано, как устроен ваш проект | в разговоре не было ни одного файла проекта, поэтому описан типичный | спросить, какие файлы он открыл до ответа |
| сказано "готово", а команда не запускалась | отчёт собран из текста задачи, а не из результата запуска | запустить самому и посмотреть вывод |
Общее у всех четырёх одно: ответ звучит как результат работы, хотя работы за ним не стояло.
С последним случаем стоит разобраться отдельно, потому что выглядит он как обман, а обмана там нет. Агент останавливается, когда работа выглядит сделанной. Если запустить ему нечего, "выглядит сделанной" - единственный доступный сигнал, и проверяющим контуром становитесь вы.
Цена у этого измеримая. В одном разборе агентских логов ложные "готово" дали почти половину всех неудач. А там, где состояние проверялось независимо от отчёта самого агента, такие случаи почти исчезали. В этом и смысл второй проверки из следующей секции: она подставляет вместо отчёта то, что можно посмотреть своими глазами.
Остаётся вопрос, почему модель вообще предпочитает достроить, а не признаться. Дело в том, как её учили и как оценивали. Представьте тест с вариантами ответа, где за пустой бланк гарантированный ноль, а за наугад отмеченный - шанс на балл. Молчать в такой системе невыгодно всегда, и отвечать при любой неуверенности разумно. Человек потом переучивается на живых задачах, где неверный ответ обходится дороже честного "не знаю". У модели такой переучки нет.
Попросить модель честно предупреждать, когда она не уверена, помогает - но это тоже текст, собранный тем же механизмом. Как дополнительный сигнал сгодится, как замена проверке нет.
Инструменты уменьшают слепые зоны
Здесь полезно развести два слова, которые в разговоре обычно валят в кучу. Модель умеет ровно одно: получить разговор и выдать продолжение. Агент - это программа вокруг модели, у которой есть инструменты: чтение файла, запуск команды, правка проекта.
А теперь деталь, от которой зависит, где именно бывает ошибка. Инструменты выбирает не программа. Модель в своём ответе просит открыть такой-то файл или запустить такую-то команду, а программа эту просьбу проверяет, выполняет и возвращает результат обратно в разговор. Решение принимает модель, действие выполняет программа. Значит, промахнуться может и само решение: не тот файл, не та команда, не тот тест.
Разница всё равно огромная. Пока файл не открыт, ответ про него строится по памяти о похожих проектах. Как только файл прочитан, а тест прогнан, в разговоре появляется факт: вот содержимое, вот вывод. Это уже не воспоминание, а проверка, и качество ответов после неё заметно другое.
Отсюда приём, который стоит одной строки в начале разговора:
Сначала найди и покажи, где это лежит в проекте, и только потом объясняй.Слепые зоны при этом сужаются, но не исчезают. Агент может открыть соседний файл вместо нужного, истолковать вывод команды по-своему или остановиться на первом правдоподобном объяснении, не дойдя до настоящей причины. Всё это я видел, и не по одному разу. Поэтому внешний сигнал - вывод теста, текст документации, содержимое файла - весит больше, чем самое уверенное рассуждение без опоры.
Три проверки, которые стоят минуты
Хорошая новость в том, что ловить такие промахи можно почти без усилий. Всё сводится к одной развилке.
Смотреть тут нужно не на то, насколько убедительно написано, а на то, есть ли в ответе за что зацепиться: конкретный файл, конкретная строка, команда с её выводом. Нет опоры - значит, перед вами пока гипотеза, а не результат. Многие ответы такими и начинаются, вопрос только в том, что вы сделаете дальше.
Дальше три проверки. Каждая занимает меньше минуты, и все три сразу нужны редко.
- Попросить показать место. Не "объясни подробнее", а "покажи файл, строку и сам фрагмент". Если места нет, это выяснится сразу.
- Открыть или запустить результат самому. Страницу в браузере, команду в терминале, тест в проекте. Отчёт о работе и работа - не одно и то же.
- Сверить утверждение об инструменте с самим инструментом. У команды есть встроенная справка, у библиотеки документация. Названный флаг или ключ конфига там либо есть, либо нет, и выясняется это за полминуты. С методом библиотеки строже: в документацию попадает не всё, поэтому его отсутствие - повод переспросить, а не приговор.
Вместо спора с ответом попросите опору напрямую:
Покажи файл и строку, где это описано.
Если такого места в проекте нет, скажи прямо, что это предположение.Две строки, которые стоит держать под рукой. Первая отправляет агента в проект вместо ответа по памяти о похожих. Вторая даёт ему выход: сказать, что места нет, оказывается дешевле, чем достроить ответ до правдоподобного.
Для отчёта "готово" работает та же просьба, только про запуск: "покажи команду, которую ты запустил, и её вывод целиком".
Гарантией это не становится: фраза "это предположение" собрана тем же механизмом, что и всё остальное. Шанс промаха она снижает, проверку не заменяет.
И сразу оговорка, чтобы не осталось неверного вкуса. Проверять - не значит не доверять инструменту. Свой собственный diff вы тоже перечитываете перед коммитом, хотя писали его сами. Здесь то же самое, только повод чуть весомее.
Что это значит для работы с Claude Code
Что из всего этого следует прямо за клавиатурой:
- ответ со ссылкой на файл, строку или вывод команды проверяется за секунды. Ответ без них проверить нечем: его остаётся только перечитать и согласиться;
- дайте агенту прочитать нужное до того, как зададите вопрос. Один лишний шаг убирает целый класс промахов;
- по уверенности судить нельзя: она завышена независимо от того, стоит за словами проверка или догадка;
- "звучит правильно" и "работает правильно" - разные вещи, и различает их только запуск;
- чем больше цена ошибки, тем раньше в разговоре стоит появиться чему-то внешнему: тесту, документации, реальному файлу. На мелкой правке хватит взгляда на diff;
- если агент ошибся, скажите ему об этом фактом, а не оценкой. "Такой функции в проекте нет, вот что лежит в папке" двигает работу дальше, "ты опять всё выдумал" не двигает никуда. И держите в уме: на уверенное возражение агент скорее подстроится, чем станет спорить, даже когда прав был он. Согласие агента это не подтверждение вашей правоты.
Механизм, который иногда уверенно промахивается, при этом остаётся крайне полезным. Знать про его границы нужно ровно затем, чтобы не тратить время на удивление и сразу переходить к проверке.