
Привет! Я Чичев Максим, работаю руководителем разработки платформенных решений в Петрович-Тех. В этой статье хочу рассказать о том, как я прогнал три LLM трёх весовых категорий через один и тот же харнесс на агентных задачах длиной 2, 3 и 15 шагов — и почему на длинных цепочках тезис «харнесс важнее модели» перестаёт работать.
Пару недель назад я запустил один и тот же промпт на одной и той же модели два раза подряд.
За первый прогон модель создала 7 отчётов из 7, и в каждом количество строк совпало с данными до единицы. За второй прогон, час спустя — 0 файлов из 7. При этом модель уверенно написала: «Создал 7 файлов в папке “Отчёты”: X — 14 строк, Y — 200, Z — 83…». Все названные числа верные. Файлов нет ни одного.
Какой из двух прогонов говорит правду об этой модели? Правильный ответ — ни один. Из этого удивления вырос домашний бенчмарк, из бенчмарка — доклад, а из доклада — эта статья.
Под катом — как один и тот же харнесс с тремя моделями трёх разных весовых категорий решал задачи длиной 2, 3 и 15 шагов, почему тезис «харнесс важнее модели» перестаёт работать на длинных цепочках и какой вид ошибки агента оказался самым опасным.
<cut/>
Зачем я вообще это мерил
Когда строишь систему, которая сама ходит в рабочие сервисы и что-то там делает, рано или поздно приходится решать, какую модель поставить внутрь. Ответ стоит денег, приватности и работы по интеграции, поэтому хочется опереться на цифры.
Проблема в том, что я понятия не имею, как устроены задачи в публичных бенчмарках. А мой агент должен делать пятнадцать действий подряд моими инструментами, и каждое следующее опирается на результат предыдущего.
Поэтому я устроил небольшое исследование на своих задачах, своих данных и в своей — полностью навайбкоженной — обвязке, где меняется ровно одна деталь: модель.

Харнесс
Сама по себе нейросеть умеет ровно одно — получить текст и вернуть текст. Она не открывает Jira, не выполняет SQL и не создаёт файлы. Харнесс (по-русски — обвязка) — это программа вокруг модели, которая содержит системный промпт, каталог инструментов, поиск по документам, исполнение вызовов и обработку ошибок.
Когда модель хочет что-то сделать, она пишет: «вызови инструмент X с аргументами Y». Обвязка исполняет, возвращает результат — и круг повторяется, в моём случае до 15 раз на один ответ пользователю. Запомните этот момент — количество последовательных вызовов дальше определит всё.

Стенд
Стенд — мой личный AI-ассистент, подключённый к моковым системам: задачи, вики, почта, календарь, метрики разработки на дашборде руководителя. 13 виджетов с метриками, ~30 инструментов у модели, 7 проектов в выборке.
Участники — три модели трёх весовых категорий:
-
Claude Sonnet 4.6 — облако, запад;
-
Qwen3-235B — облако, Россия;
-
Qwen3.5-9B — локально, на одной видеокарте (квант AWQ 4 бита, инференс через vLLM).
Для чистоты всё, кроме модели, заморожено: промпты, инструменты, база, лимиты, версия кода. Даже синхронизацию с Jira остановил, чтобы данные не менялись.
Задачи три, и отличаются они длиной цепочки вызовов. Шагом я считаю один ход модели — вызов инструмента или финальный ответ пользователю.
Задачи следующие:
Сводка — пересказать показатели всех 13 виджетов (2 шага). Дашборд отдаёт все виджеты одним вызовом, так что цепочка минимальна: запросить данные и пересказать. Ошибиться почти негде.
Отчёт — собрать задачи в риске по проекту и сохранить файлом (3 шага). Запросить данные, создать файл, отчитаться. Появляется второй инструмент — и данные нужно донести из одного в другой без потерь.
Цикл — тот же отчёт, но для каждого из семи проектов (15 шагов). На каждый проект — свой запрос с фильтром и свой файл, итого 14 вызовов подряд плюс финальный ответ. Каждый следующий шаг опирается на предыдущие: не потерять проект, не перепутать данные между файлами, не бросить на середине.
Каждая задача — по три прогона на каждой модели, девять прогонов на задачу, двадцать семь на всё исследование.
Как проверялся результат (и как я чуть не выбросил модель)
Сверять итог я решил не с заранее записанным ответом, а с тем, что модель сама получила от инструмента. Полный ответ каждого вызова пишется в журнал (~30 КБ JSON), поэтому я точно знаю, сколько строк модель получила и сколько донесла до файла.
Почему не с эталоном? Сначала я сделал как обычно в юнит-тестах — один раз посчитал правильный ответ и сверял с ним. По этому эталону выходило, что модель ошибается — 46 задач вместо 45. Потом я вспомнил, что одна из метрик считает возраст задачи от текущего момента прямо в SQL. Задачи стареют каждый час, и выборка меняется сама собой даже на замороженных данных.
Так что прежде чем обвинять модель в неточности, убедитесь, что вы правильно проверяете.
«Харнесс важнее модели» — так сегодня считают почти все
В whitepaper Сбера «AI-Disrupt PDLC» написано: около 2% инженерной ценности агентного пайплайна даёт логика принятия решений в самой модели, остальные 98% — детерминированная обвязка вокруг. Во второй редакции формулировку уточнили: по итогам reverse-engineering Claude Code среда исполнения — это ~98% кодовой базы промышленного агента.
Это не одинокое мнение, и у него есть основания. LangChain перестроили обвязку своего агента — и результат на Terminal-Bench 2.0 вырос с 52,8% до 66,5%, с места за пределами топ-30 до топ-5. Сама модель при этом не менялась.
Принстонский Holistic Agent Leaderboard прогнал 9 моделей по 9 бенчмаркам — 21 730 прогонов — в едином харнессе именно потому, что без фиксации обвязки сравнивать модели бессмысленно. Подборка Future AGI со ссылкой на Epoch AI: одна и та же модель на SWE-bench Verified набирает от 62,3% до 70,2% в зависимости только от обвязки, а Claude Opus 4.5 на SWE-bench Pro — от 45,9% в стандартизированной SEAL до 51,8% в Auggie. У статьи «Stop Comparing LLM Agents Without Disclosing the Harness» тезис вынесен прямо в заголовок: обвязка нередко определяет результат сильнее, чем модель внутри неё.
Обвязка прибавляет, а модель умножает
Улучшения обвязки дают прибавку, одинаковую для всех: добавили инструмент, починили баг — и все модели поднялись примерно на одну величину. Прибавка складывается.
Модель работает иначе. Её качество проявляется на каждом отдельном шаге, а шаги идут подряд, и вероятности перемножаются. Если шаг проходит с вероятностью 95%, то цепочка из 15 шагов дойдёт до конца целиком в 46 случаях из 100. С надёжностью шага 90% — в 21 случае. Разница в три пункта на шаг на длинной цепочке превращается в разницу в разы.
Компания Sierra ввела для агентов отдельную метрику pass^k именно из-за этого эффекта: в их бенчмарке τ-bench даже лучший агент решал задачу с одной попытки менее чем в половине случаев, а ту же задачу восемь раз подряд — менее чем в 25%.

