Lumaktaw papunta sa content
cd /blog

Agent Observability: Mga Hook, Alloy, at Grafana

[Observability][Grafana][OpenTelemetry][Architecture]

> Kinabit namin ang Claude Code at Codex sa iisang Grafana stack gamit ang OpenTelemetry at Alloy, tapos ginamit ang traces at logs para mahanap at ayusin ang mga isyu sa agent behavior sa pinagmulan mismo.

Kakaiba ang paraan ng pagkasira ng agent systems.

Minsan ang model ang problema. Minsan ang tool ang problema. Minsan okay naman ang MCP server mo, pero mali ang specialist na pinili ng agent, o kalahati ng session ay ginugol sa shell work na hindi mo inaasahan, o tahimik na nag-burn ng cost sa isang loop na parang productive kung titingnan mula sa labas.

Kung hindi mo makita ang pagkakaiba, hindi mo talaga ino-operate ang agent system mo. Nagha-hulaan ka lang.

Kaya gumawa kami ng observability stack para sa sarili naming workflow: Claude Code, Codex, Claude hook events, Codex notify events, native OpenTelemetry, Grafana Alloy, at Grafana Cloud sa kabilang dulo.

Ang interesting na parte, hindi ang “gumawa kami ng dashboard.” Ang interesting na parte, kinailangan naming hatiin ang telemetry sa dalawang magkaibang stream dahil walang iisang feed na nagbigay sa amin ng buong larawan.

Ang Problema: Fragmented ang Agent Telemetry

May telemetry na naman ang mga modernong coding agent. Nakakatulong iyon, pero hindi sapat.

Magaling ang native OTEL sa pagsagot ng mga tanong tulad ng:

  • Ilang request ba ang nagawa namin?
  • Magkano ang naging cost ng isang session?
  • Nasaan ang mga span at trace?
  • May latency spike ba?

Mas mahina ito sa pagsagot ng mga tanong tulad ng:

  • Aling MCP server ba ang ginamit ng agent?
  • Nasa Bash ba ang failure na ito, sa isang built-in file tool, o sa isang MCP call?
  • Aling skill ba ang talagang na-activate?
  • Aling subagent type ba ang na-dispatch?
  • Productive ba talaga ang ginawa ng session, o nagta-thrash lang?

Ang ikalawang klase ng tanong, mas malapit ang sagot sa hooks kaysa sa traces.

Pero totoo rin ang kabaligtaran: ang ilan sa pinakamahalagang performance na tanong, mas malapit ang sagot sa traces kaysa sa hooks.

Kung gusto mong malaman kung saan talaga na-accumulate ang latency, aling mga span ang mabagal, o kung nag-burn ba ng oras ang session sa model calls o sa tool execution, kailangan mo ng trace data bukod sa semantic events.

Ang Architecture na Naging Resulta

Dalawang telemetry path ang pinapatakbo namin nang sabay.

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

Sinadya ang paghahati na iyon.

Asymmetric din ito. Mas mayaman ang lifecycle hook surface na ibinibigay ng Claude Code sa amin. Nagbibigay naman ang Codex ng native OTEL kasama ng isang notify surface, kaya nino-normalize namin ang mas payat na turn-completion events papunta sa parehong log schema sa halip na magkunwaring pareho ang exposed controls ng dalawang runtime.

Ang Native OTEL ang nagbibigay sa amin ng baseline stream: logs at traces mula mismo sa runtime, dagdag pa ang metrics kung saan talagang nag-e-emit ang runtime nito.

Ang Hook at notify events naman ang nagbibigay ng semantic layer: mga bagay tulad ng PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, SubagentStop, SkillActivated, at ang classified metadata na talagang mahalaga sa amin kapag nagde-debug ng agent behavior. Dito nag-a-ambag ang Claude Code ng mas mayamang event stream. Nag-a-ambag naman ang Codex ng mas payat pero kapaki-pakinabang pa ring normalized stream.

Bakit Kailangan Talaga ng Hooks

Pinayayaman ng hook pipeline namin ang mga event bago ito tumama sa Loki.

Sa halip na sabihing lang “may tumakbong tool,” inuuri namin ang event sa mga field tulad ng:

  • tool_type: builtin, mcp, skill, agent, bash
  • mcp_server: aling MCP backend ang humawak sa call
  • bash_cli: ang shell command family
  • subagent_type: anong klaseng specialist ang na-dispatch
  • agent_tool: kung ang pinagmulan ay Claude Code o Codex

