Przejdź do głównej zawartości

Cykl życia wysyłania agentów

Wysłanie to jedno uruchomienie jednego agenta, w jednej rozmowie, na jednym adapterze. Wszystko, co się z nim wiąże, dzieje się na cc_server: klient wysyła wiadomość, a potem obserwuje, jak napływają zdarzenia. Żaden klient nie ma własnej ścieżki wysyłania.

Agenci są budzeni z sześciu powodów, które uruchomienie niesie jako swój kontekst wybudzenia, dzięki czemu agent wie, dlaczego został obudzony:

Powód wybudzenia Wyzwalacz
userMessage Ktoś wysłał wiadomość w przestrzeni lub wspomniał agenta
assignment Zgłoszenie zostało przypisane do agenta
pipelineStep Krok potoku je wysłał
childCompleted Zgłoszenie podrzędne zostało ukończone
followUp Zaplanowane przypomnienie o kontynuacji
recovery Ścieżka odzyskiwania wysłała ponownie po awarii

Kontekst wybudzenia niesie identyfikatory związane z powodem — zgłoszenie, przestrzeń, wiadomość, uruchomienie potoku — i są one wstrzykiwane do środowiska i promptu agenta.

Prompt jest budowany warstwami, z których każda jest oznaczoną sekcją:

  • Tożsamość — własny identyfikator agenta, jego nazwa i identyfikator obszaru roboczego, wraz z wyraźnym poleceniem przekazania tych dokładnych UUID-ów narzędziom działającym w zakresie obszaru roboczego. Obszar roboczy jest nierozerwalnie związany z agentem, więc jest obecny zawsze.
  • Katalog narzędzi i protokoły zasobów, a następnie układ obszaru roboczego.
  • Nadpisanie promptu systemowego, jeśli agent je ma, a następnie persona (parametryzowana rolą) i brief zespołu.
  • Skille — nazwy przypisane do agenta.
  • Kontrakt wykonania i procedura dla bieżącego trybu.
  • Kontekst wybudzenia i kontekst wzmianki: kto wezwał agenta i skład wokół niego.
  • Blok trybu — generowany z profilu możliwości trybu oraz jego zmaterializowanej listy narzędzi, dzięki czemu prompt nigdy nie wymieni narzędzia, którego uruchomienie w rzeczywistości nie ma.
  • Kontekst pamięci — fakty pobrane na potrzeby zadania.
  • Kontekst rozmowy — niedawna historia przestrzeni, ograniczona do 50 000 znaków dosłownego okna niezależnie od skonfigurowanego rozmiaru kontekstu agenta. Starsza historia nie jest odcinana: agent pobiera ją na żądanie za pomocą get_messages, a starsze wiadomości istotne semantycznie wciąż się pojawiają.

Polecenia są obsługiwane w dwóch miejscach. /todo i /compact są przechwytywane w polu tworzenia wiadomości i celowo nigdy nie są zapisywane jako wiadomości ani wysyłane do agenta — zapisanie /compact przesunęłoby punkt kompakcji o turę wstecz i zanieczyściło transkrypt. /plan jest obsługiwane w obu: pole tworzenia wiadomości przełącza tryb przestrzeni, co sprawia, że powierzchnia narzędzi, preset guardrailów i prompt są spójne w tej turze i w każdej następnej. /goal, /loop i /skill:<name> są obsługiwane wewnątrz samego uruchomienia i tylko we wbudowanym harnessie — /goal i /loop rozpoczynają autonomiczną pracę z budżetem kosztów, a nazwa z prefiksem skill: jest wyszukiwana jako skill, którego treść SKILL.md staje się dyrektywą tury. To właśnie przestrzeń nazw odróżnia oba słowniki: rozwiązywanie gołej nazwy względem skilli sprawiało, że skill o nazwie plan lub compact był na stałe przesłaniany przez polecenie wbudowane. Goła nazwa niebędąca poleceniem wbudowanym nadal się rozwiązuje — dla wiadomości napisanych, zanim przestrzeń nazw powstała. Nierozpoznana nazwa po prostu przechodzi dalej jako zwykły tekst.

Zanim cokolwiek zostanie uruchomione, rozmowa otrzymuje własny katalog główny roboczy, a pod nim odizolowane drzewo robocze z kopiowaniem przy zapisie dla każdego repozytorium. Domyślnie obejmuje to każde repozytorium powiązane z obszarem roboczym; przestrzeń PR — albo przestrzeń utworzona z jawnym wyborem — przygotowuje tylko repozytoria z listy dozwolonych, a rozmowa recenzująca PR przypina swoje jedyne repozytorium do referencji head pull requesta, podczas gdy pozostałe pozostają na swojej domyślnej gałęzi. Kopia źródłowa nigdy nie jest modyfikowana, a cały katalog rozmowy jest odzyskiwany, gdy przestrzeń zostanie usunięta.

