TL;DR
DeskCheck — схема работы кодинг-агента, в которой на каждом из четырёх этапов (поиск причины, правка, сверка с задачей, проверка тестами) агента заставляют расписать, как код выполняется на конкретных входных данных. Это старая программистская практика desk checking: пройти код по шагам «в уме», не запуская. Агент не просто «смотрит на код и решает», а явно трассирует вызовы, значения переменных и результат.
Главная находка: агенты и так рассуждают о коде, но делают это стихийно. Рассуждение о выполнении кода есть примерно в двух третях запусков, и там, где оно есть, задачи решаются заметно чаще. На сложных задачах агенты рассуждают больше. Но без направляющей инструкции возникают четыре типичные поломки. Агент чинит только симптом из описания бага и не находит корень. Он не может проверить «почти верную» правку, потому что тест не удаётся запустить. Он забывает часть требований из длинной задачи. Он пишет тесты на однотипные случаи и не проверяет граничные.
Метод закрывает каждую дыру отдельным обязательным шагом рассуждения. Он трассирует цепочку вызовов до корня проблемы. Он прогоняет свою правку «на бумаге» и дорабатывает её. Он выписывает требования списком и сверяет правку с каждым. Перед тестами он придумывает разнообразные входы с ожидаемыми выходами. Это дало прирост решённых задач по сравнению с обычным агентом при небольшой доплате за токены.
Схема метода
ЭТАП 1. Локализация: трассировка цепочки вызовов от точки входа → список подозрительных методов (не только тех, что названы в описании бага)
ЭТАП 2. Правка и доводка: написал патч → «прогнал» его на бумаге на входах из задачи → если поведение не то, поправил
ЭТАП 3. Аудит: выписал все требования из задачи списком → для каждого проверил, что патч его выполняет
ЭТАП 4. Валидация: придумал разнообразные входы + ожидаемые выходы (регистр, пустые, составные, граничные) → только потом пишет тесты
Это многоэтапный процесс. В статье он реализован как мультиагентная схема. В обычном агенте (Claude Code, Cursor) его можно передать одной инструкцией с этапами.
Пример применения
Задача: Вы ведёте бэкенд небольшого интернет-магазина на Python. Покупатели жалуются, что оплата через СБП падает с ошибкой, если в корзине промокод и товар из категории «Цифровые». Описание бага в тикете длинное, в нём пять требований. Агент уже один раз «починил» только первую функцию, а в соседней всё так же падает.
Промпт (в Claude Code или Cursor):
Задача: починить падение оплаты через СБП, когда в корзине есть промокод
и цифровой товар. Описание бага в тикете PAY-482.
Работай строго по четырём этапам. Не переходи к следующему,
пока не выписал результат предыдущего.
ЭТАП 1. ЛОКАЛИЗАЦИЯ.
Найди точку входа (checkout → оплата СБП). Выпиши цепочку вызовов
от неё вниз. Для каждой функции в цепочке напиши, как она себя ведёт
на входе «промокод + цифровой товар». Не останавливайся на функции,
которую назвали в тикете: проверь все соседние в той же цепочке,
в том числе те, что выглядят не связанными с симптомом.
ЭТАП 2. ПРАВКА И ДОВОДКА.
Напиши патч. Затем пройди по нему по шагам на трёх конкретных входах
из тикета: что лежит в каждой переменной, какая ветка if выполняется,
что возвращается или какое исключение летит. Если результат не совпал
с ожидаемым в тикете — исправь патч и прогони снова.
ЭТАП 3. АУДИТ ПО ТРЕБОВАНИЯМ.
Выпиши из тикета все требования нумерованным списком.
Для каждого пункта напиши: выполняется ли он в твоём патче,
в какой строке, и на каком входе ты это проверил.
ЭТАП 4. ВАЛИДАЦИЯ.
Прежде чем писать тесты, составь таблицу: вход → ожидаемый выход.
Входы должны быть разными: пустая корзина, промокод в другом регистре,
несколько цифровых товаров, нулевая сумма, смешанная корзина.
Только после таблицы пиши тесты и запускай их.
В конце: что изменил, какие требования закрыл, что осталось непроверенным.
Результат: Агент выдаст четыре блока. В первом будет трассировка цепочки вызовов с пометкой, где она ломается. Во втором — патч и «прогонка» по трём входам, возможно с исправлением. В третьем — таблица «требование → выполнено ли → где». В четвёртом — таблица входов и выходов, а затем тесты. Шансы, что он найдёт не только очевидную функцию, но и соседнюю, и вспомнит все пять пунктов тикета, выше, чем при обычной формулировке «почини баг».
Почему это работает
Слабость. Агент по умолчанию идёт за самым ярким намёком из описания. Если в тикете сказано «падает при итерации по значениям», он проверит все функции, где есть такая итерация. Функцию, которая падает по другой причине, он пропустит. Длинное ТЗ он читает выборочно и часть требований теряет. Тесты, которые он пишет, повторяют один и тот же тип случаев. А когда тест не запускается, агент либо тратит десятки шагов на возню с окружением, либо сдаётся и отправляет непроверенное.
Сильная сторона. Модель хорошо трассирует код, если её об этом явно попросить. Она умеет вести значения переменных, раскручивать ветки условий и вызовы функций. Ей не нужно запускать программу, чтобы увидеть «здесь исключение не выбросится».
Как метод это использует. Он заменяет «решай как получится» на обязательные артефакты на каждом этапе: цепочку вызовов, пошаговую прогонку, список требований, таблицу входов и выходов. Пока артефакт не написан, переходить дальше нельзя. Рассуждение становится видимым и проверяемым, а не случайным.
Рычаги управления: - Число входов на этапах 2 и 4 → больше входов дают строже проверку, но расходуют больше токенов. Для мелких правок хватит двух. - Этап 3 (аудит) → его можно оставить отдельно, даже если остальные не нужны. Он дешёвый и полезен, когда задача длинная. - Список «граничных» входов на этапе 4 → подставьте свой: даты, валюты, пустые значения, кириллица, регистры. - Условие перехода («не переходи, пока не выписал») → если его убрать, агент начнёт пропускать этапы, и метод ослабнет.
Шаблон промпта
Дословных промптов в доступной части статьи нет, там описаны только стадии. Шаблон ниже собран по этим описаниям: четыре этапа и обязательный артефакт на каждом.
Задача: {описание бага или фичи, ссылка на тикет}.
Кодовая база: {язык, фреймворк, где лежит нужный модуль}.
Работай строго по четырём этапам. Не переходи к следующему,
пока не выписал результат предыдущего.
ЭТАП 1. ЛОКАЛИЗАЦИЯ.
Найди точку входа для сценария {сценарий}. Выпиши цепочку вызовов вниз.
Для каждой функции опиши, как она ведёт себя на входе {входные данные из бага}.
Проверь не только функции, названные в описании, но и все соседние
в этой цепочке. Укажи корневую причину, а не симптом.
ЭТАП 2. ПРАВКА И ДОВОДКА.
Напиши патч. Затем «прогони» его без запуска на {число} конкретных входах:
значения переменных, выбранные ветки, возвращаемое значение или исключение.
Если результат не соответствует ожидаемому в задаче — исправь и прогони заново.
ЭТАП 3. АУДИТ ПО ТРЕБОВАНИЯМ.
Выпиши все требования из задачи нумерованным списком.
Для каждого: выполняется ли в патче, в какой строке, на каком входе проверено.
Невыполненные — доработай.
ЭТАП 4. ВАЛИДАЦИЯ.
Перед тестами составь таблицу «вход → ожидаемый выход».
Входы должны быть разными по типу: {список граничных случаев}.
Затем напиши тесты по таблице и запусти их, если окружение позволяет.
В конце коротко: что изменено, какие требования закрыты, что не проверено.
Что подставлять: {описание бага} — текст тикета целиком, не пересказ. {сценарий} и {входные данные} — как воспроизводится ошибка. {число} — обычно 2–4. {список граничных случаев} — то, что в вашем коде реально ломается: пустые значения, регистр, длинные строки, нули, смешанные типы.
🚀 Быстрый старт — вставь в чат или в файл инструкций агента:
Вот шаблон четырёхэтапной работы над багом (трассировка → правка с прогонкой на бумаге → аудит по требованиям → таблица входов и выходов перед тестами). Адаптируй под мою задачу: {твоя задача}.
Задавай вопросы, чтобы заполнить поля.
[вставить шаблон выше]
LLM спросит про язык и структуру проекта, про то, как воспроизводится ошибка, и какие граничные случаи у вас реально встречаются. Это нужно, чтобы этапы 1 и 4 были привязаны к вашему коду, а не к абстрактным примерам. Паттерн «этап → обязательный артефакт» она возьмёт из шаблона и перенесёт на вашу задачу.
Ограничения
⚠️ Корреляция ≠ причина: вывод «агенты, которые рассуждают о коде, решают больше задач» — это связь, а не доказательство. Причинную роль подтверждает отдельный эксперимент: прирост рос по мере добавления этапов. Но сам по себе первый вывод ничего не доказывает.
⚠️ Нужна многоэтапность: если вставить «рассуждай о коде» одной фразой в системный промпт, эффекта хватает слабо. Агенты, которым рассуждение запросили один раз, делали это нерегулярно. Метод держится на повторении по этапам.
⚠️ Не замена запуску: «прогонка на бумаге» нужна там, где тест запустить трудно. Если запуск возможен, реальный тест надёжнее. В статье симуляция заменяет запуск, а не отменяет его.
⚠️ Только про код: все проверки идут на задачах починки багов в репозиториях (Python, Go, TypeScript, JavaScript). Для текстов, аналитики и других задач метод не проверяли.
⚠️ Рост не безграничный: прирост решённых задач составил единицы–десять процентов. Агент всё равно ошибается, просто реже. Токенов уходит чуть больше.
Как исследовали
Исследование шло в два этапа. Сначала команда разобрала почти 8 тысяч «траекторий». Так называют полные записи работы агента: каждая мысль и каждое действие по шагам. Записи взяли у шести разных агентных схем, включая Claude Code, на трёх наборах задач SWE-bench. Это реальные баги из открытых репозиториев. Модель-классификатор находила в мыслях агента фрагменты рассуждения о коде (значения переменных, вызовы, циклы, условия, возвраты) и раскладывала их на 12 видов. Корректность разметки проверили вручную на выборке из 120 запусков, трое людей согласились между собой.
Результат оказался неожиданным. Рассуждение о коде есть примерно в двух третях запусков. Там, где оно есть, решается около 70% задач, там, где нет, — около 51%. Чем сложнее задача, тем больше рассуждений. Но оно возникает стихийно: одни схемы рассуждают на этапе поиска бага, другие на этапе тестов. В схемах, где оно требуется только один раз в системном промпте, агенты склонны это игнорировать. Там, где его требуют на каждом этапе, оно есть в каждом запуске.
Из этого появилась идея: требовать рассуждение на каждом этапе и подсказывать, какое именно. Эту схему проверили на 731 задаче SWE-bench-Pro с тремя разными моделями, против упрощённого агента mini-SWE-Agent и Claude Code. Прирост составил от 6 до 10 процентов, дополнительные расходы — около 14 центов на задачу. Токенов уходит в среднем на 7,6% больше. Локализация бага стала заметно точнее: доля найденных нужных методов выросла до 0,66 против 0,38–0,46 у конкурентов. Абляция (поэтапное добавление частей) показала рост с 53% до 68% по мере включения этапов, то есть каждый этап вносит вклад. Статистические тесты и повторные запуски подтвердили, что результат не случайный.
Адаптации и экстраполяции
💡 Адаптация для длинного ТЗ (не код): этап 3 (аудит по требованиям) переносится на любую задачу с длинным входом: договор, бриф, регламент. В статье этот этап применён только к коду. Перенос — моя экстраполяция.
Вот бриф клиента: {текст брифа}.
Вот мой черновик ответа: {черновик}.
1. Выпиши все требования из брифа нумерованным списком (явные и подразумеваемые).
2. Для каждого пункта скажи: выполнено ли в черновике, в каком месте,
и процитируй фрагмент.
3. Пункты, где нет цитаты, — доработай.
🔧 Техника: убрать «запусти тесты» → симуляция там, где запуск невозможен. Если у агента нет доступа к окружению, замените в этапе 4 «запусти тесты» на «для каждой строки таблицы пройди код по шагам и напиши, что вернётся». Эффект: даже без запуска агент найдёт ошибки в условиях и ветках.
Ресурсы
- Статья: Enforcing Code Reasoning in Agentic Scaffold for More Effective Issue Resolution
- Авторы: Changshu Liu, Ji Young Kim, Alireza Ghazanfari, Saanvi Nallu, Reyhaneh Jabbarvand. Университет в статье не указан.
- Бенчмарки: SWE-bench-Verified, SWE-bench-Pro, SWE-bench-Lite
- Базовые схемы для сравнения: mini-SWE-Agent, Claude Code, OpenHands, SWE-Doctor