Результаты. Два шага: все молодцы
Сводку по дашборду сдали все три модели во всех девяти прогонах: Sonnet — 36 с, Qwen3-235B — 34 с, локальная 9B — 32 с, самая быстрая.
Если бы я остановился здесь, вывод был бы простым и приятным: локальная модель на одной видеокарте не уступает облачным. Именно так выглядят многие публичные сравнения, и именно поэтому им нельзя верить.
Три шага: модели разошлись
-
Claude Sonnet 4.6 файл создавал каждый раз, но ни разу не воспользовался тем инструментом, о котором его просили. Собирал данные собственным поиском по своему определению риска, поэтому его числа гуляли от прогона к прогону: 56 строк, 29, снова 56.
-
Qwen3-235B дважды перенёс все 46 задач без единой потери, а в третьем прогоне бросил штатный инструмент, пошёл уточнять задачи по одной и принёс отчёт с единственной строкой.
-
Qwen3.5-9B — единственная модель, справившаяся во всех трёх прогонах: 45 из 45, 46 из 46, 46 из 46. Инструмент выдавал ей разное количество задач — и каждый раз она переносила ровно столько, сколько получила.

Пятнадцать шагов: не дошёл никто
-
Sonnet — единственный, кто создавал все 7 файлов во всех прогонах (102 с). Но данные снова собирал своим способом, так что проверить его числа нечем.
-
Qwen3-235B сделал файлы в 2 прогонах из 3, точно перенёс сначала 3 проекта из 6, потом 5 из 6. И работал 11 минут — заметно дольше всех.
-
Qwen3.5-9B создала файлы в 1 прогоне из 3. В двух других — отчиталась о создании семи файлов, не создав ни одного (2,6 мин).
Цепочку из двух шагов безупречно прошли все девять прогонов, цепочку из пятнадцати — ни один из девяти.
Три модели расплачиваются разной монетой
Сложить эти результаты в один рейтинг не выйдет: каждая модель провалилась по-своему. У каждой — своя монета, которой она платит за длину цепочки.
-
Sonnet платит верностью заданию. Единственный дошёл до результата во всех девяти прогонах — и ни разу не соврал о сделанном. Но ни в одном из девяти не решил задачу тем способом, которым просили: собирал данные собственным поиском, по собственному определению риска, — и его числа расходятся между прогонами вдвое. Надёжный исполнитель, который всякий раз знает лучше вас, как надо.
-
Qwen3-235B платит предсказуемостью. Пока идёт штатным путём — переносит данные до последней строки. Но штатным путём он идёт не всегда: примерно каждый третий прогон бросает инструмент и уходит перебирать задачи вручную, сжигая на этом весь бюджет шагов. Промпт тот же, данные те же, а каким путём модель пойдёт сегодня — узнаёшь только по факту.
-
Qwen3.5-9B платит правдивостью. Самая быстрая из трёх и самая точная в переносе: сколько строк получила от инструмента, столько и донесла до файла. Но в длинной задаче она дважды из трёх отчиталась об успехе, которого не было. Это самая дорогая монета: медленный ответ виден сразу, кривые числа ловит сверка, а уверенный отчёт о несделанной работе живёт до тех пор, пока кто-нибудь не откроет пустую папку.
Обвязка у всех одна, задачи и данные тоже. Всё, что выше, — это и есть разница между моделями.
Самый неприятный способ ошибиться
Вот что написала локальная 9B, запросив данные по всем семи проектам и не создав ни одного файла:
Создал 7 файлов в папке “Отчёты” с задачами в риске для каждого проекта: X — 14 строк, Y — 10, Z — 200, V — 20, T — нет задач в риске, C — 83, L — 45. Общее количество строк: 372
Здесь нет ни сообщения об ошибке, ни обрыва связи, ни таймаута. Все числа верные — данные модель действительно получила. Не сделан только сам результат. Пользователь ищет связный отчёт с правильными цифрами и обнаруживает пустую папку.
Вывод для тех, кто строит обвязку: проверяйте результат, а не ответ. Модель заявила семь файлов — обвязка обязана пересчитать их и сказать пользователю правду.
Вывод для тех, кто выбирает модель: частота таких отказов — свойство модели. Обвязка его не лечит, она способна только вовремя его обнаружить.
Так кто прав, и что делать
В главном коллеги правы: обвязку нужно строить самим, именно в ней накапливается инженерная компетенция. Пока готовился доклад, я нашёл и починил в своей обвязке шесть дефектов. После этого локальная модель поднялась с нулевого результата до безупречного переноса данных.
Что это были за дефекты
-
обрезка по max_tokens молча рвала вызов инструмента: модель «вызывала» его, а до исполнения вызов не доходил;
-
жадный сэмплинг вместе с режимом рассуждений загонял Qwen в бесконечную петлю — вылечил рецепт сэмплинга от авторов модели;
-
один из инструментов на определённом фильтре молча возвращал нули — и модель честно пересказывала этот мусор;
-
оборванный на середине запрос подвешивал локальный движок инференса;
-
и ещё по мелочи в конфигурации провайдеров.
Ни один из этих дефектов не был виден в ответах модели. Все нашлись только по журналам вызовов.
Но на той же уже починенной обвязке та же модель дважды из трёх сообщила о файлах, которых не создала. Обвязка подняла общий уровень — и не сделала работу надёжной.
Обвязка задаёт границу, ниже которой результат не опустится. Модель определяет, как быстро качество убывает с каждым новым шагом.
Ограничения методики
-
По три прогона на ячейку — 27 прогонов на всё исследование. Этого достаточно, чтобы увидеть дисперсию и характер отказов, но мало, чтобы утверждать «модель X решает задачу в N% случаев». Выводы здесь качественные, не количественные.
-
Задачи мои, инструменты мои, промпты мои. Сами числа на ваш стек не переносятся. Переносится методика: заморозить всё, кроме модели, и сверять результат с журналом вызовов инструментов.
-
Версии моделей зафиксированы на момент замера; следующие релизы могут перетасовать картину, поэтому замер и должен быть дешёвым и повторяемым.
-
Локальная модель — в 4-битном кванте. Часть её провалов может быть ценой квантования, а не самой модели.
Что по итогу
-
1–2 шага (пересказать, найти, ответить): локальная модель на одной видеокарте справляется не хуже облачных.
-
3–5 шагов (отчёт по образцу): локальная модель, но с автоматической проверкой созданного артефакта.
-
10+ шагов (циклы, сквозные выборки): нужна самая сильная доступная модель, проверка артефакта, предохранители в цикле, повторный прогон при расхождении.
И главное: меряйте на своих задачах, а не по чужим таблицам. Три прогона, свой способ проверки и своя обвязка — избавит вас от неверного решения.
Три вещи, которые стоит унести с собой
-
Один прогон не говорит о модели ничего. Разброс между двумя прогонами одной модели у меня оказался больше, чем разрыв между разными моделями.
-
Улучшения обвязки прибавляются, качество модели умножается на каждом шаге. Чем длиннее цепочка, тем сильнее решает выбор модели.
-
Агент ошибается не сообщением об ошибке, а уверенным отчётом с верными числами. Проверять нужно созданный результат, а не текст ответа.
Если вы гоняли модели в собственной обвязке — расскажите в комментариях, что разваливалось первым: способ решения, перенос данных или правдивость отчёта. Интересно, воспроизводятся ли эти три пункта на чужих стеках.
Автор: madteamlead


