Obserwowalność agentów: hooki, Alloy i Grafana
> Podłączyliśmy Claude Code i Codex do jednego stosu Grafana za pomocą OpenTelemetry i Alloy, a następnie użyliśmy śladów (traces) i logów, by znajdować i naprawiać problemy z zachowaniem agentów u źródła.
Systemy agentowe zawodzą na dziwne sposoby.
Czasem problemem jest model. Czasem narzędzie. Czasem Twój serwer MCP działa bez zarzutu, ale agent wybrał niewłaściwego specjalistę, albo spędził połowę sesji na pracy powłokowej, której się nie spodziewałeś, albo po cichu spalił budżet w pętli, która z zewnątrz wyglądała na produktywną.
Jeśli nie widzisz tej różnicy, tak naprawdę nie obsługujesz systemu agentowego. Zgadujesz.
Zbudowaliśmy więc stos obserwowalności dla naszego własnego przepływu pracy: Claude Code, Codex, zdarzenia hooków Claude, zdarzenia notify Codex, natywny OpenTelemetry, Grafana Alloy i Grafana Cloud po drugiej stronie.
Ciekawa część to nie „zrobiliśmy dashboard”. Ciekawa część polega na tym, że musieliśmy podzielić telemetrię na dwa różne strumienie, ponieważ żaden pojedynczy feed nie dawał nam pełnego obrazu.
Problem: telemetria agentów jest rozdrobniona
Nowoczesne agenty kodujące już emitują część telemetrii. To pomaga, ale to nie wystarcza.
Natywny OTEL dobrze odpowiada na pytania w stylu:
- Ile żądań wykonaliśmy?
- Ile kosztowała dana sesja?
- Gdzie są spany i ślady (traces)?
- Czy nastąpił skok opóźnienia?
Znacznie gorzej radzi sobie z pytaniami takimi jak:
- Na którym serwerze MCP agent się opierał?
- Czy ta awaria dotyczyła
Bash, wbudowanego narzędzia plikowego, czy wywołania MCP? - Który skill faktycznie się aktywował?
- Jaki typ subagenta został wysłany do zadania?
- Czy sesja wykonywała użyteczną pracę, czy tylko się miotała?
Ta druga klasa pytań leży bliżej hooków niż śladów.
Ale odwrotność też jest prawdą: część najważniejszych pytań o wydajność leży bliżej śladów niż hooków.
Jeśli chcesz wiedzieć, gdzie faktycznie kumulowało się opóźnienie, które spany były wolne, albo czy sesja spaliła czas na wywołaniach modelu czy na wykonywaniu narzędzi, potrzebujesz danych ze śladów tak samo jak zdarzeń semantycznych.
Architektura, na której skończyliśmy
Uruchamiamy dwie ścieżki telemetrii równolegle.
Claude Code
native OTEL -> Alloy -> Grafana Cloud
hooks -> send_event.py -> Grafana Cloud Loki
Codex
native OTEL -> Alloy -> Grafana Cloud
notify hook -> codex_notify.py -> shared Loki schema
Ten podział jest celowy.
Jest też asymetryczny. Claude Code daje nam znacznie bogatszą powierzchnię hooków cyklu życia. Codex daje nam natywny OTEL plus powierzchnię notify, więc normalizujemy cieńsze zdarzenia zakończenia tury do tego samego schematu logów, zamiast udawać, że oba środowiska uruchomieniowe udostępniają te same kontrolki.
Natywny OTEL daje nam bazowy strumień: logi i ślady z samego środowiska uruchomieniowego, plus metryki tam, gdzie środowisko faktycznie je emituje.
Zdarzenia hooków i notify dają nam warstwę semantyczną: rzeczy takie jak PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, SubagentStop, SkillActivated oraz sklasyfikowane metadane, na których nam naprawdę zależy przy debugowaniu zachowania agenta. Claude Code dostarcza tu bogatszy strumień zdarzeń. Codex dostarcza cieńszy, ale wciąż użyteczny znormalizowany strumień.
Dlaczego hooki w ogóle istnieją
Nasz potok hooków wzbogaca zdarzenia, zanim trafią do Loki.
Zamiast po prostu powiedzieć „uruchomiło się narzędzie”, klasyfikujemy zdarzenie do pól takich jak:
tool_type: builtin, mcp, skill, agent, bashmcp_server: który backend MCP obsłużył wywołaniebash_cli: rodzina poleceń powłokisubagent_type: jaki rodzaj specjalisty został wysłany do zadaniaagent_tool: czy źródłem był Claude Code, czy Codex
To oznacza, że możemy zadawać pytania, które mają znaczenie operacyjne:
{service_name="claude-code-hooks"} | agent_tool="codex-cli"
{service_name="claude-code-hooks"} | tool_type="mcp"
{service_name="claude-code-hooks"} | json | bash_cli="git"
To nie są pola dla ozdoby. To różnica między „agent wydawał się wolny” a „agent spędził ostatnie dziesięć minut na intensywnych operacjach git w powłoce z wysokim wskaźnikiem niepowodzeń narzędzi”.
Jeden szczegół implementacyjny, który wygląda dziwniej, niż jest: współdzielony strumień Loki wciąż używa service_name="claude-code-hooks" jako etykiety, nawet gdy zdarzenie pochodzi z Codex. Prawdziwy podział między środowiskami uruchomieniowymi następuje na agent_tool.
Dlaczego Alloy siedzi pośrodku
Grafana Alloy w tym układzie to nie tylko przekaźnik. To granica polityki.
Kierujemy natywny strumień OTEL z Claude Code i Codex do lokalnego proxy Alloy na localhost:4318, a następnie pozwalamy Alloy oczyścić ładunek, zanim przekaże go dalej do Grafana Cloud.
To ma znaczenie, ponieważ surowa telemetria agentów jest pełna pól o wysokiej kardynalności, które są przydatne do analizy, ale fatalne jako indeksowane etykiety:
session_idprompt_id- liczba tokenów
- czasy trwania
- bloby parametrów narzędzi
Jeśli zaindeksujesz wszystko, dostajesz eksplozję etykiet i zepsuty dzień.
Więc Alloy robi dla nas trzy rzeczy:
- Utrzymuje bardzo mały zestaw zaindeksowanych etykiet o niskiej kardynalności.
- Przenosi zaszumione, ale użyteczne pola do ustrukturyzowanych metadanych.
- Całkowicie odrzuca czysty szum.
Ważna idea jest prosta: obserwuj więcej, indeksuj mniej.
Dlaczego strumień hooków omija Alloy
Strumień hooków jest już ukształtowany pod Loki.
Zanim send_event.py wypchnie zdarzenie, już zdecydowaliśmy, które pola zasługują na traktowanie jako etykiety, a które należą do ustrukturyzowanego ciała JSON. Ten strumień trafia prosto do bramki OTLP Grafana Cloud, zamiast przechodzić kolejny raz przez Alloy.
System ma więc jasny podział pracy:
- Alloy okiełznuje surowy natywny strumień OTEL.
- Wzbogacanie hooków czyni zdarzenia semantyczne przeszukiwalnymi.
Dzięki temu architektura pozostaje prostsza niż próba przepchnięcia wszystkiego jedną ścieżką.
Co faktycznie pokazuje dashboard
Poniższy zrzut ekranu pochodzi z jednego z dashboardów obserwowalności stojących za naszym przepływem pracy agentów. To nie benchmark, a liczby to tylko wycinek z danego momentu. Chodzi o kształt danych: kanał aktywności, wywołania narzędzi, awarie, prompty oraz podziały według agenta, narzędzi wbudowanych, użycia MCP, poleceń powłoki i skilli.
Przydatne jest to, że ten dashboard żyje na tym samym stosie Grafana co reszta telemetrii agentów. Możemy filtrować według agenta źródłowego i rodziny narzędzi oraz patrzeć na różne środowiska uruchomieniowe bez wymyślania osobnej historii obserwowalności dla każdego systemu.
Dlaczego ślady mają większe znaczenie, niż się wydaje na pierwszy rzut oka
Logi mówią nam, jaka kategoria pracy się wydarzyła. Ślady mówią nam, jak ta praca rozwijała się w czasie.
To rozróżnienie ma znaczenie w systemach agentowych, ponieważ „wolno” jest zbyt tępym określeniem, by było użyteczne.
Ślad może nam powiedzieć, czy ból pochodził z:
- opóźnienia modelu
- czasu wykonania narzędzia
- powtarzanych ponowień
- jednej szczególnie kosztownej interakcji MCP
- długiego ogona drobnych operacji, które osobno wyglądały niegroźnie
W praktyce używamy razem strumienia hooków i śladów Tempo.
- Logi hooków odpowiadają: co się wydarzyło?
- Ślady odpowiadają: gdzie poszedł czas?
To połączenie zmienia obserwowalność z dashboardu w wyjaśnienie.
Gdzie pasuje Codex
Codex jest częścią tego samego stosu, ale nie jest identyczny z Claude Code.
Dla Codex podłączamy dwa elementy:
- Natywny OTEL z Codex do Alloy
- Webhook notify do
codex_notify.py, który mapuje zakończenia tur na ten sam schemat Loki, którego używamy dla zdarzeń hooków
To daje nam ujednolicony filtr taki jak agent_tool="codex-cli" w tym samym strumieniu logów.
Uczciwe zastrzeżenie: ładunek notify Codex jest obecnie cieńszy niż ładunek hooków Claude Code, ponieważ nie jest to ten sam rodzaj powierzchni integracji. W naszej konfiguracji dziś zakończenia tur Codex można znormalizować do współdzielonego schematu, ale bogata ekstrakcja narzędzie-po-narzędziu wciąż lepiej działa w natywnym strumieniu OTEL niż w moście notify.
To nie jest powód, by unikać tego wpisu. To właśnie jego sens. Prawdziwe systemy obserwowalności buduje się z niedoskonałych sygnałów.
Grafana przez MCP zmienia grę
Większa zmiana polega na tym, że Grafana to nie tylko miejsce, które ludzie odwiedzają w przeglądarce.
W tym repozytorium udostępniamy też Grafana przez MCP. To oznacza, że agent może odpytywać Loki, Prometheus i Tempo bezpośrednio, zamiast czekać, aż człowiek najpierw ręcznie sprawdzi dashboardy.
To zamienia obserwowalność w aktywny wkład w przepływ pracy.
Agent może zapytać:
- Które rodziny narzędzi zawodziły najczęściej w ostatniej godzinie?
- Który serwer MCP zdominował sesję?
- Czy niedawne zmiany zmniejszyły liczbę niepowodzeń narzędzi, czy tylko przeniosły pracę na ścieżki bardziej powłokowe z tymi samymi błędami?
- Które ślady pokazują najwyższe opóźnienie lub powtarzane ponowienia?
Gdy to masz, jesteś bardzo blisko pętli samodoskonalenia.
Od dashboardu do pętli sprzężenia zwrotnego
To jest część, którą uważamy za najciekawszą.
Gdy stos obserwowalności staje się przeszukiwalny z poziomu warstwy agenta, telemetria przestaje być bierną powierzchnią raportowania i staje się sygnałem sterującym.
Pętla wygląda tak:
- Aktywność agenta emituje ślady, metryki i wzbogacone logi hooków.
- Grafana przechowuje dowody w Loki, Tempo i Prometheus, tam gdzie istnieją metryki.
- Agenci odpytują te dowody przez Grafana MCP.
- System identyfikuje zły dobór narzędzi, kruche skille, słabe trasowanie lub przepływy pracy zbyt zależne od powłoki, które wciąż generują błędy, których można było uniknąć.
- Agenci lub operatorzy dostosowują prompty, konfiguracje agentów, opisy skilli, reguły trasowania lub dostęp do narzędzi.
- Kolejna sesja generuje nowy kształt telemetrii, a cykl się powtarza.
Tak przechodzi się od „ciekawego dashboardu” do „mierzalnego systemu poprawy”.
Celem nie jest maksymalizacja jednej kategorii narzędzi. Celem jest znalezienie właściwej mieszanki CLI, narzędzi wbudowanych, wywołań MCP i skilli dla pracy, która faktycznie jest wykonywana.
Na co to pozwala nam odpowiedzieć
Gdy oba środowiska uruchomieniowe trafiają do tego samego stosu Grafana, możemy znacznie szybciej odpowiadać na pytania operacyjne:
- Czy awarie skupiają się w jednej rodzinie narzędzi?
- Czy przepływy pracy zbyt zależne od powłoki tworzą błędy, których można uniknąć tam, gdzie powinno istnieć narzędzie wyższego poziomu?
- Które serwery MCP dźwigają większość obciążenia?
- Czy płacimy za aktywność agenta, która nie generuje znaczącego postępu?
- Czy sesja jest niezdrowa z powodu modelu, narzędzi, czy warstwy orkiestracji?
Jest to szczególnie przydatne w przepływach pracy z wieloma agentami, gdzie „agent był zajęty” nie mówi prawie nic.
Jeśli jeden specjalista jest wciąż wysyłany do zadań i generuje wysoki wskaźnik niepowodzeń, to problem trasowania lub kształtowania promptu.
Jeśli jeden serwer MCP dominuje wszystkie wywołania, może to być dobra architektura albo sygnał, że reszta jest martwym balastem.
Jeśli niepowodzenia narzędzi rosną, a koszt pozostaje wysoki, masz problem operacyjny, nie jakościowy.
Jeśli praca powłokowa wciąż zawodzi w przewidywalny, możliwy do uniknięcia sposób tam, gdzie powinno istnieć narzędzie wyższego poziomu, to sygnał produktowy.
Jeśli jeden skill aktywuje się bez przerwy, ale nie poprawia wyników, to sygnał promptu lub trasowania.
Prawdziwa lekcja
Głębsza lekcja jest taka, że obserwowalność agentów potrzebuje zarówno telemetrii środowiska uruchomieniowego, jak i telemetrii przepływu pracy.
Telemetria środowiska uruchomieniowego mówi Ci, co system zrobił.
Telemetria przepływu pracy mówi Ci, co agent myślał, że robi.
Potrzebujemy obu.
Jeśli zachowujesz tylko ślady i liczniki, tracisz warstwę semantyczną. Jeśli zachowujesz tylko zdarzenia hooków, tracisz opóźnienia, spany i szerszy obraz środowiska uruchomieniowego.
A jeśli zachowujesz oba, ale nigdy nie sprzęgasz ich zwrotnie z warstwą agenta, masz monitoring, nie adaptację.
To połączenie sprawia, że system jest na tyle wytłumaczalny, by nim obsługiwać, i na tyle strojalny, by go ulepszać.
Co wciąż jest niedoskonałe
Wciąż są szorstkie krawędzie.
- Nie każde zdarzenie hooka zawiera dane o czasie trwania i tokenach, jakich byśmy chcieli.
- Część najlepszych widoków czasowych wciąż pochodzi ze śladów Tempo, a nie z logów hooków.
- Codex jest dziś mniej semantycznie bogaty niż Claude Code w wzbogaconym strumieniu zdarzeń.
- Zrzut ekranu dashboardu to działająca powierzchnia operacyjna, nie dopieszczony artefakt marketingowy.
Ten ostatni punkt jest zamierzony. Wolimy pokazać prawdziwy panel przyrządów niż udawać, że systemy agentowe magicznie same się tłumaczą.
Dlaczego to ma znaczenie dla Maguyva
Maguyva polega na dawaniu agentom lepszej inteligencji kodu. Ale gdy agenty faktycznie wykonują użyteczną pracę, natychmiast pojawia się nowy wymóg: musisz widzieć, jak się zachowują.
Jakość wyszukiwania, jakość trasowania, dobór narzędzi i efektywność kontekstu — wszystko to staje się problemami do zaobserwowania.
Dlatego uważamy, że warto o tym pisać. Przyszły stos agentowy to nie tylko prompty i narzędzia. To prompty, narzędzia i warstwa instrumentacji, która mówi Ci, czy całość działa.
Jeśli budujesz poważne przepływy pracy agentowej, obserwowalność nie jest opcjonalną infrastrukturą. Jest częścią produktu.
Powiązane treści
Więcej z dziennika budowy Maguyva
Dlaczego zaktualizowaliśmy wyszukiwanie kodu do voyage-4-large_
Przenieśliśmy nasze embeddingi kodu na voyage-4-large — obecnie na szczycie publicznego rankingu RTEB dla wyszukiwania kodu. Wersja uczciwa: kompromis, na jaki idziemy, co faktycznie indeksujemy i dlaczego płacimy za embeddingi premium.
Rekurencyjne samodoskonalenie językowe: szlifowanie inteligencji kodu w ~280 językach_
Obsługujemy inteligencję kodu dla ~280 języków. Żaden człowiek nie jest w stanie tego ręcznie zweryfikować. Zbudowaliśmy więc pętlę rekurencyjnego samodoskonalenia językowego — wyrywkowa kontrola, LLM jako sędzia, naprawa jednej rzeczy, ponowna walidacja — i uruchamiamy ją z flotą izolowanych agentów, dopóki ekstrakcja nie będzie naprawdę poprawna, a nie tylko zielona.
Wielomodalne wyszukiwanie z fuzją: dobór właściwego retrievera do każdego zapytania_
Zapytanie w stylu „gdzie zdefiniowano parseConfig” potrzebuje innego wyszukiwania niż „jak działa autoryzacja”. Maguyva klasyfikuje intencję, odpowiednio waży cztery tryby wyszukiwania i łączy wyniki za pomocą ważonej Reciprocal Rank Fusion.