Ibig sabihin, makapagtatanong kami ng mga bagay na importante sa operations:

{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"

Hindi vanity fields lang iyon. Iyon ang pagkakaiba sa pagitan ng “parang mabagal ang agent” at “ginugol ng agent ang huling sampung minuto sa shell-heavy git operations na may mataas na tool failure rate.”

May isang implementation detail na mas kakaiba ang itsura kaysa sa aktwal: ginagamit pa rin ng shared Loki stream ang service_name="claude-code-hooks" bilang label kahit galing pa ito sa Codex. Ang tunay na paghahati sa pagitan ng mga runtime nangyayari sa agent_tool.

Bakit Nasa Gitna ang Alloy

Hindi lang forwarder ang Grafana Alloy sa setup na ito. Ito ang policy boundary.

Itinuturo namin ang native OTEL stream mula sa Claude Code at Codex sa isang local Alloy proxy sa localhost:4318, tapos hinahayaan ang Alloy na linisin ang payload bago ito i-forward papunta sa Grafana Cloud.

Mahalaga iyon dahil puno ang raw agent telemetry ng high-cardinality na mga field na kapaki-pakinabang para sa analysis pero nakakatakot naman kung gagawing indexed labels:

  • session_id
  • prompt_id
  • token counts
  • durations
  • mga blob ng parameter ng tool

Kung ii-index mo lahat, magkakaroon ka ng label explosion at masamang araw.

Kaya tatlong bagay ang ginagawa ng Alloy para sa amin:

  1. Pinapanatili ang napakaliit na set ng low-cardinality labels na naka-index.
  2. Inililipat ang maiingay pero kapaki-pakinabang na mga field papunta sa structured metadata.
  3. Tinatanggal ang purong ingay nang tuluyan.

Simple ang mahalagang ideya dito: mag-obserba nang mas marami, mag-index nang mas kaunti.

Bakit Nilalampasan ng Hook Stream ang Alloy

Naka-shape na ang hook stream para sa Loki.

Sa oras na mag-push ng event ang send_event.py, nadesisyunan na namin kung aling mga field ang dapat gawing label at alin ang dapat mapunta sa structured JSON body. Deretso na ang stream na iyon papunta sa OTLP gateway ng Grafana Cloud sa halip na dumaan pa ulit sa Alloy.

Kaya malinaw ang division of labor ng system:

  • Pinapaamo ng Alloy ang raw native OTEL stream.
  • Ginagawang queryable ng hook enrichment ang mga semantic event.

Mas pinapanatiling simple nito ang architecture kaysa sa sapilitang pagpasa ng lahat sa isang path.

Ang Talagang Ipinapakita ng Dashboard

Ang screenshot sa ibaba ay mula sa isa sa mga observability dashboard sa likod ng agent workflow namin. Hindi ito benchmark, at ang mga numero ay isang point-in-time slice lang. Ang punto ay ang hugis ng data: feed ng aktibidad, mga tawag sa tool, failure, prompt, at breakdown ayon sa agent, built-in na tool, MCP usage, shell command, at skills.

Ang kapaki-pakinabang na parte, nasa parehong Grafana stack ang dashboard na ito kasama ang natitirang agent telemetry. Puwede naming i-filter ayon sa source agent at tool family at tingnan ang lahat sa iba’t ibang runtime nang hindi na kailangang mag-imbento ng ibang observability story para sa bawat system.

Grafana dashboard na nagpapakita ng feed ng aktibidad, bilang ng mga tawag sa tool, failure, prompt, at breakdown ayon sa agents, built-in na tool, MCP usage, CLI command, at skills para sa isang agent workflow.
Isa sa mga live dashboard sa likod ng agent workflow namin. Isang slice lang ito ng shared Grafana stack na tumatanggap din ng telemetry mula sa iba naming agent runtime at system. I-click ang larawan para sa full-resolution na bersyon.

Bakit Mas Mahalaga ang Traces Kaysa sa Unang Tingin

Sinasabi sa amin ng logs kung anong kategorya ng trabaho ang nangyari. Sinasabi naman sa amin ng traces kung paano umunlad ang trabaho sa paglipas ng oras.

Mahalaga ang pagkakaibang iyon sa agent systems dahil masyadong malabo ang salitang “mabagal” para maging kapaki-pakinabang.

Puwedeng sabihin sa amin ng trace kung saan galing ang sakit ng ulo:

  • latency ng modelo
  • oras ng pagpapatakbo ng tool
  • paulit-ulit na retries
  • isang lalong mahal na MCP interaction
  • mahabang buntot ng maliliit na operations na parang wala namang epekto kung tingnan nang paisa-isa

Sa praktika, magkasabay naming ginagamit ang hook stream at ang Tempo traces.

  • Sinasagot ng Hook logs: anong klaseng bagay ang nangyari?
  • Sinasagot ng Traces: saan napunta ang oras?

Ang kombinasyon ng dalawa ang nagpapalit sa observability mula sa isang dashboard papunta sa isang paliwanag.

Kung Saan Pumapasok ang Codex

Bahagi ng parehong stack ang Codex, pero hindi ito kapareho ng Claude Code.

Para sa Codex, dalawang piraso ang ikinakabit namin:

  • Native OTEL mula sa Codex papunta sa Alloy
  • Isang notify webhook papunta sa codex_notify.py, na nagma-map ng turn completions papunta sa parehong Loki schema na ginagamit namin para sa hook events

Ibig sabihin, may unified filter kaming tulad ng agent_tool="codex-cli" sa loob ng parehong log stream.

Ang tapat na caveat: mas payat pa ngayon ang notify payload ng Codex kumpara sa hook payload ng Claude Code dahil hindi ito parehong klase ng integration surface. Sa setup namin ngayon, puwedeng i-normalize ang mga turn completion ng Codex papunta sa shared schema, pero mas maganda pa rin ang rich tool-by-tool extraction sa native OTEL stream kaysa sa notify bridge.

Hindi iyon dahilan para iwasan ang post na ito. Iyon mismo ang punto ng post na ito. Ang tunay na observability system, ginagawa mula sa mga imperfect na signal.

Binabago ng Grafana Over MCP ang Laro

Ang mas malaking shift, hindi na lang lugar ang Grafana na binibisita ng mga tao sa browser.

Sa repo na ito, ini-expose din namin ang Grafana sa MCP. Ibig sabihin, puwedeng direktang mag-query ng Loki, Prometheus, at Tempo ang isang agent sa halip na maghintay sa isang tao na manual na tingnan muna ang mga dashboard.

Ginagawa nito ang observability na isang active input sa workflow.

Puwedeng magtanong ang isang agent:

  • Aling tool families ang pinakamaraming nag-fail sa nakaraang oras?
  • Aling MCP server ang naging dominante sa isang session?
  • Binawasan ba ng mga kamakailang pagbabago ang tool failures, o inilipat lang nila ang trabaho papunta sa mas shell-heavy na mga path na may parehong mga pagkakamali?
  • Aling mga trace ang nagpapakita ng pinakamataas na latency o paulit-ulit na retries?

Kapag meron ka na niyan, malapit ka na sa isang self-improvement loop.

Mula sa Dashboard Papunta sa Feedback Loop

Ito ang parte na sa amin ang pinaka-interesting.

Sa oras na queryable na ang observability stack mula sa agent layer, hindi na lang passive reporting surface ang telemetry — nagiging control signal na ito.

Ganito ang hugis ng loop:

  1. Naglalabas ang agent activity ng traces, metrics, at pinayamang hook logs.
  2. Iniimbak ng Grafana ang ebidensya sa Loki, Tempo, at Prometheus kung saan mayroong metrics.
  3. Nagqu-query ang mga agent ng ebidensyang iyon sa pamamagitan ng Grafana MCP.
  4. Kinikilala ng system ang masamang tool mix, marupok na skills, mahinang routing, o shell-heavy na workflows na patuloy na gumagawa ng maiiwasang pagkakamali.
  5. Nag-aadjust ang mga agent o operator ng prompts, agent configs, skill descriptions, routing rules, o tool access.
  6. Nagbubunga ng bagong telemetry shape ang susunod na session, at umuulit ang cycle.

Ganoon ka aakyat mula sa “interesting dashboard” papunta sa “measurable improvement system.”

Hindi ang punto na i-maximize ang isang tool category. Ang punto, mahanap ang tamang timpla ng CLI, built-in tools, MCP calls, at skills para sa trabahong talagang ginagawa.

Ano ang Kaya Naming Sagutin Ngayon

Sa oras na parehong napunta sa iisang Grafana stack ang dalawang runtime, mas mabilis naming masasagot ang mga operational na tanong:

  • Nakakonsentra ba ang mga failure sa isang tool family?
  • Gumagawa ba ng maiiwasang pagkakamali ang mga shell-heavy na workflow kung saan dapat may mas mataas na antas na tool?
  • Aling mga MCP server ang may pinakamabigat na workload?
  • Nagbabayad ba kami para sa agent activity na hindi naman nagbubunga ng makabuluhang progreso?
  • Hindi ba malusog ang isang session dahil sa model, sa mga tool, o sa orchestration layer?

Lalo itong kapaki-pakinabang sa multi-agent workflows, kung saan wala talagang sinasabi ang “busy ang agent.”

Kung paulit-ulit na na-dispatch ang isang specialist at gumagawa ng mataas na failure rate, isyu iyon sa routing o sa prompt-shaping.

Kung isang MCP server ang dominante sa lahat ng calls, puwedeng magandang architecture iyon, o palatandaan na patay na timbang ang lahat ng iba pa.

Kung sumisipa ang tool failures habang mataas pa rin ang cost, isyu iyon sa operations, hindi sa quality.

Kung paulit-ulit na nabibigo ang shell work sa predictable at maiiwasang paraan kung saan dapat may mas mataas na antas na tool, isyu iyon sa produkto.

Kung palaging na-a-activate ang isang skill pero hindi naman umaangat ang outcomes, isyu iyon sa prompt o sa routing.

Ang Tunay na Aral

Ang mas malalim na aral dito, kailangan ng agent observability ng parehong telemetry ng runtime at telemetry ng workflow.

Sinasabi sa iyo ng telemetry ng runtime kung ano ang ginawa ng system.

Sinasabi sa iyo ng workflow telemetry kung ano sa tingin ng agent ang ginagawa nito.

Kailangan namin ng pareho.

Kung traces at counters lang ang panatilihin mo, mawawala sa iyo ang semantic layer. Kung hook events lang ang panatilihin mo, mawawala sa iyo ang latency, spans, at ang mas malawak na larawan ng runtime.

At kung panatilihin mo man ang pareho pero hindi mo ito ipinapakain pabalik sa agent layer, monitoring lang ang meron ka, hindi adaptation.

Ang kombinasyon ang gumagawa sa system na sapat na maipaliwanag para ma-operate at sapat na ma-tune para umangat.

Ano ang Hindi Pa Perpekto

May mga rough edge pa rin.

  • Hindi lahat ng hook event ay may kasamang duration at token data na gusto namin.
  • Ang ilan sa pinakamagandang timing view, galing pa rin sa Tempo traces, hindi sa hook logs.
  • Mas mababa pa ngayon ang semantic richness ng Codex kumpara sa Claude Code sa enriched event stream.
  • Ang dashboard screenshot ay isang live operations surface, hindi isang pinakintab na marketing artifact.

Sinadya ang huling punto na iyon. Mas gusto naming ipakita ang tunay na instrument panel kaysa magkunwaring self-explanatory na lang basta-basta ang agent systems.

Bakit Mahalaga Ito Para sa Maguyva

Ang layunin ng Maguyva, bigyan ang mga agent ng mas magandang code intelligence. Pero sa oras na talagang may kapaki-pakinabang na trabaho na ang mga agent, may bagong requirement na agad na lumilitaw: kailangan mong makita kung paano sila kumikilos.

Nagiging observable problems ang search quality, routing quality, tool selection, at context efficiency.

Kaya naman sa tingin namin, sulit itong isulat. Hindi lang prompts at tools ang future agent stack. Prompts, tools, at ang instrumentation layer na nagsasabi sa iyo kung gumagana ba talaga ang buong bagay.

Kung nagtatayo ka ng seryosong agent workflows, hindi optional infrastructure ang observability. Bahagi ito ng produkto.

Kaugnay na babasahin

Higit pa mula sa build log ng Maguyva