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

Встроенные инструменты агента

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

Каждый инструмент здесь регистрируется, только когда для запуска подключён его опорный ресурс — супервизор языкового сервера или отладки, парсер tree-sitter, фабрика ядер, порт вопросов, состав vibe. Обнаружение языкового сервера или отладочного адаптера для этой рабочей копии — отдельная, более поздняя проверка (status / adapters): эти инструменты остаются на поверхности, чтобы агент мог спросить, почему ничего не работает, а не гадать.

Каждый инструмент объявляет уровень, и уровень решает, какие поверхности его видят, — а не просто то, спрашивает ли он подтверждение. Режим плана и субагенты только для чтения ограничены уровнем read, поэтому инструмент уровня write или exec полностью отсутствует в их схеме.

Уровень Значение Инструменты здесь
read Без побочных эффектов lsp, ast_grep, ask_user, пять vibe_*
write Изменяет файлы lsp_rename, ast_edit, resolve
exec Запускает процесс или управляет им debug, eval

Регистрируется, когда у запуска есть супервизор языкового сервера и рабочий каталог. Способен ли сервер на самом деле ответить, определяется в момент вызова как пересечение: маркер корня должен существовать, и бинарник сервера должен разрешаться. Каждое из условий само по себе означает, что сервер не запустится — status так и говорит, — а не молчаливое предположение.

Позиции адресуются строкой line плюс подстрокой symbol, никогда — столбцом. Модель, у которой просят столбец, гадает, а неверная догадка разрешается в другой символ на той же строке — ответ, который выглядит правильным, но говорит о другом. Пропуск symbol в навигационном действии — это ошибка, а не догадка о первом столбце.

Действие Аргументы Возвращает
diagnostics file (или "*") Ошибки и предупреждения; "*" вместо этого запускает проверку проекта
definition file, line, symbol Где объявлен символ
type_definition file, line, symbol Где объявлен его тип
implementation file, line, symbol Конкретные реализации
references file, line, symbol Все использования, не более 50
hover file, line, symbol Сигнатура и doc-комментарий
symbols query или file Поиск по рабочему пространству с query (не более 100); символы документа с file (не более 200)
code_actions file, line, symbol Быстрые исправления, которые предлагает сервер
status — Какие серверы работают и для каких корней
reload — Перезапускает сервер для этого корня

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

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

lsp_rename — переименование в пределах проекта

Заголовок раздела «lsp_rename — переименование в пределах проекта»

Отдельный инструмент уровня write ровно по одной причине: уровень решает видимость. Добавление переименования в lsp либо дало бы исследователю только для чтения возможность переписать репозиторий, либо поставило бы каждый hover за запрос подтверждения.

Аргумент Значение
file Где находится символ
line Строка с нумерацией от 1
symbol Подстрока, опознающая его в этой строке
new_name Как его назвать

Находит код по форме, а не по тексту. $NAME сопоставляется с любым узлом, $$$NAME — с последовательностью соседних узлов, а $_ — это подстановочный знак, который ничего не связывает.

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

ast_grep(pattern: "if ($X != null) $X.dispose()", language: "dart")

находит проверку, которая освобождает то же, что проверяла, и не находит ту, что освобождает что-то другое.

Аргумент Значение
pattern Фрагмент кода с метапеременными
path Файл или каталог для поиска; по умолчанию всё рабочее пространство
language Идентификатор поставляемой грамматики (dart, python, rust, c, …). Выводится, когда path указывает на файл
max_results По умолчанию 50

ast_edit — структурная перезапись с подготовкой

Заголовок раздела «ast_edit — структурная перезапись с подготовкой»

То же сопоставление, плюс шаблон rewrite, в который подставляются обратно метапеременные. Ничего не записывается. Изменение подготавливается, и результат называет edit_id.

ast_edit(pattern: "dispose($X)", rewrite: "$X.dispose()", language: "dart")
→ (proposed) 12 replacements in 4 files … call resolve with edit_id "edit_1"
Аргумент Значение
pattern Что сопоставлять
rewrite Что подставить на это место, с подстановкой $NAME
path Область; по умолчанию всё рабочее пространство
language Идентификатор языка

resolve — зафиксировать или отбросить подготовленное изменение

Заголовок раздела «resolve — зафиксировать или отбросить подготовленное изменение»
Аргумент Значение
edit_id Из результата (proposed)
action accept или discard

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


