Observabilita agentů: hooks, Alloy a Grafana
> Zapojili jsme Claude Code a Codex do jednoho Grafana stacku pomocí OpenTelemetry a Alloy a pak jsme pomocí trace a logů dohledávali a opravovali problémy v chování agentů přímo u zdroje.
Agentní systémy selhávají podivnými způsoby.
Někdy je problém v modelu. Někdy v nástroji. Někdy je váš MCP server v pořádku, ale agent si zvolil špatného specialistu, nebo strávil polovinu session prací v shellu, kterou jste nečekali, nebo tiše propálil náklady ve smyčce, která zvenčí vypadala produktivně.
Pokud ten rozdíl nevidíte, agentní systém ve skutečnosti neprovozujete. Jen hádáte.
Postavili jsme si tedy observabilitu pro náš vlastní workflow: Claude Code, Codex, hook eventy Claude, notify eventy Codexu, nativní OpenTelemetry, Grafana Alloy a na druhé straně Grafana Cloud.
Zajímavá část není „udělali jsme dashboard“. Zajímavá je skutečnost, že jsme museli telemetrii rozdělit do dvou různých proudů, protože žádný jednotlivý feed nám nedal celý obrázek.
Problém: telemetrie agentů je roztříštěná
Moderní kódovací agenti už nějakou telemetrii vysílají. To pomáhá, ale nestačí to.
Nativní OTEL umí dobře odpovídat na otázky typu:
- Kolik požadavků jsme provedli?
- Kolik stála daná session?
- Kde jsou spany a trace?
- Vyskočila latence?
Mnohem hůř odpovídá na otázky jako:
- Na který MCP server se agent spoléhal nejvíc?
- Selhalo to v
Bash, ve vestavěném nástroji pro práci se soubory, nebo ve volání MCP? - Který skill se skutečně aktivoval?
- Jaký typ subagenta byl vyslán?
- Dělala session užitečnou práci, nebo se jen bezcílně motala?
Ta druhá skupina otázek stojí blíž hookům než trace.
Platí ale i opak: některé z nejdůležitějších výkonnostních otázek stojí blíž trace než hookům.
Pokud chcete vědět, kde se latence skutečně nakumulovala, které spany byly pomalé, nebo jestli session propálila čas ve voláních modelu, nebo v provádění nástrojů, potřebujete kromě sémantických eventů i data z trace.
Architektura, u které jsme skončili
Provozujeme dvě telemetrické cesty vedle sebe.
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
Toto rozdělení je záměrné.
Je také asymetrické. Claude Code nám dává mnohem bohatší povrch lifecycle hooků. Codex nám dává nativní OTEL plus notify rozhraní, takže tenčí eventy dokončení tahu normalizujeme do stejného schématu logů, místo abychom předstírali, že oba runtime nabízejí stejné kontrolní prvky.
Nativní OTEL nám dává základní proud: logy a trace ze samotného runtime, plus metriky tam, kde je runtime skutečně vysílá.
Hook a notify eventy nám dávají sémantickou vrstvu: věci jako PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, SubagentStop, SkillActivated a klasifikovaná metadata, na kterých nám při ladění chování agentů skutečně záleží. Claude Code sem přispívá bohatším proudem eventů. Codex přispívá tenčím, ale pořád užitečným normalizovaným proudem.
Proč hooky vůbec existují
Naše hook pipeline eventy obohacuje ještě předtím, než dorazí do Loki.
Místo pouhého „nástroj proběhl“ klasifikujeme event do polí jako:
tool_type: builtin, mcp, skill, agent, bashmcp_server: který MCP backend volání zpracovalbash_cli: rodina shellového příkazusubagent_type: jaký typ specialisty byl vyslánagent_tool: jestli zdroj byl Claude Code, nebo Codex
To znamená, že si můžeme klást otázky, na kterých provozně záleží:
{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 nejsou okrasná pole. Jsou to rozdíl mezi „agent připadal pomalý“ a „agent strávil posledních deset minut prací se shellem těžkou na git operace s vysokou mírou selhání nástrojů“.
Jeden implementační detail, který vypadá podivněji, než ve skutečnosti je: sdílený proud Loki pořád používá service_name="claude-code-hooks" jako label, i když event pochází z Codexu. Skutečné rozdělení mezi runtimy probíhá na agent_tool.
Proč je Alloy uprostřed
Grafana Alloy v tomto nastavení není jen forwarder. Je to hranice politiky.
Nativní OTEL proud z Claude Code a Codexu míříme na lokální Alloy proxy na localhost:4318 a necháme Alloy payload vyčistit, než ho přepošle do Grafana Cloud.
Na tom záleží proto, že syrová telemetrie agentů je plná polí s vysokou kardinalitou, která jsou užitečná pro analýzu, ale hrozná jako indexované labely:
session_idprompt_id- počty tokenů
- doby trvání
- blob s parametry nástrojů
Pokud indexujete všechno, dostanete explozi labelů a špatný den.
Alloy pro nás tedy dělá tři věci:
- Udržuje indexovanou jen velmi malou sadu labelů s nízkou kardinalitou.
- Přesouvá hlučná, ale užitečná pole do strukturovaných metadat.
- Úplně zahazuje čistý šum.
Ta důležitá myšlenka je jednoduchá: pozoruj víc, indexuj méně.
Proč hookový proud obchází Alloy
Hookový proud je už tvarovaný pro Loki.
V okamžiku, kdy send_event.py odešle event, jsme už rozhodli, která pole si zaslouží zacházení jako label a která patří do strukturovaného JSON těla. Tento proud jde přímo do OTLP brány Grafana Cloud, místo aby procházel ještě jednou přes Alloy.
Systém tak má jasné rozdělení práce:
- Alloy krotí syrový nativní OTEL proud.
- Obohacení hooky dělá sémantické eventy dotazovatelnými.
Díky tomu je architektura jednodušší, než kdybychom se snažili prohnat všechno jednou cestou.
Co dashboard skutečně ukazuje
Snímek obrazovky níže pochází z jednoho z observability dashboardů za naším agentním workflow. Není to benchmark a čísla jsou jen výřez v jednom okamžiku. Jde o tvar dat: activity feed, volání nástrojů, selhání, prompty a rozpady podle agenta, vestavěných nástrojů, použití MCP, shellových příkazů a skillů.
Užitečné je, že tento dashboard žije na stejném Grafana stacku jako zbytek agentní telemetrie. Můžeme filtrovat podle zdrojového agenta a rodiny nástrojů a dívat se napříč runtimy, aniž bychom si pro každý systém vymýšleli jiný příběh observability.
Proč na trace záleží víc, než se na první pohled zdá
Logy nám říkají, jaká kategorie práce proběhla. Trace nám říkají, jak se práce v čase odvíjela.
Ten rozdíl v agentních systémech záleží, protože „pomalé“ je příliš tupý pojem na to, aby byl užitečný.
Trace nám dokáže říct, jestli bolest pramenila z:
- latence modelu
- doby provádění nástrojů
- opakovaných pokusů
- jedné obzvlášť nákladné interakce s MCP
- dlouhého ocasu drobných operací, které samostatně vypadaly neškodně
V praxi používáme hookový proud a trace v Tempo společně.
- Hook logy odpovídají na: co se stalo za typ věci?
- Trace odpovídají na: kam šel čas?
Ta kombinace je to, co promění observabilitu z dashboardu ve vysvětlení.
Kam zapadá Codex
Codex je součástí stejného stacku, ale není totožný s Claude Code.
Pro Codex zapojujeme dvě části:
- Nativní OTEL z Codexu do Alloy
- Notify webhook do
codex_notify.py, který mapuje dokončení tahů do stejného schématu Loki, jaké používáme pro hook eventy
To nám dává jednotný filtr jako agent_tool="codex-cli" v rámci stejného proudu logů.
Poctivá výhrada: notify payload Codexu je v současnosti tenčí než hookový payload Claude Code, protože nejde o stejný typ integračního povrchu. V našem dnešním nastavení se dokončení tahů Codexu dají normalizovat do sdíleného schématu, ale bohatá extrakce nástroj po nástroji je pořád lepší v nativním OTEL proudu než v notify mostu.
To není důvod se tomuto příspěvku vyhýbat. Je to jeho smysl. Skutečné observability systémy se sestavují z nedokonalých signálů.
Grafana přes MCP mění hru
Větší posun je v tom, že Grafana není jen místo, kam lidé chodí přes prohlížeč.
V tomto repozitáři vystavujeme Grafanu i přes MCP. To znamená, že agent umí dotazovat Loki, Prometheus a Tempo přímo, místo aby čekal, až člověk nejdřív ručně prohlédne dashboardy.
To mění observabilitu v aktivní vstup do workflow.
Agent se může zeptat:
- Které rodiny nástrojů selhávaly nejvíc za poslední hodinu?
- Který MCP server v session dominoval?
- Snížily nedávné změny počet selhání nástrojů, nebo jen přesunuly práci do cest náročnějších na shell se stejnými chybami?
- Které trace ukazují nejvyšší latenci nebo opakované pokusy?
Jakmile tohle máte, jste velmi blízko smyčce sebezlepšování.
Od dashboardu ke zpětnovazební smyčce
Toto je část, kterou považujeme za nejzajímavější.
Jakmile je observability stack dotazovatelný z vrstvy agenta, telemetrie přestává být pasivní reportovací plochou a stává se řídicím signálem.
Smyčka vypadá takto:
- Aktivita agenta vysílá trace, metriky a obohacené hook logy.
- Grafana ukládá důkazy do Loki, Tempo a Prometheus tam, kde metriky existují.
- Agenti se na tyto důkazy dotazují přes Grafana MCP.
- Systém identifikuje špatný mix nástrojů, křehké skilly, slabé směrování nebo workflow náročné na shell, které pořád produkují chyby, jimž se dalo vyhnout.
- Agenti nebo operátoři upravují prompty, konfigurace agentů, popisy skillů, pravidla směrování nebo přístup k nástrojům.
- Další session vyprodukuje nový tvar telemetrie a cyklus se opakuje.
Takhle se posunete od „zajímavého dashboardu“ k „měřitelnému systému zlepšování“.
Cílem není maximalizovat jednu kategorii nástrojů. Cílem je najít správný mix CLI, vestavěných nástrojů, volání MCP a skillů pro práci, která se skutečně dělá.
Co nám to umožňuje zodpovědět
Jakmile oba runtime přistanou ve stejném Grafana stacku, umíme mnohem rychleji odpovídat na provozní otázky:
- Jsou selhání koncentrovaná v jedné rodině nástrojů?
- Vytvářejí workflow náročné na shell chyby, kterým by se šlo vyhnout tam, kde by měl existovat nástroj vyšší úrovně?
- Které MCP servery nesou většinu zátěže?
- Platíme za aktivitu agenta, která neprodukuje smysluplný pokrok?
- Je session nezdravá kvůli modelu, nástrojům, nebo orchestrační vrstvě?
To je obzvlášť užitečné ve víceagentních workflow, kde vám „agent byl zaneprázdněný“ neřekne skoro nic.
Pokud je jeden specialista pořád vysílán a produkuje vysokou míru selhání, jde o problém směrování nebo formulace promptu.
Pokud jeden MCP server dominuje všem voláním, může to být dobrá architektura, nebo signál, že všechno ostatní je mrtvá váha.
Pokud selhání nástrojů rostou, zatímco náklady zůstávají vysoké, máte provozní problém, ne problém kvality.
Pokud práce v shellu pořád selhává předvídatelně a vyhnutelně tam, kde by měl existovat nástroj vyšší úrovně, jde o produktový signál.
Pokud se jeden skill neustále aktivuje, ale výsledky nezlepšuje, jde o signál k promptu nebo směrování.
Skutečné ponaučení
Hlubší ponaučení je, že observabilita agentů potřebuje jak telemetrii runtime, tak telemetrii workflow.
Telemetrie runtime vám řekne, co systém udělal.
Telemetrie workflow vám řekne, co si agent myslel, že dělá.
Potřebujeme obojí.
Pokud si necháváte jen trace a čítače, přijdete o sémantickou vrstvu. Pokud si necháváte jen hook eventy, přijdete o latenci, spany a širší obrázek runtime.
A pokud si necháváte obojí, ale nikdy to nezpětně nezapojíte do vrstvy agenta, máte monitoring, ne adaptaci.
Kombinace je to, co dělá systém dostatečně vysvětlitelným na provoz a dostatečně laditelným na zlepšování.
Co je pořád nedokonalé
Pořád tu jsou hrubé hrany.
- Ne každý hook event obsahuje data o délce trvání a tokenech, jaká bychom chtěli.
- Některé z nejlepších pohledů na časování pořád pocházejí z Tempo trace, ne z hook logů.
- Codex je dnes v obohaceném proudu eventů sémanticky chudší než Claude Code.
- Snímek dashboardu je živý provozní povrch, ne vypulírovaný marketingový artefakt.
Tenhle poslední bod je záměrný. Radši ukážeme skutečný přístrojový panel, než abychom předstírali, že agentní systémy se magicky vysvětlují samy.
Proč na tom u Maguyva záleží
Maguyva má agentům dávat lepší inteligenci nad kódem. Ale jakmile agenti skutečně dělají užitečnou práci, okamžitě se objeví nový požadavek: potřebujete vidět, jak se chovají.
Kvalita vyhledávání, kvalita směrování, výběr nástrojů a efektivita kontextu se všechno stávají pozorovatelnými problémy.
Proto si myslíme, že o tom stojí za to psát. Budoucí agentní stack nejsou jen prompty a nástroje. Jsou to prompty, nástroje a instrumentační vrstva, která vám řekne, jestli to celé funguje.
Pokud stavíte seriózní agentní workflow, observabilita není volitelná infrastruktura. Je součástí produktu.
Související čtení
Další ze stavebního deníku Maguyva
Proč jsme upgradovali vyhledávání v kódu na voyage-4-large_
Přesunuli jsme naše embeddingy kódu na voyage-4-large — aktuálně na špici veřejného žebříčku RTEB pro retrieval kódu. Upřímná verze: kompromis, který děláme, co skutečně indexujeme a proč platíme za prémiové embeddingy.
Jazykové rekurzivní sebezlepšování: brousíme code intelligence napříč ~280 jazyky_
Podporujeme code intelligence pro ~280 jazyků. Ručně to žádný člověk zaudituje. Postavili jsme proto jazykovou smyčku rekurzivního sebezlepšování — namátková kontrola, LLM jako rozhodčí, oprav jednu věc, znovu ověř — a necháme ji běžet na flotile izolovaných agentů, dokud extrakce není skutečně správná, ne jen zelená.
Multi-modální fúzní vyhledávání: pro každý dotaz ten správný retriever_
Dotaz jako „kde je definovaný parseConfig“ chce jiné vyhledávání než „jak funguje autentizace“. Maguyva klasifikuje záměr, podle toho zváží čtyři vyhledávací modality a výsledky sloučí pomocí vážené Reciprocal Rank Fusion.