← max_tokens

Turn count как продуктовая метрика

Пользователь не чувствует размер контекстного окна. Он чувствует цепочку шагов между запросом и полезным ответом. Если агенту нужно двенадцать последовательных ходов, быстрая модель всё равно не превращает их в один: система двенадцать раз возвращается к модели, инструментам и проверкам. Поздние ходы обычно стоят дороже ранних, потому что снова прогоняют через модель накопленный диалог, результаты инструментов и промежуточное состояние.

Именно эту метрику я бы поставил рядом с задержкой и ценой: turns per request. Не как любопытную деталь в trace, а как ранний продуктовый сигнал.

Суммарные токены могут скрывать разницу. Два запроса выглядят похожими по расходу, но один заканчивает задачу за четыре шага, а другой восемнадцать раз возвращается в цикл. Поэтому важно смотреть не только на tokens, но и на step count, loop flags и похожие поля. Они отделяют решённую работу от бесполезного блуждания — особенно в случаях, где агрегированные токены сглаживают проблему.

Каждый turn — отдельное ожидание

На уровне реализации turn устроен просто: система получает запрос, агент отвечает, а внутри ответа может быть вызов инструмента.

Это определение важно не само по себе. Оно показывает, почему быстрая модель не отменяет последовательность шагов. Если агент читает пять файлов один за другим, пользователь ждёт не один большой ответ, а пять отдельных циклов: вызов модели, запрос к инструменту, чтение результата и следующий шаг.Именно поэтому параллельные tool calls в Continue — не просто оптимизация для красоты. Если пять независимых чтений можно выполнить параллельно, их не нужно прогонять через модель по очереди. Иначе пять чтений превращаются в пять последовательных ожиданий.

Впечатление от продукта формулируется не так: “мы поставили модель быстрее”. Оно формулируется так: “пользователь ждал семь раз, прежде чем получил полезный ответ”.Маленькая модель может ощущаться медленной, если постоянно делает лишние промежуточные шаги. Большая модель может ощущаться приемлемо, если цикл короткий, а инструменты возвращают достаточно данных за один вызов.

Простая часть: больше turn’ов — больше ожиданий. Более неприятная часть: поздние turn’ы часто ещё и дороже, потому что несут больше накопленного контекста.

Поздние ходы дороже ранних

Стоимость агентного запроса не равна числу ходов, умноженному на фиксированный тариф. Поздние ходы обычно несут в модель более длинный контекст, чем ранние.

В ML Systems есть хороший пример: к десятому шагу агент может подавать в модель уже 8k токенов, хотя начинал с 500. При этом prefill примерно линейно масштабируется с длиной контекста. Десятый ход не повторяет первый. Он включает первый ход, а сверху — след решений, результаты инструментов, наблюдения и ошибки, которые появились после него.

С оплатой похожая история, только эффект резче. Augment Code объясняет, что история сообщений растёт линейно по итерациям, а оплачиваемые входные токены — квадратично: каждый новый вызов снова отправляет в модель предыдущий контекст. Поэтому распределение ходов часто показывает проблему раньше, чем её полностью видно в счёте за инфраструктуру.

История сообщений растёт линейно, а оплачиваемые входные токены — квадратично, потому что каждый вызов снова шлёт контекст.

Два публичных примера хорошо показывают этот наклон. Galileo пишет, что пятишаговый ReAct-цикл использует примерно в 10 раз больше токенов, чем прямой ответ. В материале Stevens Institute говорится, что Reflexion-цикл на 10 итераций может потребить в 50 раз больше токенов, чем один линейный проход.

Точный множитель в вашей системе будет другим. Важна форма зависимости: стоимость растёт не только от числа ходов, но и от контекста, который несёт каждый следующий ход.

Больше контекста не лечит проблему

“Дайте агенту больше контекста” часто выглядит разумным первым шагом. Иногда это правда помогает: нужная политика, схема, пример или документ могут убрать лишний запрос к инструменту.

Но больше контекста легко создаёт другую проблему. Он может спрятать нужный факт среди лишнего материала, увеличить prefill и сделать каждый следующий ход тяжелее. Руководство Anthropic по проектированию контекста формулирует этот компромисс прямо: каждый новый токен расходует часть бюджета внимания модели, поэтому контекст нужно отбирать, а не просто расширять.

Это не значит, что маленький контекст всегда лучше. Это значит, что контекст влияет на turn count, но не заменяет эту метрику. Хорошая иерархия извлечения может сократить число ходов: агент быстрее получает нужные данные и меньше блуждает. Свалка всех доступных данных может, наоборот, увеличить число ходов: модель дольше разбирает шум, чаще выбирает обходные маршруты и дороже платит за каждый следующий шаг.

Без распределения turns per request на реальном трафике обе истории звучат правдоподобно. Большое окно может сделать агента сильнее. А может просто дать ему больше места, чтобы дольше путаться.

Вынесите turns per request на дашборд

Начните с распределения turns per request на продакшн-трафике. При необходимости обезличьте данные, но сохраняйте структуру агентного цикла.Для каждого агентного запуска записывайте: id запроса, маршрут, модель, вызовы инструментов, номер хода, входные и выходные токены, задержку, причину остановки, состояние ошибки и финальный результат.Не ограничивайтесь агрегатами. Сохраняйте сырую последовательность ходов: именно она показывает циклы, повторы и места, где агент возвращается к той же проблеме без прогресса.

