Когда у агента три инструмента, проблем выбора нет. Когда двадцать — выбор становится главной проблемой агента. Сегодня — про tool selection: как помочь модели в большом наборе инструментов и какие архитектурные решения это требует.
Модель выбирает инструмент по совпадению описания и текущего намерения. Когда инструментов мало и они разные — выбор очевиден. Когда много или они похожи — начинаются ошибки: модель путает близкие, выбирает «универсальные», игнорирует подходящие. Лечится не «более умной моделью», а архитектурой: группировкой инструментов, иерархическим выбором, динамической загрузкой, явными подсказками в system prompt. Это и есть промпт-инжиниринг масштаба «целого агента».
Качество выбора инструмента деградирует нелинейно с их количеством. До определённого порога — всё хорошо. После него — начинаются систематические ошибки. Порог примерно такой:
Цифры условные — они зависят от модели, специфичности инструментов, схожести между ними. Но общая форма кривой та же: после 15-20 инструментов начинается заметная деградация выбора.
Что именно идёт не так на больших наборах:
send_email и send_message — модель иногда выбирает не тот.web_search — она его вызывает на любой вопрос, даже когда есть специализированный инструмент.get_customer_orders делает три: list_customers → get_customer → get_orders.Выбор инструмента — это задача, которая решается архитектурой, не «надеждой на умную модель». Чем больше инструментов — тем больше нужно архитектурной работы.
Чтобы помочь модели выбирать лучше, надо понимать, как она это делает. В упрощённом виде — это та же генерация токенов, что и любая работа модели. Сначала разворачивается описание инструментов в system prompt, потом — текущий контекст и запрос. И модель «генерирует» следующее действие — вызов инструмента.
На что модель ориентируется при этой генерации:
Если пользователь сказал «отправь письмо», а есть инструмент send_email с описанием «отправляет письмо» — высокая вероятность выбора.
«Напиши коллеге» → модель понимает, что это про email, даже если слова «email» не было. Тут уже работает обучение модели на больших данных.
Если модель только что вызвала get_emails, следующий шаг логично связан с email. Контекст подсказывает.
Тонкий, но реальный эффект: инструменты, описанные раньше в system prompt, выбираются немного чаще. Это эффект «недавнего внимания».
Когда инструментов много, сигналы начинают конфликтовать:
Поэтому архитектурные решения — это, по сути, способы усилить нужные сигналы и приглушить лишние.
Несколько фундаментальных стратегий. Можно использовать одну, можно комбинировать:
В system prompt инструменты подаются не плоским списком, а сгруппированными по категориям:
Группировка не меняет, какие инструменты есть, но организует контекст. Модель видит структуру, а не свалку. Помогает на больших списках.
Стоимость: почти нулевая. Просто другой формат system prompt.
Двухступенчатый выбор. На первом шаге модель видит небольшой список «роутеров»: handle_email_request, handle_calendar_request, handle_file_request. Каждый — это «вход в домен».
После выбора домена — модель видит только инструменты этого домена. Из 50 инструментов в одну итерацию входит максимум 5-7. Качество выбора возвращается на «нормальное» из таблицы.
Самый мощный подход. Не подаёшь модели все инструменты в system prompt. Вместо этого — заранее анализируешь запрос пользователя (отдельным небольшим LLM-вызовом или эвристикой) и подаёшь только релевантные.
Пример: пользователь спросил «когда у меня следующая встреча?». Анализатор понимает, что это про календарь, и в system prompt подаёт только 3 инструмента календаря. Email, файлы, прочее — не попадают в контекст вообще.
Это даёт два эффекта: экономия токенов (вместо 50 описаний — 3) и повышение точности (модель не путает).
Стоимость: дополнительный LLM-вызов на каждый запрос. Дешевле, чем кажется — для роутинга подходит маленькая модель.
Самый простой и недооценённый подход. В system prompt явно пишешь правила выбора:
send_email, не send_message»web_search используй только когда другие инструменты не подходят. Сначала проверь свои данные через локальные инструменты»Это явные подсказки модели, которые сильно меняют поведение. Не требуют архитектурных переделок — просто хорошо написанный system prompt.
Чем сложнее набор инструментов — тем больше подсказок нужно. Это нормальная часть промпт-инжиниринга для агентов.
В Дне 17 говорили: лучше много маленьких инструментов, чем «универсальный с параметром action». Это верно. Но если у тебя уже 25 маленьких инструментов и есть проблемы выбора — иногда обратное движение оправдано.
Лучший компромисс: среднее количество среднего размера инструментов. Не send_email + send_message + send_dm + send_sms, а одно send_communication(channel, message) с понятными вариантами channel. Удержать число инструментов на 10-15, но не делать чересчур абстрактные «комбайны».
Если ты уверен, что определённые инструменты могут понадобиться в определённых ситуациях — стоит ли вообще их прятать (динамическая загрузка) или лучше держать все и подсказать модели правила?
Эмпирически: прятать выгоднее, чем подсказывать, на наборах больше 20. На меньших — наоборот, подсказки эффективнее. Динамическая загрузка добавляет latency (один LLM-вызов больше), и для маленьких наборов этот overhead не окупается.
«У нас плохой tool selection — возьмём GPT-5 вместо 4o». Большая модель действительно справляется лучше с большими наборами. Но это в 10 раз дороже и в 3-5 раз медленнее. И всё равно — деградирует на 50+ инструментах.
Архитектурные решения (группировка, иерархия, динамика) дают больший эффект на качестве при меньшей стоимости. Менять модель — последний шаг, не первый.
Агент работает, что-то делает, иногда хорошо, иногда плохо — а ты не знаешь, где конкретно сбой. Часто это именно tool selection: модель выбрала не тот инструмент, всё дальше пошло криво.
Привычка: логировать все вызовы инструментов и периодически смотреть статистику. Какие инструменты вызываются чаще всего? Какие — никогда? Какие — невпопад? Это даёт картину того, где архитектура хромает.
«Каждая новая ошибка выбора → новая подсказка в system prompt». Через месяц system prompt — длинная простыня из правил «не используй X для Y» и «когда Z — иди в W». Каждое правило стоит токенов, путает модель, конфликтует с другими.
Признак того, что пора переходить к иерархии или динамике — это больше 5-7 правил выбора в system prompt. Дальнейшие подсказки уже не помогают, а вредят.
Соблазн делать «универсального помощника» с доступом ко всему. На бумаге звучит мощно. На практике — это худший вариант для выбора инструментов: 50+ tools, домены смешаны, контекст замусорен.
Стандартная архитектура зрелых продуктов — несколько специализированных агентов, между которыми переключается главный (или сам пользователь). Это всё ещё с MCP, но с разделением. Об этом — в Дне 20.
В Claude Desktop подключи 5-7 разных MCP-серверов одновременно (filesystem, github, и пару других). У тебя получится 30-50 инструментов в контексте. Сделай простой запрос — например, «найди мне последние файлы, которые я редактировал». Понаблюдай: какой инструмент Claude выберет? Иногда — нужный, иногда — нелепо неподходящий. Это даст тебе живое ощущение деградации выбора на большом наборе.
Возьми гипотетического агента с 20-30 инструментами (можешь взять реальный список из любого MCP-сервера). Разбей их на 3-5 доменов. Для каждого домена придумай «роутер»: какой один инструмент модель должна вызывать, чтобы попасть в этот домен. Подумай, как выглядит system prompt при таком подходе. Это упражнение даст тебе чувство архитектуры — какое разбиение «правильное», а какое — неестественное.
В сообществе AI-инструментов часто публикуют утечки или анализ system prompt'ов известных продуктов. Найди один такой разбор (Cursor system prompt analysis, Claude Code system prompt, что-то подобное). Посмотри, какие там есть подсказки по выбору инструментов. Это покажет тебе, как зрелые команды решают эту задачу — намного больше подсказок, чем кажется на первый взгляд.