Kopiowanie przy zapisie to jedyna implementacja wszędzie tam, gdzie dostarczany jest rift, oparta na dołączonym module natywnym. System plików, który nie potrafi tworzyć reflinków — albo katalog danych na innym wolumenie niż repozytorium — powoduje niepowodzenie przygotowania, a nie przejście na zapas. git worktree to backend w systemie Windows, gdzie nie ma backendu kopiowania przy zapisie do zbudowania, i nie jest to ciche degradowanie na innych hostach. Brakujący rift na platformie, która go dostarcza, oznacza zepsutą instalację — serwer odmawia uruchomienia, zamiast po cichu przechodzić na zapas, bo ciche przejście na zapas ukrywa usterkę za wolniejszą ścieżką na zawsze.

Przed startem jakiegokolwiek procesu dla każdego uruchomienia ustalane są dwie tożsamości.

Autorstwo w Gitcie. Commity tworzone przez agenta mają autora podanego jako agent — <Name> (agent) <agentId@agents.control-center.local> zarówno w GIT_AUTHOR_*, jak i GIT_COMMITTER_* — nigdy nie podszywając się pod człowieka. Część lokalna to UUID agenta, a nie slug jego nazwy. Osoba zlecająca pracę jest uwzględniana w stopce Co-Authored-By:, przekazywanej w środowisku i wskazanej w promptcie systemowym. Jawnie ustawiona przez wywołującego tożsamość zawsze wygrywa z obiema.

Tożsamość na hoście kodu. Dane uwierzytelniające GitHub dla uruchomienia pochodzą wyłącznie od brokera — token instalacji App o zakresie repozytorium albo jego zapasowy PAT ze środowiska — nigdy z własnego, zapisanego tokenu zlecającego członka. actingUserId ogranicza zapasowy PAT, żeby członek, który nie jest właścicielem serwera, nie dziedziczył jego zasięgu; nie nakłada osobistego tokenu na środowisko agenta.

Dane uwierzytelniające dostawcy modeli są ustalane w stałej kolejności i ta kolejność ma znaczenie:

  1. nadpisanie w środowisku dla danego adaptera,
  2. środowisko wywołującego,
  3. magazyn danych uwierzytelniających serwera (odświeżający token OAuth, jeśli zbliża się jego wygaśnięcie),
  4. środowisko procesu.

Ponieważ nadpisanie dla danego adaptera jest pierwsze, po cichu wygrywa z kontem dostawcy podłączonym w aplikacji. Jeśli uruchomienie rozlicza się na niewłaściwym koncie, to nadpisanie jest pierwszym miejscem, w którym warto zajrzeć. Dane uwierzytelniające dostawców są globalne dla hosta — współdzielone przez wszystkie obszary robocze w instalacji.

Token GitHub uruchomienia pochodzi od brokera danych uwierzytelniających: to token tylko do odczytu o zakresie repozytorium worktree. Push przechodzi przez bramę uruchomień agentów, która przed przekazaniem go dalej pyta regułę Push do zdalnego repozytorium, a żaden klucz systemu zgłoszeń nie jest wstrzykiwany. Zobacz Sandbox i bezpieczeństwo.

Uruchomienie startuje z drzewem roboczym jako swoim katalogiem roboczym i — w przypadku Claude Code — z wygenerowaną konfiguracją MCP, aby agent mógł dotrzeć do powierzchni narzędzi Control Center. ACP i bash harnessu otrzymują oczyszczone środowisko; Claude Code przez NoSandboxAdapter dziedziczy środowisko hosta.

Uruchomienie strumieniuje z powrotem typowaną sekwencję zdarzeń, którą procesor strumienia zapisuje jako delty wiadomości, składa w segmenty transkryptu i zamienia na zdarzenia komunikacyjne:

Zdarzenie Co niesie
thinking Dane wyjściowe rozumowania, renderowane na miejscu
text Widoczne dane wyjściowe
toolCall Wywołanie narzędzia wraz z jego identyfikatorem i ustrukturyzowanymi argumentami
toolResult Pasujący wynik, oznaczony, gdy zakończył się błędem lub jest częścią strumienia
usage Liczba tokenów i koszt w oknie pomiarowym
error Błąd wraz z ustrukturyzowanym kodem adaptera, gdy go zgłosił
sandboxViolation System operacyjny odrzucił wywołanie systemowe. Emitowane wyłącznie tam, gdzie sandbox faktycznie otacza proces — zobacz notatkę powyżej
debug Diagnostyka czasu działania (znaczniki startu, decyzje guardrailów, przypomnienia o kontrakcie)
done Uruchomienie się zakończyło