Затем разделите ходы на продуктивные и пустые.

Продуктивный ход меняет состояние задачи: достаёт недостающий факт, выполняет нужное действие, сужает план, задаёт необходимое уточнение или формирует финальный ответ.Пустой ход не двигает задачу вперёд. Он повторяет запрос, снова читает тот же источник без новой пользы, исправляет ошибку форматирования, которую можно было предотвратить раньше, вызывает инструмент, который маршрутизация могла выбрать до входа в агентный цикл, или уходит в самопроверку, которая не меняет следующее действие.

Дашборд должен показывать p50, p90 и p99 turns per request по маршрутам. Рядом — долю успешных запусков по диапазонам ходов, стоимость на запрос и задержку на запрос.Полезный вывод выглядит не так: “агенты в среднем делают 6,2 хода”.Полезный вывод выглядит так: “тикеты по счетам обычно закрываются к ходу 4, а задачи миграции кода держат p90 на 17 и начинают чаще падать после хода 12”.

Так turn count становится опережающим индикатором. Распределение начинает ехать вверх до того, как пользователи массово жалуются на медленную систему. Хвост распределения толстеет до того, как финансы замечают счёт.

Сокращайте пустые ходы, а не полезную работу

Цель — не минимальное число ходов любой ценой. Цель — ноль пустых ходов.

Маршрутизация должна происходить до входа в агентный цикл, пока выбор ещё дешёвый. Классификатор может решить, нужно ли вообще звать агента, какой маршрут выбрать и какие инструменты подготовить. Так простые запросы не попадают в дорогой общий цикл.

Результаты инструментов должны быть полнее. Если модели нужны пять связанных фактов, один инструмент часто должен вернуть все пять: с источниками, статусами уверенности и недостающими полями. Иначе агент тратит отдельные ходы на то, что система могла собрать заранее. Составные инструменты развивают ту же идею. В документации Claude про programmatic tool calling описан подход, где код вызывает инструменты внутри контейнера выполнения, вместо того чтобы каждый раз возвращаться в модель ради отдельного tool call. Смысл тот же: не превращать понятный процесс в цепочку лишних агентных ходов.

Параллельность — ещё один прямой рычаг. Независимые чтения не должны проходить через модель по очереди. Если три источника можно забрать одновременно, заберите их одновременно и отдайте следующему ходу уже объединённый результат.

Состояние тоже важно. Агент не должен заново выводить то, что система уже знает. Храните устойчивое состояние, промежуточные решения, id найденных источников и отклонённые ветки в компактном виде. Передавайте это состояние вперёд, вместо того чтобы просить модель каждый раз восстанавливать его из длинного лога диалога.

Наконец, добавьте бюджет ходов с мягкой деградацией. На ходу 6 можно продолжать обычный сценарий. На ходу 10 — вернуть частичный ответ с открытыми вопросами. На ходу 14 — остановить исследование инструментами и попросить человека выбрать направление.Бюджет ходов — это продуктовый контракт, а не только инфраструктурный ограничитель.

Оптимизируйте произведение ходов и контекста

Turn count связывает два решения.

Первое принимается до входа в агентный цикл: нужно ли вообще звать агента. Дешёвый классификатор или маршрутизатор может развести прямые ответы, поиск, детерминированные сценарии и эскалации к человеку по разным путям.

Дешёвый классификатор отправляет запрос в прямой ответ, поиск, сценарий или к человеку до дорогого агентного цикла.

Второе решение — какой контекст нужен выбранному пути: память, извлечение, файлы, схемы инструментов, сводки и сохранённое состояние.

Эти решения нельзя оптимизировать отдельно. Слишком мало контекста создаёт лишние обращения. Слишком много контекста делает каждое обращение тяжелее и всё равно может порождать уточняющие ходы.

Turn count заставляет смотреть на простую зависимость: стоимость и задержка складываются из числа последовательных ходов и контекста, который несёт каждый ход.

Упрощённо: стоимость и задержка ≈ ходы × контекст на ход Формула грубая, но полезная. Если сократить контекст, но оставить длинный цикл, агент продолжит тратить время на лишние шаги. Если дать агенту всё сразу, но не убрать повторы, поздние ходы станут дорогими. Я бы не гнался за одной универсальной целью. Запрос по счёту, который закрывается за два хода, и миграция кода на двенадцать ходов — разные продукты. Дашборд должен показывать это по маршруту и результату, на реальном продакшн-распределении, а не на красивом бенчмарке. Практическая цель уже, но честнее: каждый ход должен делать работу. Если ход не меняет состояние, не собирает доказательства, не выполняет действие и не приближает финальный ответ, продукт заставляет пользователя ждать, пока агент платит за перечитывание самого себя.

<|endoftext|> · 2 627 tok · finish_reason: stop

// top_k · nearest neighbors

  1. [0] 0.735 Не каждый запрос заслуживает агента
  2. [1] 0.712 Промпт — это 5% работы: контекст-инжиниринг LLM-агента в проде
  3. [2] 0.655 Агент прошёл eval. В прод я его всё равно не пущу

cosine of embeddings · scale 0–1 absolute · computed at build

integrity: sha256 cb85062b…

tokens · o200k_base