Перейти к содержимому

Настроить контекст инструментов агента

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

Откройте разговор и нажмите индикатор использования контекста в заголовке разговора. Он заново собирает ровно ту поверхность, которую отправил бы следующий запуск, ничего при этом не выполняя. Ещё (или команда /context) открывает полный обозреватель контекста, где можно изучить каждый инструмент.

Здесь важны два сегмента:

  • Определения инструментов и MCP и динамические инструменты — резидентный набор с реальной стоимостью каждого инструмента в токенах.
  • Инструменты по требованию — отложенный индекс. За каждую запись здесь начисляется только её имя, потому что запрос несёт лишь имя; при открытии всё равно показываются полное описание и схема, так что видно, сколько она стоила бы, если бы запуск её подтянул.

Если отложенный сегмент пуст, отложенная загрузка для этого сервера выключена. Проверьте --tool-deferral в CLI cc_server.

Измените, какие инструменты загружаются заранее

Заголовок раздела «Измените, какие инструменты загружаются заранее»

Резидентный набор — это политика, а не конфигурация: он живёт в ModeToolPolicy (packages/cc_domain/lib/features/mcp/domain/value_objects/mode_tool_policy.dart) и применяется к каждому запуску:

  • residentBuiltins — словарь файлов и оболочки.
  • residentDiscovery — search_tools и list_my_tools. Не удаляйте их: именно так агент добирается до всего остального.
  • residentMcpTools — несколько инструментов Control Center, которые стоят своей схемы в каждом запросе.
  • Блок для каждого режима — для инструментов, которые данный режим использует почти на каждом ходу.

При его редактировании действуют два правила:

Добавляйте инструмент, только если его использует большинство запусков. Каждое имя стоит своей схемы в каждом запросе каждого запуска — и так навсегда. Инструмент, важный когда он нужен, но в целом редкий, относится к отложенной половине: агент всё равно его найдёт.

Используйте настоящее имя инструмента. Резидентное имя, не совпадающее ни с одним инструментом, инертно: ни ошибки, ни предупреждения — инструмент просто откладывается. test/tooling/resident_tool_names_test.dart это ловит, а заодно удерживает каждый режим в пределах 40 резидентных инструментов — в этом и смысл упражнения: за этой полосой точность выбора инструментов заметно падает.

Обязательные и закреплённые глаголы режима добавляются автоматически, поэтому собственный глагол вывода режима перечислять никогда не нужно.

Диагностируйте неудачный выбор инструмента

Заголовок раздела «Диагностируйте неудачный выбор инструмента»

Когда агент использовал не тот инструмент или заявил, что чего-то не может, разберитесь, что из трёх вещей произошло.

Каждый запуск записывает, какие отложенные инструменты он загрузил и что это вызвало — прямой вызов по имени или запрос search_tools. Откройте поток событий запуска (Настройки → Рабочее пространство → Агенты → агент → Журнал → Просмотр) и поищите [harness] loaded N deferred tool(s).

  • Ничего не записано, а агент сказал, что возможности нет — он даже не искал. Это проблема промпта, а не поиска: отложенный индекс присутствует в его системном промпте вместе с указанием не объявлять возможность отсутствующей, пока поиск не вернулся пустым.
  • Поиск записан, но ничего не загрузилось — настоящий промах поиска. Переходите к шагу 2.
  • Инструменты загрузились, но использован не тот — найденные инструменты слишком похожи. Переходите к шагу 3.

search_tools сопоставляет имена, описания и названия аргументов. Промах почти всегда означает, что в описании нет слов, которые использовал агент.

Добавьте их. Описания — это поисковый индекс, поэтому удлиняйте их, а не сокращайте — пишите словарь, который оператор действительно набрал бы (“assign”, “hand off”, “give to”), а не только внутреннее существительное. Сокращение описания ради экономии токенов лишает вас и попадания в поиске, и точности выбора, а экономит почти ничего по сравнению со схемой.

Если нужный инструмент существует, но ранжируется низко, для этого и предназначен аргумент limit; собственное описание инструмента подсказывает агенту расширить поиск, который выглядит близким, но промахивается.

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

ticket_relation и ticket_pr_link следуют этому образцу: каждый обрабатывает связывание и развязывание через различающий аргумент. Выбор, сделанный внутри одного вызова, с полным контекстом запроса, надёжнее выбора между двумя похожими описаниями.

Оставляйте инструменты раздельными, когда им нужны разные правила подтверждения, разный аудит или разная отрисовка, — это причины, по которым объединение обошлось бы по-настоящему дорого.

Доля попаданий в кэш отображается в разделе Наблюдаемость → Инсайты как Доля кэша. У здорового долгого разговора она высокая; если она стабильно низкая, что-то перезаписывает префикс на каждом ходу.

Частые причины, в порядке вероятности:

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

Отключение отложенной загрузки через --tool-deferral=off — законный A/B-тест, позволяющий выяснить, вызвано ли изменение поведения двухуровневой поверхностью. Он в точности воспроизводит запрос, каким тот был до появления отложенной загрузки, поэтому если поведение сохраняется и с выключенной загрузкой, причина не в поверхности.