Регистрируется, когда у запуска есть супервизор отладочных сессий, рабочий каталог и идентификатор разговора. Способен ли адаптер на самом деле запуститься, определяется в момент вызова по тому же правилу пересечения, что и для языкового сервера (маркер корня и бинарник). Уровень exec; небезопасен при параллельном выполнении (сессия — это состояние между вызовами, поэтому continue, обогнавший stack, прочитал бы кадр, который уже сдвинулся).

Одна сессия на разговор, с жёстким TTL (30 минут). Второй launch отклоняется, а не заменяет первый молча.

Операция Аргументы Примечания
adapters — Какие адаптеры здесь пригодны и почему нет
status — Работает ли сессия и где она остановилась
breakpoints file, lines[] Пустой lines очищает файл. Можно ставить до запуска
launch program, args[] Запускает программу остановленной на ваших точках останова
attach port Подключается к уже запущенной отлаживаемой программе
continue thread_id? Выполняет до следующей остановки
pause thread_id? Останавливает её там, где она есть
step_over / step_in / step_out thread_id? Делает один шаг
threads — Идентификаторы и имена потоков
stack thread_id? Кадры, не более 30
scopes frame_id Области видимости кадра, у каждой есть reference
variables reference Дочерние элементы, не более 50; значения не длиннее 400 символов
evaluate expression, frame_id? Вычисляется в собственной области видимости кадра
output — stdout/stderr отлаживаемой программы, с ограничением размера
terminate — Завершает сессию и убивает адаптер
Идентификатор Команда Маркеры корня
dart dart debug_adapter pubspec.yaml
debugpy python3 -m debugpy.adapter pyproject.toml, setup.py, requirements.txt
lldb lldb-dap Cargo.toml, CMakeLists.txt
delve dlv dap go.mod

debugpy предпочитает локальные для проекта .venv/bin или venv/bin вместо $PATH: python из $PATH — это другое окружение, и подключение не из того окружения падает так, что это читается как сломанный код.


Ячейка Python или JavaScript, переменные, импорты и загруженные данные которой переживают переходы между вызовами. Уровень exec; небезопасна при параллельном выполнении.

Аргумент Значение
code Ячейка
description Обязательно. 5–10 слов для метки в транскрипте
language python (по умолчанию) или javascript
reset Отбросить интерпретатор и сначала начать с чистого
  • Последнее выражение отражается так, как это делает блокнот.
  • display() работает, датафрейм pandas отрисовывается как таблица, а график matplotlib возвращается как изображение, которое показывает транскрипт.
  • Идиомы IPython, которые люди набирают рефлекторно, — %pip, %cd, !cmd, %%bash, %%timeit — переписываются в обычный код. %pip вдобавок вытесняет sys.modules, поэтому следующий import видит то, что только что установили.

Вызов собственных инструментов из ячейки

Заголовок раздела «Вызов собственных инструментов из ячейки»
contents = tool("read", {"path": "lib/auth.dart"})

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

Тайм-аут ячейки — это бюджет бездействия (по умолчанию 5 минут), и он приостанавливается, пока не завершится вызов через мост, поэтому ячейка, которая разветвляется на субагентов, не убивается посреди разветвления.


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

Аргумент Значение
question Что спросить
context Необязательно: почему вы спрашиваете и что зависит от ответа
options[] Варианты, каждый {label, description?}
allow_free_text Принимается ли ответ, набранный вручную
multi_select Можно ли выбрать несколько вариантов

Пропуск — это успех: действуйте на основании заявленного допущения и не спрашивайте снова. Тайм-аут — это ошибка с той же инструкцией. Запросы разрешения («можно мне это сделать?») — отдельный шлюз, и они отрисовываются в разговоре той же карточкой.

Регистрируется, только когда существуют и порт вопросов, и целевое пространство. Без подключённого человека вызов падает, а не блокируется навсегда, — та же позиция отказа по умолчанию, которую занимает prompt ограничения без подключённого подтверждающего.


Регистрируются, только пока включён режим vibe. Все пять относятся к уровню read: шлюз должен стоять на инструментах воркера, там, где правка действительно происходит.

Инструмент Аргументы Примечания
vibe_spawn brief, label, tier? Возвращает управление сразу; воркер продолжает работу
vibe_send worker_id, message Дописывает к заданию и запускает заново
vibe_wait worker_id, timeout_seconds? Блокируется, пока он не завершится
vibe_kill worker_id Останавливает его
vibe_list — Уровень, статус, затраченное время и последний результат

tier — это fast (механическая работа с чёткой спецификацией) или good (проектирование, суждение или проверка результата воркера fast).