Kontekst narzędzi i cache promptów
Dwie rzeczy są prawdą o każdym żądaniu wysyłanym przez wbudowany harness: definicje narzędzi to największy stały koszt, a niemal żadne z nich nie zostanie użyte. Ta strona wyjaśnia, co Control Center z tym robi i dlaczego odpowiedzią nie jest po prostu „wysyłanie mniejszej liczby narzędzi”.
Problemem jest uwaga, nie bajty
Dział zatytułowany „Problemem jest uwaga, nie bajty”Control Center rejestruje około 126 narzędzi. Wysłane w całości, ich definicje kosztują mniej więcej 23 000 tokenów przy każdym żądaniu — koszt, którego żadna kompresja nie tknie, bo definicje narzędzi podróżują w innej części żądania niż rozmowa.
Rachunek za tokeny to najbardziej oczywisty zarzut, a przy cache promptów jest też tym mniejszym. Prawdziwym kosztem jest trafność wyboru. Publikowane ewaluacje wywoływania narzędzi zgadzają się, że modele niezawodnie wybierają właściwe narzędzie do około 30–50 narzędzi w kontekście, a powyżej tej liczby radzą sobie coraz gorzej. Wskazywana przyczyna to nie liczba tokenów, lecz semantyczne nakładanie się: gdy katalog zawiera kilka narzędzi o podobnie brzmiących opisach, model wybiera między podobnymi opisami, zamiast przypominać sobie o jakiejś możliwości.
Przy 126 narzędziach agent jest znacznie powyżej tego przedziału w każdej pojedynczej turze — także w tych wielu turach, w których potrzebował tylko odczytać plik.
Dwuwarstwowa powierzchnia
Dział zatytułowany „Dwuwarstwowa powierzchnia”Uruchomienie widzi więc dwie rzeczy:
- rezydentny zestaw — około dwudziestu kilku narzędzi, wysyłanych z pełnymi schematami przy każdym żądaniu;
- indeks nazw całej reszty, pogrupowany pod nagłówkami takimi jak „Tickets and projects” czy „Memory and knowledge”, kosztujący kilkaset tokenów za cały katalog.
Zmierzone na obecnym katalogu, zmniejsza to blok narzędzi z ~23,1 tys. tokenów do ~5,0 tys., czyli o około 78%, i umieszcza stale widoczny zestaw w przedziale, w którym wybór jest niezawodny.
Zestaw rezydentny to narzędzia, których uruchomienie używa w większości uruchomień: narzędzia plikowe i powłoki (read, write, edit, search, bash, …), narzędzia odkrywania, lista zadań, wyszukiwanie w pamięci oraz czasownik, który bieżący tryb musi wywołać, aby dostarczyć swój wynik. Własny czasownik wyjściowy trybu jest zawsze rezydentny — uruchomienie nigdy nie może szukać tego jednego wywołania, które tworzy jego rezultat.
Odroczenie nie oznacza niedostępności
Dział zatytułowany „Odroczenie nie oznacza niedostępności”To właśnie ten element sprawia, że projekt jest bezpieczny, a nie tylko tani. Odroczone narzędzie można wywołać już od pierwszej tury. Wstrzymywany jest wyłącznie jego schemat.
Agent widzi nazwę w swoim prompcie. Jeśli wywoła tę nazwę bezpośrednio, harness wczytuje schemat i uruchamia narzędzie w tym samym kroku — bez błędu, bez dodatkowej rundy. Model nie musi wiedzieć, że narzędzie było kiedykolwiek „wyładowane”.
Gdy agent zna zadanie, ale nie zna nazwy, search_tools przyjmuje opis w naturalnym języku („przypisz komuś zgłoszenie”), szereguje całą powierzchnię uruchomienia i zwraca dopasowania z już wczytanymi schematami, dzięki czemu już następna tura może jedno z nich wywołać. Jeśli wyszukiwanie nic nie znajdzie, mówi o tym wprost i proponuje inne sformułowanie albo szersze wyszukiwanie — celowo, bo agent, który odczyta puste wyszukiwanie jako „ta możliwość nie istnieje”, wymyśli zamiennik, zamiast szukać dalej.
search_tools istnieje tylko we wbudowanym harnessie. Zewnętrzni klienci MCP mają zamiast tego search_tool_bm25, który szereguje ten sam indeks, ale jedynie opisuje dopasowania — ci klienci otrzymali już wszystkie schematy z tools/list, więc nie ma czego wczytywać.
Czego odroczenie nigdy nie robi
Dział zatytułowany „Czego odroczenie nigdy nie robi”Odroczenie stosuje się po filtrze narzędzi trybu, nigdy zamiast niego. Ukrywa schemat; nie może ujawnić narzędzia, którego tryb odmówił. Aktywowane narzędzie nadal przechodzi przez prośbę o zatwierdzenie i guardraile akcji dokładnie tak samo jak narzędzie rezydentne, a narzędzie nie może wczytać nazwy, której od początku nie było na powierzchni uruchomienia.
Powierzchnia MCP widziana przez zewnętrznych klientów nie jest tym dotknięta. tools/list nadal zwraca pełny katalog. Wcześniejsza próba jej okrojenia całkowicie popsuła agentów: klienci MCP weryfikują nazwy narzędzi względem własnej zbuforowanej listy i odrzucają wszystko, czego na niej nie ma, nawet nie pytając serwera — narzędzie „ukryte, ale wywoływalne” było więc po prostu nieosiągalne. Odroczenie żyje w harnessie, gdzie wczytanie narzędzia w trakcie uruchomienia jest czymś, co harness faktycznie potrafi zrobić.
Jak to wyłączyć
Dział zatytułowany „Jak to wyłączyć”--tool-deferral=off (albo CC_SERVER_TOOL_DEFERRAL=off) przywraca rezydentność każdego dopuszczonego narzędzia, generując dokładnie te żądania, które serwer wysyłał, zanim odroczenie powstało. Zobacz dokumentację referencyjną CLI cc_server.
Cache promptów
Dział zatytułowany „Cache promptów”Obciążenie agentów jest asymetryczne: wysyłają ogromne prompty i otrzymują krótkie odpowiedzi, tura po turze, za każdym razem z tym samym prefiksem. Dostawcy buforują ten prefiks, a odczyt z cache kosztuje około jednej dziesiątej tego, co świeży odczyt. Trafność cache jest więc podstawową właściwością harnessu, a nie optymalizacją — a w Anthropic dodatkowo zwiększa przepustowość, bo zbuforowane tokeny nie liczą się do limitu wejścia na minutę.
Buforowanie działa na podstawie dokładnego dopasowania prefiksu, z czego wynika jedna nadrzędna zasada.
Nigdy nie przepisuj tego, co już zostało wysłane
Dział zatytułowany „Nigdy nie przepisuj tego, co już zostało wysłane”Każdy zmieniony bajt unieważnia cache od tego miejsca wzwyż. Dlatego harness wyłącznie dopisuje: nowe wiadomości na końcu, a nowo aktywowane schematy narzędzi po zbuforowanym bloku narzędzi, zamiast włączać je do niego. Ta kolejność jest powodem, dla którego aktywacja jest tania — zbuforowany prefiks pozostaje identyczny, a uruchomienie płaci tylko za właśnie wczytane schematy.
Pętla odcina też nieaktualne wyniki narzędzi ze starszych tur, aby odzyskać kontekst. Czeka, aż do odzyskania będzie wystarczająco dużo, by przepisanie się opłacało, więc odcięcie jest rzadkim głębokim przepisaniem, a nie ciągłym nietrafieniem cache.
Gdzie trafiają znaczniki cache
Dział zatytułowany „Gdzie trafiają znaczniki cache”Dostawca pozwala na ograniczoną liczbę znaczników cache, a Control Center wydaje je świadomie:
| Znacznik | Co obejmuje | Czas życia |
|---|---|---|
| Ostatnie narzędzie rezydentne | Blok narzędzi | 1 godzina |
| Ostatni blok systemowy | Narzędzia + prompt systemowy | 1 godzina |
| Koniec poprzedniej tury | Historia do ostatniego żądania | 5 min |
| Koniec bieżącej tury | Pełna historia | 5 min |
Dwa ostatnie tworzą ruchomą parę, a powód jej istnienia jest subtelny: wyszukiwanie w cache przeszukuje wstecz ograniczoną liczbę bloków w poszukiwaniu czegoś, co zapisało wcześniejsze żądanie. Pojedyncza tura uruchamiająca wiele narzędzi równolegle może wygenerować więcej bloków niż to okno — wtedy jeden znacznik na końcu po cichu chybia, a żądanie płaci pełną cenę, choć nic w odpowiedzi o tym nie mówi. Oznaczenie dokładnego miejsca, w którym zatrzymało się poprzednie żądanie, czyni trafienie strukturalnym, a nie wyścigiem.
Prefiks narzędzi i systemu dostaje długi czas życia, bo jest stały przez całe uruchomienie, dzielą go wszystkie uruchomienia i podagenci o tym samym kształcie, a zegar startuje, gdy żądanie się zaczyna — tura, która strumieniuje przez kilka minut, zdążyła już wykorzystać większość krótkiego okna, zanim powstanie następne żądanie.
Podagenci dzielą jeden prefiks
Dział zatytułowany „Podagenci dzielą jeden prefiks”Podagenci tego samego typu tworzą identyczne co do bajtu prefiksy promptów, więc powinni odczytywać jeden wpis cache, zamiast każdy zapisywać własny. Wpis staje się jednak czytelny dopiero wtedy, gdy żądanie, które go zapisało, zacznie odpowiadać — dlatego przy fan-outcie uruchomionym za jednym razem każde dziecko płaci wyższą cenę za prefiks, który wszystkie dzielą.
Harness pozwala wystartować pierwszemu dziecku danego kształtu, a potem zwalnia jego rodzeństwo, gdy tylko zacznie ono strumieniować. Oczekiwanie jest ograniczone: wolne pierwsze dziecko kosztuje trafienie cache, nigdy sam fan-out. Z tego samego powodu każdy podagent dostaje ten sam zestaw narzędzi rezydentnych niezależnie od swojego profilu — różnicowanie go według profilu rozdrobniby wspólny prefiks bez żadnej korzyści, skoro profil już zdecydował, co dziecko może wywoływać.
Jak to obserwować
Dział zatytułowany „Jak to obserwować”Obie połowy są obserwowalne, a nie zakładane:
- Eksplorator kontekstu przy rozmowie raportuje narzędzia rezydentne, odroczony indeks oraz to, ile kosztowałby każdy wstrzymany schemat; powstaje na tej samej ścieżce kodu, której używa rzeczywiste uruchomienie.
- Każde uruchomienie zapisuje, które odroczone narzędzia wczytało i co to wyzwoliło, dzięki czemu wyszukiwanie, które nic nie znajduje, jest widoczne jako nietrafienie wyszukiwania, a nie znika w agencie po cichu robiącym coś pokrewnego.
- Obserwowalność podaje Trafność cache jako odczyty z cache w stosunku do wszystkich przetworzonych tokenów promptu, wraz z zapisami do cache — uruchomienie, które ciągle odbudowuje swój prefiks, wypada nisko, zamiast wypadać jak takie, które cache nigdy nie potrzebowało.