Wbudowane narzędzia agentów
To narzędzia związane z serwerem, które wbudowane środowisko uruchomieniowe agenta rejestruje bezpośrednio — serwer językowy, wyszukiwanie strukturalne, debugger, kernele, pytania i sterowanie workerami — w odróżnieniu od narzędzi MCP, które mostkuje, oraz ogólnych narzędzi plikowych, wyszukiwania i powłoki ze środowiska uruchomieniowego harnessu. Nie ma ich w rejestrze MCP: zewnętrzny klient MCP ich nie zobaczy, bo każde jest przypisane do żywego zasobu po stronie serwera — procesu serwera językowego, adaptera debuggera, interpretera — który należy do jednego uruchomienia.
Każde narzędzie tutaj jest rejestrowane tylko wtedy, gdy jego zasób zaplecza jest podłączony na czas uruchomienia — nadzorca serwera językowego lub debugowania, parser tree-sittera, fabryka kernelów, port pytań, lista workerów vibe. Wykrywanie serwera językowego lub adaptera debuggera dla tej kopii roboczej to osobne, późniejsze sprawdzenie (status / adapters): te narzędzia pozostają na powierzchni, żeby agent mógł zapytać, dlaczego nic nie da się użyć, zamiast zgadywać.
Poziomy zatwierdzania
Dział zatytułowany „Poziomy zatwierdzania”Każde narzędzie deklaruje poziom, a poziom decyduje o tym, które powierzchnie je widzą — nie tylko o tym, czy pojawia się prośba o zatwierdzenie. Tryb planu i podagenci tylko do odczytu są ograniczone do poziomu read, więc narzędzie poziomu write lub exec jest całkowicie nieobecne w ich schemacie.
| Poziom | Znaczenie | Narzędzia tutaj |
|---|---|---|
read |
Bez efektów ubocznych | lsp, ast_grep, ask_user, pięć vibe_* |
write |
Zmienia pliki | lsp_rename, ast_edit, resolve |
exec |
Uruchamia proces lub steruje nim | debug, eval |
lsp — zapytania do serwera językowego
Dział zatytułowany „lsp — zapytania do serwera językowego”Rejestrowane, gdy uruchomienie ma nadzorcę serwera językowego i katalog roboczy. To, czy serwer faktycznie potrafi odpowiedzieć, jest wykrywane w momencie wywołania, jako część wspólna: znacznik korzenia musi istnieć i plik binarny serwera musi dać się odnaleźć. Każdy z tych warunków osobno oznacza, że żaden serwer nie startuje — status tak właśnie mówi — a nie ciche zgadywanie.
Pozycje są adresowane za pomocą line oraz podciągu symbol, nigdy przez kolumnę. Model poproszony o kolumnę zgaduje, a błędne trafienie wskazuje inny symbol w tym samym wierszu — odpowiedź, która wygląda poprawnie, a dotyczy czegoś innego. Pominięcie symbol w akcji nawigacyjnej jest błędem, a nie zgadywaniem pierwszej kolumny.
| Akcja | Argumenty | Zwraca |
|---|---|---|
diagnostics |
file (albo "*") |
Błędy i ostrzeżenia; "*" uruchamia zamiast tego sprawdzanie całego projektu |
definition |
file, line, symbol |
Gdzie symbol jest zadeklarowany |
type_definition |
file, line, symbol |
Gdzie zadeklarowano jego typ |
implementation |
file, line, symbol |
Konkretne implementacje |
references |
file, line, symbol |
Każde użycie, ograniczone do 50 |
hover |
file, line, symbol |
Sygnatura i komentarz dokumentacyjny |
symbols |
query albo file |
Wyszukiwanie w obszarze roboczym z query (ograniczone do 100); symbole dokumentu z file (ograniczone do 200) |
code_actions |
file, line, symbol |
Szybkie poprawki oferowane przez serwer |
status |
— | Które serwery działają i dla których korzeni |
reload |
— | Restartuje serwer dla tego korzenia |
Diagnostyka przy zapisie
Dział zatytułowany „Diagnostyka przy zapisie”Zysk nie polega na samym narzędziu. write, edit i apply_patch są opakowane: po zapisie plik jest synchronizowany i zapisywany przez serwer językowy, a do wyniku narzędzia trafiają wyłącznie nowo wprowadzone komunikaty diagnostyczne. Agent dowiaduje się, że zepsuł kompilację, w momencie, w którym ją zepsuł — bez konieczności pamiętania o tym, żeby o to zapytać.
Komunikaty już zgłoszone są pomijane dzięki rejestrowi prowadzonemu dla każdego uruchomienia, z kluczem opartym na wadze, kodzie i komunikacie — pozycja jest celowo wyłączona, więc komunikat, który jedynie przesunął się o cztery linie w dół, nie zostaje ponownie zgłoszony jako nowy.
lsp_rename — zmiana nazw w całym projekcie
Dział zatytułowany „lsp_rename — zmiana nazw w całym projekcie”Osobne narzędzie poziomu write, z dokładnie jednego powodu: to poziom decyduje o widoczności. Włączenie zmiany nazw do lsp albo dałoby eksploratorowi tylko do odczytu możliwość przepisywania repozytorium, albo postawiłoby każde hover za prośbą o zatwierdzenie.
| Argument | Znaczenie |
|---|---|
file |
Gdzie znajduje się symbol |
line |
Wiersz numerowany od 1 |
symbol |
Podciąg identyfikujący go w tym wierszu |
new_name |
Jak go nazwać |
ast_grep — wyszukiwanie strukturalne
Dział zatytułowany „ast_grep — wyszukiwanie strukturalne”Znajduje kod po kształcie, a nie po tekście. $NAME dopasowuje dowolny węzeł, $$$NAME dopasowuje serię węzłów rodzeństwa, a $_ to symbol wieloznaczny, który niczego nie wiąże.
Cechą, która czyni go dopasowywaczem, a nie wyrażeniem regularnym z dodatkowymi krokami, jest to, że metazmienna powtórzona w jednym wzorcu musi przechwycić ten sam tekst.
ast_grep(pattern: "if ($X != null) $X.dispose()", language: "dart")pasuje do warunku ochronnego, który zwalnia to, co sprawdził, i nie pasuje do takiego, który zwalnia coś innego.
| Argument | Znaczenie |
|---|---|
pattern |
Fragment kodu z metazmiennymi |
path |
Plik lub katalog do przeszukania; domyślnie cały obszar roboczy |
language |
Identyfikator dostarczonej gramatyki (dart, python, rust, c, …). Wnioskowany, gdy path wskazuje plik |
max_results |
Domyślnie 50 |
ast_edit — przepisanie strukturalne w poczekalni
Dział zatytułowany „ast_edit — przepisanie strukturalne w poczekalni”To samo dopasowywanie plus szablon rewrite z podstawionymi z powrotem metazmiennymi. Nic nie zostaje zapisane. Zmiana trafia do poczekalni, a wynik podaje 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"| Argument | Znaczenie |
|---|---|
pattern |
Co dopasować |
rewrite |
Co wstawić w to miejsce, z podstawionymi $NAME |
path |
Zakres; domyślnie cały obszar roboczy |
language |
Identyfikator języka |
resolve — zatwierdź albo odrzuć zmianę z poczekalni
Dział zatytułowany „resolve — zatwierdź albo odrzuć zmianę z poczekalni”| Argument | Znaczenie |
|---|---|
edit_id |
Z wyniku (proposed) |
action |
accept albo discard |
Każdy plik jest porównywany z treścią zapisaną w momencie przygotowania, a każda niezgodność odrzuca całą zmianę. Częściowo zastosowane przepisanie strukturalne zostawia drzewo, które nie kompiluje się ani w starym, ani w nowym kształcie.
debug — sterowanie debuggerem
Dział zatytułowany „debug — sterowanie debuggerem”Rejestrowane, gdy uruchomienie ma nadzorcę sesji debugowania, katalog roboczy i identyfikator rozmowy. To, czy adapter faktycznie potrafi wystartować, jest wykrywane w momencie wywołania, według tej samej zasady części wspólnej co w przypadku serwera językowego (znacznik korzenia i plik binarny). Poziom exec; nie jest bezpieczne równolegle (sesja to stan trwający między wywołaniami, więc continue wyprzedzające stack odczytałoby ramkę, która już się przesunęła).
Jedna sesja na rozmowę, z twardym TTL (30 minut). Drugie launch jest odrzucane, zamiast po cichu zastępować pierwsze.
| Operacja | Argumenty | Uwagi |
|---|---|---|
adapters |
— | Które adaptery są tutaj użyteczne i dlaczego nie |
status |
— | Czy sesja działa i gdzie się zatrzymała |
breakpoints |
file, lines[] |
Puste lines czyści plik. Można je ustawić przed uruchomieniem |
launch |
program, args[] |
Uruchamia program zatrzymany na Twoich punktach przerwania |
attach |
port |
Podłącza się do już działającego debugowanego procesu |
continue |
thread_id? |
Biegnie do następnego zatrzymania |
pause |
thread_id? |
Zatrzymuje go tam, gdzie jest |
step_over / step_in / step_out |
thread_id? |
Przesuwa o jeden krok |
threads |
— | Identyfikatory i nazwy wątków |
stack |
thread_id? |
Ramki, ograniczone do 30 |
scopes |
frame_id |
Zasięgi ramki, każdy z reference |
variables |
reference |
Dzieci, ograniczone do 50, wartości do 400 znaków |
evaluate |
expression, frame_id? |
Obliczane w zasięgu samej ramki |
output |
— | stdout/stderr debugowanego procesu, ograniczone |
terminate |
— | Kończy sesję i zabija adapter |
Adaptery
Dział zatytułowany „Adaptery”| Id | Polecenie | Znaczniki korzenia |
|---|---|---|
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 preferuje lokalne dla projektu .venv/bin lub venv/bin ponad $PATH: Python z $PATH to inne środowisko, a podłączenie z niewłaściwego zawodzi w sposób, który wygląda jak zepsuty kod.
eval — trwałe interpretery
Dział zatytułowany „eval — trwałe interpretery”Komórka Pythona lub JavaScriptu, której zmienne, importy i wczytane dane przetrwają między wywołaniami. Poziom exec; nie jest bezpieczna równolegle.
| Argument | Znaczenie |
|---|---|
code |
Komórka |
description |
Wymagane. Od 5 do 10 słów na etykietę transkryptu |
language |
python (domyślnie) albo javascript |
reset |
Odrzuca interpreter i zaczyna od czystego stanu |
- Ostatnie wyrażenie jest zwracane tak, jak robi to notatnik.
display()działa, ramka pandas renderuje się jako tabela, a wykres matplotlib wraca jako obraz, który pokazuje transkrypt.- Idiomy IPython, które wpisuje się odruchowo —
%pip,%cd,!cmd,%%bash,%%timeit— są przepisywane na zwykły kod.%pipdodatkowo usuwa moduły zsys.modules, więc następnyimportwidzi to, co właśnie zainstalowano.
Wywoływanie własnych narzędzi z wnętrza komórki
Dział zatytułowany „Wywoływanie własnych narzędzi z wnętrza komórki”contents = tool("read", {"path": "lib/auth.dart"})Most wchodzi z powrotem do rejestru narzędzi harnessu, więc guardraile, zatwierdzanie i każde opakowanie działają dokładnie tak samo jak przy wywołaniu zleconym przez model. Korzysta z własnego potoku kernela, a nie z gniazda loopback: żadnego portu, żadnego sekretu, żadnej reguły ruchu wychodzącego.
Limit czasu komórki to budżet bezczynności (domyślnie 5 minut), który jest wstrzymywany, gdy wywołanie przez most jest w toku, więc komórka rozdzielająca pracę na subagentów nie zostaje zabita w połowie rozdzielania.
ask_user — zadaj człowiekowi pytanie
Dział zatytułowany „ask_user — zadaj człowiekowi pytanie”Poziom read. Jedyny sposób, w jaki uruchomienie pyta operatora o cokolwiek. Renderuje w rozmowie kartę z numerowanymi opcjami i blokuje się, aż ktoś odpowie, pominie pytanie albo upłynie jego limit czasu. Nigdy nie zapisuj pytania jako wiadomości czatu — to kończy turę.
| Argument | Znaczenie |
|---|---|
question |
O co zapytać |
context |
Opcjonalne: dlaczego pytasz i co zależy od odpowiedzi |
options[] |
Opcje, każda {label, description?} |
allow_free_text |
Czy odpowiedź wpisana z klawiatury jest przyjmowana |
multi_select |
Czy można wybrać kilka opcji |
Pominięcie to sukces: działaj na podstawie wyraźnie podanego założenia i nie pytaj ponownie. Upłynięcie limitu czasu to błąd z tą samą instrukcją. Prośby o pozwolenie („czy mogę to zrobić?”) to osobna bramka i renderują się jako ta sama karta w rozmowie.
Rejestrowane tylko wtedy, gdy istnieje zarówno port pytań, jak i docelowa przestrzeń. Bez podłączonego człowieka wywołanie zawodzi, zamiast blokować się na zawsze — ta sama postawa domyślnej odmowy (fail-closed), którą przyjmuje prompt guardraila, gdy nie ma podłączonego zatwierdzającego.
vibe_* — kierowanie workerami w tle
Dział zatytułowany „vibe_* — kierowanie workerami w tle”Rejestrowane tylko wtedy, gdy włączony jest tryb vibe. Wszystkie pięć należą do poziomu read: bramka należy do narzędzi workera, tam gdzie faktycznie dochodzi do edycji.
| Narzędzie | Argumenty | Uwagi |
|---|---|---|
vibe_spawn |
brief, label, tier? |
Zwraca natychmiast; worker działa dalej |
vibe_send |
worker_id, message |
Dopisuje do zlecenia i uruchamia ponownie |
vibe_wait |
worker_id, timeout_seconds? |
Blokuje, aż worker się ukończy |
vibe_kill |
worker_id |
Zatrzymuje go |
vibe_list |
— | Poziom, status, czas i ostatni wynik |
tier to fast (praca mechaniczna o jasnej specyfikacji) albo good (projektowanie, osąd albo recenzowanie wyniku workera fast).