Lompat ke konten
cd /blog

Observabilitas Agen: Hooks, Alloy, dan Grafana

[Observabilitas][Grafana][OpenTelemetry][Arsitektur]

> 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, bash
  • mcp_server: backend MCP mana yang menangani panggilan
  • bash_cli: keluarga perintah shell
  • subagent_type: jenis spesialis apa yang dikirim
  • agent_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_id
  • prompt_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:

  1. Menjaga sekumpulan kecil label berkardinalitas rendah tetap terindeks.
  2. Memindahkan field yang berisik tetapi berguna ke metadata terstruktur.
  3. 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.

Dashboard Grafana yang menampilkan activity feed, jumlah panggilan tool, kegagalan, prompt, dan pemecahan berdasarkan agen, tool bawaan, penggunaan MCP, perintah CLI, dan skill untuk alur kerja agen.
Salah satu dashboard langsung di balik alur kerja agen kami. Tangkapan layar ini hanyalah satu irisan dari stack Grafana bersama yang juga menerima telemetri dari runtime dan sistem agen kami yang lain. Klik gambar untuk versi resolusi penuh.

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:

  1. Aktivitas agen mengemisikan trace, metrik, dan log hook yang telah diperkaya.
  2. Grafana menyimpan bukti tersebut di Loki, Tempo, dan Prometheus tempat metrik itu ada.
  3. Agen meng-query bukti itu lewat Grafana MCP.
  4. 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.
  5. Agen atau operator menyesuaikan prompt, config agen, deskripsi skill, aturan perutean, atau akses tool.
  6. 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