Observabilitas Agen: Hooks, Alloy, dan Grafana
> Kami menghubungkan Claude Code dan Codex ke satu stack Grafana yang sama dengan OpenTelemetry dan Alloy, lalu menggunakan trace dan log untuk menemukan dan memperbaiki masalah perilaku agen langsung di sumbernya.
Sistem agen gagal dengan cara-cara yang aneh.
Kadang modelnya yang bermasalah. Kadang toolnya yang bermasalah. Kadang server MCP Anda baik-baik saja, tetapi agen memilih spesialis yang salah, atau menghabiskan separuh sesi melakukan pekerjaan shell yang tidak Anda duga, atau diam-diam membakar biaya dalam sebuah loop yang dari luar terlihat produktif.
Jika Anda tidak bisa melihat perbedaannya, Anda sebenarnya tidak sedang mengoperasikan sistem agen. Anda sedang menebak-nebak.
Jadi kami membangun stack observabilitas untuk alur kerja kami sendiri: Claude Code, Codex, event hook Claude, event notify Codex, OpenTelemetry native, Grafana Alloy, dan Grafana Cloud di sisi lainnya.
Bagian yang menarik bukan “kami membuat dashboard.” Bagian yang menarik adalah kami harus memecah telemetri menjadi dua stream berbeda karena tidak ada satu pun feed tunggal yang memberi kami gambaran utuh.
Masalahnya: Telemetri Agen Itu Terfragmentasi
Agen coding modern sudah mengemisikan sebagian telemetri. Itu membantu, tetapi tidak cukup.
OTEL native andal menjawab pertanyaan seperti:
- Berapa banyak request yang kami buat?
- Berapa biaya sebuah sesi?
- Di mana span dan trace-nya?
- Apakah latensi melonjak?
OTEL native jauh lebih buruk menjawab pertanyaan seperti:
- Server MCP mana yang paling diandalkan agen?
- Apakah kegagalan ini terjadi di
Bash, tool file bawaan, atau panggilan MCP? - Skill mana yang benar-benar aktif?
- Tipe subagen mana yang dikirim?
- Apakah sesi ini sedang melakukan pekerjaan yang berguna, atau sekadar mondar-mandir tanpa hasil?
Kelas pertanyaan kedua itu lebih dekat ke hooks ketimbang trace.
Tetapi kebalikannya juga benar: beberapa pertanyaan performa terpenting justru lebih dekat ke trace ketimbang hooks.
Jika Anda ingin tahu di mana latensi sebenarnya menumpuk, span mana yang lambat, atau apakah sesi menghabiskan waktu pada panggilan model versus eksekusi tool, Anda butuh data trace, bukan hanya event semantik.
Arsitektur yang Kami Bangun
Kami menjalankan dua jalur telemetri berdampingan.
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
Pemisahan itu disengaja.
Ini juga asimetris. Claude Code memberi kami permukaan hook lifecycle yang jauh lebih kaya. Codex memberi kami OTEL native plus permukaan notify, sehingga kami menormalkan event penyelesaian turn yang lebih tipis ke dalam skema log yang sama, alih-alih berpura-pura kedua runtime menyediakan kontrol yang identik.
OTEL native memberi kami stream dasar: log dan trace dari runtime itu sendiri, ditambah metrik di mana runtime benar-benar mengemisikannya.
Event hook dan notify memberi kami lapisan semantik: hal-hal seperti PreToolUse, PostToolUse, PostToolUseFailure, UserPromptSubmit, SubagentStop, SkillActivated, dan metadata terklasifikasi yang benar-benar kami pedulikan saat men-debug perilaku agen. Claude Code menyumbang stream event yang lebih kaya di sini. Codex menyumbang stream ternormalisasi yang lebih tipis tetapi tetap berguna.
Mengapa Hooks Ada Sama Sekali
Pipeline hook kami memperkaya event sebelum mencapai Loki.
Alih-alih hanya berkata “sebuah tool berjalan,” kami mengklasifikasikan event tersebut ke dalam field seperti:
tool_type: builtin, mcp, skill, agent, bashmcp_server: backend MCP mana yang menangani panggilanbash_cli: keluarga perintah shellsubagent_type: jenis spesialis apa yang dikirimagent_tool: apakah sumbernya Claude Code atau Codex
Itu berarti kami bisa mengajukan pertanyaan yang penting secara operasional:
{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"
Field-field itu bukan sekadar pemanis. Itulah perbedaan antara “agennya terasa lambat” dan “agen menghabiskan sepuluh menit terakhir dalam operasi git yang sarat shell dengan tingkat kegagalan tool yang tinggi.”
Satu detail implementasi yang terlihat lebih aneh dari kenyataannya: stream Loki bersama masih menggunakan service_name="claude-code-hooks" sebagai label bahkan saat event berasal dari Codex. Pemisahan sesungguhnya antara runtime terjadi di agent_tool.
Mengapa Alloy Berada di Tengah
Grafana Alloy bukan sekadar forwarder dalam setup ini. Ia adalah batas kebijakan.
Kami mengarahkan stream OTEL native dari Claude Code dan Codex ke proxy Alloy lokal di localhost:4318, lalu membiarkan Alloy membersihkan payload sebelum meneruskannya ke Grafana Cloud.
Itu penting karena telemetri agen mentah penuh dengan field berkardinalitas tinggi yang berguna untuk analisis tetapi buruk sebagai label yang diindeks:
session_idprompt_id- jumlah token
- durasi
- blob parameter tool
Jika Anda mengindeks segalanya, Anda akan mendapat ledakan label dan hari yang buruk.
Jadi Alloy melakukan tiga hal untuk kami:
- Menjaga sekumpulan kecil label berkardinalitas rendah tetap terindeks.
- Memindahkan field yang berisik tetapi berguna ke metadata terstruktur.
- Membuang noise murni sepenuhnya.
Idenya sederhana: amati lebih banyak, indeks lebih sedikit.
Mengapa Stream Hook Melewati Alloy
Stream hook sudah dibentuk untuk Loki.
Saat send_event.py mengirim sebuah event, kami sudah memutuskan field mana yang layak diberi perlakuan label dan mana yang masuk ke body JSON terstruktur. Stream itu langsung menuju gateway OTLP Grafana Cloud tanpa melewati Alloy lagi.
Jadi sistem ini punya pembagian tugas yang jelas:
- Alloy menjinakkan stream OTEL native yang mentah.
- Pengayaan hook membuat event semantik bisa di-query.
Itu membuat arsitekturnya lebih sederhana daripada memaksa semuanya lewat satu jalur.
Apa yang Sebenarnya Ditampilkan Dashboard
Tangkapan layar di bawah ini berasal dari salah satu dashboard observabilitas di balik alur kerja agen kami. Ini bukan benchmark, dan angka-angkanya hanyalah irisan pada satu titik waktu. Intinya adalah bentuk datanya: activity feed, panggilan tool, kegagalan, prompt, dan pemecahan berdasarkan agen, tool bawaan, penggunaan MCP, perintah shell, dan skill.
Bagian yang berguna adalah dashboard ini hidup di stack Grafana yang sama dengan telemetri agen lainnya. Kami bisa menyaring berdasarkan agen sumber dan keluarga tool, lalu melihat lintas runtime tanpa perlu menciptakan cerita observabilitas yang berbeda untuk setiap sistem.
Mengapa Trace Lebih Penting Daripada Kelihatannya
Log memberi tahu kami kategori pekerjaan apa yang terjadi. Trace memberi tahu kami bagaimana pekerjaan itu berlangsung seiring waktu.
Perbedaan itu penting dalam sistem agen karena kata “lambat” terlalu tumpul untuk berguna.
Sebuah trace bisa memberi tahu kami apakah rasa sakitnya berasal dari:
- latensi model
- waktu eksekusi tool
- retry yang berulang
- satu interaksi MCP yang sangat mahal
- ekor panjang operasi-operasi kecil yang terlihat tak berbahaya jika dilihat sendiri-sendiri
Dalam praktiknya kami menggunakan stream hook dan trace Tempo secara bersamaan.
- Log hook menjawab: jenis hal apa yang terjadi?
- Trace menjawab: ke mana waktunya pergi?
Kombinasi itulah yang mengubah observabilitas dari sekadar dashboard menjadi sebuah penjelasan.
Di Mana Posisi Codex
Codex adalah bagian dari stack yang sama, tetapi tidak identik dengan Claude Code.
Untuk Codex kami menyambungkan dua bagian:
- OTEL native dari Codex ke Alloy
- Webhook notify ke
codex_notify.py, yang memetakan penyelesaian turn ke skema Loki yang sama dengan yang kami gunakan untuk event hook
Itu memberi kami filter terpadu seperti agent_tool="codex-cli" di dalam stream log yang sama.
Catatan jujurnya: payload notify Codex saat ini lebih tipis daripada payload hook Claude Code karena bukan jenis permukaan integrasi yang sama. Dalam setup kami hari ini, penyelesaian turn Codex bisa dinormalkan ke skema bersama, tetapi ekstraksi tool-per-tool yang kaya masih lebih baik di stream OTEL native ketimbang di bridge notify.
Itu bukan alasan untuk menghindari tulisan ini. Itulah justru intinya. Sistem observabilitas sungguhan dirakit dari sinyal-sinyal yang tidak sempurna.
Grafana Lewat MCP Mengubah Permainan
Pergeseran yang lebih besar adalah Grafana bukan lagi hanya tempat manusia berkunjung lewat browser.
Dalam repo ini kami juga mengekspos Grafana lewat MCP. Artinya, seorang agen bisa meng-query Loki, Prometheus, dan Tempo secara langsung tanpa perlu menunggu manusia memeriksa dashboard secara manual terlebih dahulu.
Itu mengubah observabilitas menjadi input aktif bagi alur kerja.
Seorang agen bisa bertanya:
- Keluarga tool mana yang paling banyak gagal dalam satu jam terakhir?
- Server MCP mana yang mendominasi sebuah sesi?
- Apakah perubahan terbaru mengurangi kegagalan tool, atau hanya memindahkan pekerjaan ke jalur yang lebih sarat shell dengan kesalahan yang sama?
- Trace mana yang menunjukkan latensi tertinggi atau retry berulang?
Setelah Anda punya itu, Anda sudah sangat dekat dengan loop peningkatan diri.
Dari Dashboard Menuju Feedback Loop
Inilah bagian yang paling kami anggap menarik.
Setelah stack observabilitas bisa di-query dari lapisan agen, telemetri berhenti menjadi permukaan pelaporan yang pasif dan berubah menjadi sinyal kendali.
Loop-nya terlihat seperti ini:
- Aktivitas agen mengemisikan trace, metrik, dan log hook yang telah diperkaya.
- Grafana menyimpan bukti tersebut di Loki, Tempo, dan Prometheus tempat metrik itu ada.
- Agen meng-query bukti itu lewat Grafana MCP.
- Sistem mengidentifikasi bauran tool yang buruk, skill yang rapuh, perutean yang lemah, atau alur kerja sarat shell yang terus menghasilkan kesalahan yang seharusnya bisa dihindari.
- Agen atau operator menyesuaikan prompt, config agen, deskripsi skill, aturan perutean, atau akses tool.
- Sesi berikutnya menghasilkan bentuk telemetri baru, dan siklus itu berulang.
Itulah cara Anda berpindah dari “dashboard yang menarik” menjadi “sistem peningkatan yang terukur.”
Tujuannya bukan memaksimalkan satu kategori tool. Tujuannya adalah mendarat pada bauran CLI, tool bawaan, panggilan MCP, dan skill yang tepat untuk pekerjaan yang sesungguhnya sedang dilakukan.
Apa yang Bisa Kami Jawab dengan Ini
Setelah kedua runtime mendarat di stack Grafana yang sama, kami bisa menjawab pertanyaan operasional jauh lebih cepat:
- Apakah kegagalan terkonsentrasi pada satu keluarga tool?
- Apakah alur kerja yang sarat shell menciptakan kesalahan yang seharusnya bisa dihindari, padahal seharusnya ada tool level-lebih-tinggi?
- Server MCP mana yang menanggung beban kerja terbesar?
- Apakah kami membayar untuk aktivitas agen yang tidak menghasilkan kemajuan yang berarti?
- Apakah sebuah sesi tidak sehat karena modelnya, tool-nya, atau lapisan orkestrasinya?
Ini sangat berguna dalam alur kerja multi-agen, tempat “agennya sibuk” hampir tidak memberi tahu apa-apa.
Jika satu spesialis terus dikirim dan menghasilkan tingkat kegagalan yang tinggi, itu masalah perutean atau pembentukan prompt.
Jika satu server MCP mendominasi semua panggilan, itu bisa berarti arsitektur yang baik atau tanda bahwa semua yang lain adalah beban mati.
Jika kegagalan tool melonjak sementara biaya tetap tinggi, Anda punya masalah operasional, bukan masalah kualitas.
Jika pekerjaan shell terus gagal dengan cara yang bisa diprediksi dan seharusnya bisa dihindari, padahal seharusnya ada tool level-lebih-tinggi, itu sinyal produk.
Jika satu skill terus aktif tetapi tidak memperbaiki hasil, itu sinyal prompt atau perutean.
Pelajaran Sesungguhnya
Pelajaran yang lebih dalam di sini adalah observabilitas agen membutuhkan telemetri runtime sekaligus telemetri alur kerja.
Telemetri runtime memberi tahu Anda apa yang dilakukan sistem.
Telemetri alur kerja memberi tahu Anda apa yang dikira agen sedang ia lakukan.
Kami butuh keduanya.
Jika Anda hanya menyimpan trace dan counter, Anda kehilangan lapisan semantik. Jika Anda hanya menyimpan event hook, Anda kehilangan latensi, span, dan gambaran runtime yang lebih luas.
Dan jika Anda menyimpan keduanya tetapi tidak pernah memasukkannya kembali ke lapisan agen, Anda punya monitoring, bukan adaptasi.
Kombinasi itulah yang membuat sistem cukup bisa dijelaskan untuk dioperasikan dan cukup bisa disetel untuk ditingkatkan.
Apa yang Masih Belum Sempurna
Masih ada sisi-sisi yang kasar.
- Tidak semua event hook menyertakan data durasi dan token seperti yang kami inginkan.
- Sebagian tampilan timing terbaik masih berasal dari trace Tempo, bukan log hook.
- Codex hari ini masih kurang kaya secara semantik dibandingkan Claude Code dalam stream event yang diperkaya.
- Tangkapan layar dashboard adalah permukaan operasi yang sungguhan, bukan artefak pemasaran yang dipoles.
Poin terakhir itu disengaja. Kami lebih memilih menunjukkan panel instrumen yang sesungguhnya daripada berpura-pura sistem agen secara ajaib menjelaskan dirinya sendiri.
Mengapa Ini Penting Bagi Maguyva
Maguyva soal memberi agen kecerdasan kode yang lebih baik. Tetapi begitu agen benar-benar melakukan pekerjaan yang berguna, sebuah kebutuhan baru segera muncul: Anda perlu melihat bagaimana perilaku mereka.
Kualitas pencarian, kualitas perutean, pemilihan tool, dan efisiensi konteks semuanya berubah menjadi masalah yang bisa diobservasi.
Itulah sebabnya kami rasa ini layak ditulis. Stack agen masa depan bukan sekadar prompt dan tool. Ia adalah prompt, tool, dan lapisan instrumentasi yang memberi tahu Anda apakah keseluruhannya berjalan dengan baik.
Jika Anda membangun alur kerja agen yang serius, observabilitas bukan infrastruktur opsional. Ia adalah bagian dari produk.
Bacaan terkait
Lebih banyak dari build log Maguyva
Mengapa Kami Meningkatkan Pencarian Kode ke voyage-4-large_
Kami memindahkan embedding kode kami ke voyage-4-large — saat ini teratas di papan peringkat retrieval kode RTEB publik. Versi jujurnya: trade-off yang kami ambil, apa yang sebenarnya kami indeks, dan mengapa kami membayar untuk embedding premium.
Language Recursive Self-Improvement: Menggrind Kecerdasan Kode di ~280 Bahasa_
Kami mendukung kecerdasan kode untuk ~280 bahasa. Tidak ada manusia yang bisa mengaudit itu secara manual. Jadi kami membangun loop language recursive self-improvement — spot-check, LLM-as-judge, perbaiki satu hal, validasi ulang — dan menjalankannya dengan sepasukan agen terisolasi sampai ekstraksinya benar-benar tepat, bukan sekadar hijau.
Multi-Modal Fusion Search: Memilih Retriever yang Tepat untuk Setiap Kueri_
Kueri seperti 'di mana parseConfig didefinisikan' menginginkan pencarian yang berbeda dari 'bagaimana auth bekerja'. Maguyva mengklasifikasikan intent, memberi bobot pada empat modalitas retrieval sesuai kebutuhannya, lalu menggabungkan hasilnya dengan weighted Reciprocal Rank Fusion.