Celowo nigdzie nie ma limitu tur. Twardy limit iteracji zabija uzasadnioną długą pracę (migracje, porządkowanie po fan-out) i nie wyłapuje niczego, czego wcześniej nie wyłapią niżej opisane ograniczenia. Uruchomienie kończy się, gdy:

  • model sam się zatrzyma;
  • człowiek go zatrzyma albo przejmie rozmowę (co wstrzymuje wbudowany harness na następnej czystej granicy tury — uruchomienie Claude Code, które nie ma bezpiecznej granicy, zostaje zamiast tego zatrzymane);
  • zadziała watchdog ciszy. Brak danych wyjściowych przez próg czasu i sesja jest kończona niepowodzeniem silentRun. Domyślnie 15 minut, w trybach z przewagą odczytu (przegląd i plan) spada do 10; agent może go nadpisać w zakresie od 1 do 240 minut. Watchdog jest uzbrajany, gdy proces potomny zgłosi swój PID, więc obejmuje CLI Claude Code — nie wbudowany harness, który niczego nie uruchamia;
  • zadziała limit kosztów — ale tylko dla poleceń autonomicznych.

Zabezpieczenie przed pętlą zagłady nie kończy uruchomienia: trzy identyczne wywołania narzędzi pod rząd i pętla kieruje agenta ku zmianie podejścia.

Podsumowując: zwykła interaktywna tura we wbudowanym harnessie nie ma limitu tur, limitu kosztów ani watchdoga ciszy. Kończy się, gdy model się zatrzyma albo gdy zatrzyma go człowiek. To świadomy kompromis — alternatywy zabijają uzasadnioną długą pracę — ale oznacza to, że interaktywne uruchomienie bez nadzoru ogranicza wyłącznie osąd samego modelu.

W trakcie uruchomienia wiadomość wysłana do działającego agenta trafia do kolejki jako sterowanie i jest opróżniana na następnej granicy tury, więc możesz nakierować uruchomienie bez zabijania go. Sterowanie, wstrzymywanie, podagenci i kontrakt wykonania to funkcje wbudowanego harnessu; Claude Code nie ma żadnej z nich.

Każde wysłanie zapisuje AgentRunLog: czas rozpoczęcia i zakończenia, podsumowanie, liczbę tokenów i szacowany koszt (wraz z kosztem zsumowanym z podagentów), adapter i model, identyfikator procesu i ścieżkę logu, rozmowę oraz powiązane zgłoszenie lub uruchomienie potoku, a do tego dwa pola klasyfikacji, które niosą większość prawdy.

  • Status jest zgrubny: pending, running, completed, error.
  • Żywotność to dokładniejszy odczyt: alive, productive, completed, blocked, empty, looping, failed, stalled, dead.
  • Rodzina błędów sensownie grupuje niepowodzenia: transientUpstream, sandboxInfrastructure, budgetExceeded, processLost, silentRun, unknown.

Zamknięcie uruchomienia publikuje AgentRunCompleted i wiele od niego zależy: sumowanie kosztów potoku, wznowienie kroku potoku, który czekał na to uruchomienie, ukończenie powiązanego zgłoszenia, zmapowanie orkiestracji na stan końcowy, decyzja nadzorcy celu o kontynuacji lub zatrzymaniu, rola kontrolera i ocena budżetu po uruchomieniu. Lista obecności pojawia się osobno, obserwując ostatnie dzienniki uruchomień, a nie samo zdarzenie. Powiadomienia „agent ukończył pracę” nie ma na tej liście: zdarzenie pojawia się, gdy kończy się strumień procesu, zanim odpowiedź zostanie zapisana, więc powiadomieniem jest MessageReceived danej tury, publikowane po utrwaleniu wiadomości.

Egzekwowanie budżetu jest reakcją, a nie bramką. Gdy uruchomienie się zakończy, ewaluator porównuje wydatki agenta od początku miesiąca z jego obowiązującym pułapem (powiązana polityka budżetowa, jeśli istnieje, w przeciwnym razie własna miesięczna kwota agenta; zero oznacza brak limitu). Przekroczenie miękkiego progu zapisuje incydent ostrzegawczy; wyczerpanie budżetu zapisuje incydent krytyczny i przełącza status cyklu życia agenta na paused na schemacie organizacyjnym. Wysyłanie nadal przyjmuje pracę od tego agenta. Wyzwalacz potoku BudgetThresholdCrossed może rozpocząć dalszą pracę na podstawie tego samego zdarzenia.

Każdy dziennik uruchomienia może nieść rodowód ponowień — identyfikator uruchomienia nadrzędnego, licznik prób i podsumowanie kontynuacji. Drzewo uruchomień rozmowy pokazuje numer próby, gdy jest niezerowy. „Spróbuj ponownie” z czatu to nowe wysłanie z nowym dziennikiem uruchomienia.