Вбудовані інструменти агента
Це прив’язані до сервера інструменти, які вбудоване середовище виконання агента реєструє безпосередньо — мовний сервер, структурний пошук, налагоджувач, ядра, запитання й керування воркерами — на противагу інструментам MCP, які воно під’єднує, та загальним інструментам для файлів, пошуку й оболонки із середовища виконання harness. Їх немає в реєстрі 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 |
lsp — запити до мовного сервера
Розділ із назвою «lsp — запити до мовного сервера»Реєструється, коли запуск має наглядача мовного сервера та робочий каталог. Чи сервер справді може відповісти, визначається під час виклику як перетин: кореневий маркер має існувати і бінарник сервера має резолвитися. Кожна з умов окремо означає, що жоден сервер не запуститься — 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 |
Сигнатура й коментар документації |
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 |
Як його назвати |
ast_grep — структурний пошук
Розділ із назвою «ast_grep — структурний пошук»Знаходить код за формою, а не за текстом. $NAME зіставляє будь-який вузол, $$$NAME — послідовність сусідніх вузлів, а $_ — це шаблонний символ, який нічого не зв’язує.
Властивість, яка робить його механізмом зіставлення, а не regex із зайвими кроками: метазмінна, повторена в одному шаблоні, має захопити той самий текст.
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 |
Кожен файл звіряють із вмістом, зафіксованим у момент підготовки, і будь-яка розбіжність відхиляє всю зміну. Частково застосований структурний перезапис лишає дерево, яке не компілюється ні за старою формою, ні за новою.
debug — керувати налагоджувачем
Розділ із назвою «debug — керувати налагоджувачем»Реєструється, коли запуск має наглядача сесій налагодження, робочий каталог та ідентифікатор розмови. Чи адаптер справді може запуститися, визначається під час виклику за тим самим правилом перетину, що й для мовного сервера (кореневий маркер і бінарник). Рівень 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 — це інше середовище, і під’єднання не з того середовища падає так, що це читається як зламаний код.
eval — постійні інтерпретатори
Розділ із назвою «eval — постійні інтерпретатори»Комірка 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"})Міст знову входить у реєстр інструментів harness, тож обмеження, схвалення та кожна обгортка застосовуються точно так, як до виклику, виданого моделлю. Він іде власним каналом ядра, а не через loopback-сокет: жодного порту, жодного секрету, жодного правила вихідного трафіку.
Тайм-аут комірки — це бюджет бездіяльності (типово 5 хвилин), і він призупиняється, поки триває виклик через міст, тож комірку, яка розгалужується на субагентів, не вбивають посеред розгалуження.
ask_user — поставити людині запитання
Розділ із назвою «ask_user — поставити людині запитання»Рівень read. Єдиний спосіб, яким запуск щось питає в оператора. Він показує в розмові пронумеровану картку й блокує, доки хтось не відповість, не пропустить або доки запитання не вичерпає тайм-аут. Ніколи не пишіть запитання як повідомлення в чаті — це завершує хід.
| Аргумент | Значення |
|---|---|
question |
Що спитати |
context |
Необов’язково: чому ви питаєте і що залежить від відповіді |
options[] |
Варіанти, кожен {label, description?} |
allow_free_text |
Чи приймається введена відповідь |
multi_select |
Чи можна вибрати кілька варіантів |
Пропуск — це успіх: продовжуйте на заявленому припущенні й не питайте знову. Тайм-аут — це помилка з тією самою інструкцією. Запити на дозвіл («чи можна мені це зробити?») — це окремий шлюз, і вони показуються як така сама картка в розмові.
Реєструється лише тоді, коли існують і порт запитань, і цільовий простір. Без під’єднаної людини виклик падає, а не блокується назавжди — та сама позиція відмови за замовчуванням, яку займає prompt обмеження, коли не під’єднано жодного того, хто схвалює.
vibe_* — керування фоновими воркерами
Розділ із назвою «vibe_* — керування фоновими воркерами»Реєструється лише поки увімкнено режим 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-воркер).