Membangun Laras-Bot: Dari Takopi, Pattern Utah, ke Impian ngoding dari Hape
Beberapa minggu lalu, aku nyobain Takopi — sebuah CLI tool yang bisa jalanin coding agent dan nyambungin ke Telegram1. Idenya simpel tapi powerful banget: ada layer otomasi di atas coding agent, dengan interface chat sebagai gateway-nya. Pas nyoba, rasanya langsung “klik”.
Tapi pas udah dipake beberapa lama, aku mulai ngerasa ada yang kurang—terutama di sisi observability pas agent-nya lagi kerja. Terus aku nemu sebuah tulisan yang nunjukin pattern yang pas buat nutup celah itu. Akhirnya, berujung jadi proyek sendiri yang sekarang udah jalan hampir seminggu di homelab.
Nah, ini ceritanya gimana laras-bot akhirnya lahir.
Takopi: Pertama kali semuanya terasa “klik” #
Takopi itu intinya layer otomasi di atas coding agent berbasis CLI. Dia support beberapa engine kayak Pi dan Codex, terus punya gateway ke Telegram.
Yang bikin aku semangat bukan cuma fitur-fiturnya, tapi gimana cara dia ngelola project:
- Project registration: Tinggal
takopi initdi sebuah repo dan bikin alias. Dari mana aja (termasuk lewat chat), tinggal kirim perintah kayak/happy-gadgets do something. - Topic binding: Tiap topik di Telegram bisa di-bind ke satu project. Jadi percakapan tetep rapi, satu topik = satu konteks project.
Ini mirip banget sama UX di Slack atau Discord: tiap channel ngomongin hal yang beda, konteks kepisah, gak campur aduk. Dari sini aku mikir: “Wah, ini cara kerja yang mau aku pake terus nih.” Tapi ya itu tadi, ada sesuatu yang masih ganjel.
Celah yang mau aku tutup: Resilience & Error Monitoring #
Sebenernya Takopi udah oke banget, dia pun udah punya streaming output buat liat apa yang lagi dikerjain agent-nya. Tapi masalah utamaku lebih ke arah resilience dan monitoring pas ada yang error.
Belajar dari pengalaman pas pake OpenClaw dulu, banyak cron job atau sesi chat yang sering banget kena silently error—tiba-tiba berenti gitu aja tanpa kabar, atau failed tapi kita gak tau di step mana dan kenapa.
Buat tugas kecil sih gak masalah ya. Tapi kalau agent-nya mesti jalan 10-30 menit—misalnya pas lagi refactor besar atau debug yang kompleks—aku butuh visibilitas yang lebih dalam:
- Kalau error, dia nyangkut di activity mana secara spesifik?
- Bisa gak tugasnya di-retry otomatis tanpa harus ngulang dari nol?
- Status tiap langkahnya tercatat gak secara historis?
Aku butuh sistem yang lebih “keras kepala” dan bisa kasih tau dengan jelas kalau ada yang gak beres. Di situlah aku ngerasa butuh sesuatu yang lebih dari sekadar streaming logs.
Pattern Utah: Agent loop sebagai Durable Workflow #
Terus aku baca blog post dari JoelClaw tentang Utah2, dan dia ngasih link ke proyek open-source namanya Utah dari Inngest3.
Utah ini ngasih contoh implementasi yang bikin aku beneran paham polanya. Idenya begini:
Setiap interaksi sama agent di-orchestrate sebagai durable workflow. Tiap langkah (think, act, observe) adalah step yang bisa dimonitor, di-retry, dan di-trace.
Kira-kira alurnya kayak gini:
Message masuk → trigger workflow
├── step: acknowledge (tampilin "typing...")
├── step: think (LLM call)
├── step: tool-read
├── step: tool-exec
├── step: think lagi (loop)
└── step: send-replyPlus ada beberapa tambahan keren:
- Heartbeat: Cron berkala buat ngerangkum daily logs jadi long-term memory.
- Failure handler: Global catch yang bakal ngabarin kita kalau ada yang error.
- Singleton per chat: Satu sesi per thread, otomatis cancel kalau ada pesan baru masuk.
Yang bikin Utah menarik bukan cuma kodenya, tapi pattern-nya. Ini pola yang muncul terus di berbagai proyek: Pi punya session management, Takopi punya project management, Utah punya workflow durability—semuanya kayak “konvergen” ke satu titik kebutuhan yang sama.
Inspirasi di Atas Bermuara Jadi Laras-Bot #
Tulisan JoelClaw itu nunjukin sesuatu yang sekarang makin aku yakini: ada pola arsitektur yang ditemuin secara independen oleh banyak orang, dan semuanya bermuara ke bentuk yang mirip.
Dari tiap proyek yang aku pelajarin, ada beberapa komponen yang selalu ada:
| Komponen | Takopi | Utah | Pi |
|---|---|---|---|
| Transport/Gateway | Telegram | Inngest Cloud | Terminal |
| Orchestration | Internal | Inngest (durable) | Session management |
| Project/Context | Project + branch | Workspace files | Session dir |
| Memory | — | File-based + distillation | Session file |
| Observability | Minimal | Inngest dashboard | Internal |
Masing-masing punya kelebihan sendiri. Tapi masalahnya: gak ada yang punya semuanya dalam satu paket.
Keputusan: Bikin sendiri aja wqwq #
Dari situ, keputusannya udah jelas: aku mau gabungin hal-hal terbaik dari tiap pattern tadi, tapi pake infrastruktur yang emang udah ada di homelab-ku sendiri.
Tech stack pilihanku:
- Node.js + TypeScript + Fastify: Backend yang emang udah jadi makanan sehari-hari.
- Temporal: Durable workflow engine yang jalan di homelab pake SQLite-backed (jadi gak perlu ribet setup DB terpisah).
- SQLite: Database utama, simpel, enteng, dan ngebut.
- Mattermost: Self-hosted chat yang mirip Slack, setup-nya gampang banget.
Kenapa Mattermost, bukan Telegram?
Takopi milih Telegram karena gampang diakses siapa aja. Tapi buat kebutuhanku, Mattermost lebih masuk akal:
- Self-hosted: Data gak lewat server orang lain.
- Mirip Slack: UX-nya udah biasa dipake pas kerja, jadi lebih familiar.
- Channel = Project: Tiap channel bisa di-bind ke satu project, persis kayak konsep Takopi tapi lebih rapi.
- Full control: Bisa di-custom dan dipantau sesuka hati.
Dan yang paling penting: Temporal udah jalan di homelab-ku. Jadi kalau mau liat workflow dashboard-nya, tinggal buka web UI-nya aja, beres!
Laras-Bot: Arsitekturnya #
Proyek ini aku kasih nama laras-bot. Kodenya ada di repo sendiri dan sekarang udah jalan anteng sebagai systemd service.
Flow Utama #
Contoh interaksi dengan laras-bot di Mattermost.
Mattermost (WebSocket)
→ Message masuk
→ Project Router (nentuin ke project mana)
→ Dispatcher → Temporal Workflow (chatThreadWorkflow)
→ Activities:
├── ensureSession (bikin/lanjutin session)
├── createRun (catat run di DB)
├── executeEngineTurn (jalanin engine CLI)
└── finalizeRun (simpen hasilnya)
→ Engine Adapter (Pi / Gemini)
→ Events via NATS → Progress Consumer → MattermostTemporal Workflow: chatThreadWorkflow #
Ini jantung dari sistemnya. Workflow ini aku desain pake pola drain-and-exit loop yang terinspirasi dari konsep singleton per chat milik Utah. Idenya sederhana: cuma boleh ada satu workflow aktif per thread chat, jadi gak bakal ada dua agent yang rebutan konteks di waktu yang sama.
Alurnya kira-kira begini:
- Tunggu pesan masuk (lewat signal).
- Proses pesannya: ensure session → create run → execute engine → finalize.
- Cek apa masih ada pesan di antrean (queue).
- Kalau kosong, tunggu timeout 10 detik terus selesaikan workflow.
- Workflow baru bakal otomatis jalan lagi kalau ada pesan baru masuk.
Semua proses ini kelihatan jelas di Temporal Web Dashboard. Aku bisa trace tiap langkahnya, liat riwayat event-nya, dan gampang banget kalau mau debug pas ada yang aneh-aneh. Gak ada lagi ceritanya error diem-diem tanpa jejak wqwq.
Engine Adapter: Pi dan Gemini #
Sejauh ini aku implementasi dua engine:
Pi: Karena dia punya package pi-ai yang bisa nyambung ke berbagai provider AI. Enaknya, aku bisa switch provider dengan gampang dan pake fitur --append-system-prompt buat nyuntik kepribadian (persona) si agent.
Gemini CLI: Aku suka banget sama model Gemini, dan CLI-nya makin ke sini makin mantap. Plus, langganan Google One AI Pro itu value-nya gede banget: dapet Gemini CLI, NotebookLM, AI Studio, dll. Harganya mirip sama langganan AI lain tapi dapet fiturnya bejibun.
Kedua engine ini jalan sebagai child process. Si adapter bakal nangkep output JSONL, ngerapiin event-nya, terus dikirim lewat NATS biar kita bisa liat progress-nya secara real-time di Mattermost.
Scheduled Tasks via Temporal #
Tampilan daftar scheduled tasks di Temporal dashboard.
Ini fitur yang bikin kerjaan harian jadi otomatis banget. Cron-nya dikelola langsung sama Temporal, jadi lebih enak karena:
- Bisa dipantau di dashboard Temporal.
- Bisa dipicu manual kalau lagi butuh.
- Bisa di-pause atau resume.
- Udah ada retry logic bawaan kalau gagal.
Beberapa task yang udah jalan otomatis:
| Task | Jadwal |
|---|---|
| Brain auto commit | setiap 4 jam |
| Brain qmd update | setiap 6 jam |
| Daily Brain Memory | setiap hari |
| Morning Journal & Weather | harian pagi |
| Daily Journal Retro Check | harian sore |
| Monday Blog Writer | senin |
| Sunday Weekly Digest | minggu |
Trace detail untuk satu workflow yang sedang berjalan.
Review setelah seminggu pake #
Sekarang laras-bot udah jalan hampir seminggu. Ini beberapa statistiknya:
- 254 sessions (250 aktif).
- 547 runs (tingkat keberhasilan 94%).
- 7 projects aktif.
- 7 scheduled tasks yang jalan terus.
Perubahan paling kerasa dibanding sebelumnya:
- Bisa monitor dari mana aja: Cukup buka dashboard Temporal, bisa liat semua workflow yang lagi jalan dan trace langkah demi langkah.
- Restart tanpa takut ilang state: Kalau ada masalah koneksi, tinggal restart server-nya. Workflow yang sempet kegantung bakal dilanjutin otomatis karena state-nya aman di Temporal.
- Punya kontrol penuh: Semuanya jalan di homelab, gak tergantung sama layanan pihak ketiga buat urusan orchestration-nya.
Bukan cuma soal Tool, tapi soal Pattern #
Kalau ditarik garis besarnya, cerita ini tuh sambungan dari tulisan sebelumnya soal evolusi workflow coding agent4. Dari Cody ke Amp terus ke Pi, fokusnya selalu sama: konteks harus dijaga, sesi harus dipisah, dan agent harus punya peran yang jelas.
Laras-bot nambahin satu lapis lagi: orchestration harus observable. Bukan cuma asal agent-nya jalan, tapi kita kudu bisa liat gimana dia jalan, di mana, dan berapa lama.
Pola yang muncul dari Takopi, Utah, Pi, sampe laras-bot itu sebenernya sama:
- Pisahin konteks per project/thread: Takopi pake topic, laras-bot pake channel binding.
- Durable execution: Utah pake Inngest, laras-bot pake Temporal.
- Engine abstraction: Semuanya bisa gonta-ganti engine (Pi, Gemini, dll).
Masing-masing emang beda cara ngerjainnya, tapi polanya mirip-mirip. Dan ini bikin aku makin yakin kalau ini bukan sekadar tren doang, tapi emang cara yang “bener” buat ngatur coding agent buat skala personal.
Selanjutnya? #
Masih ada beberapa hal yang mau aku perbaikin lagi:
- Dashboard monitoring khusus: Aku pengen bikin dashboard ringan buat mantau session lebih detail dan real-time dengan cara consume events dari NATS. Jadi bisa liat langsung tiap step-nya (kayak tool-read, tool-exec, think loop) pas lagi jalan.
- Abstraksi Konsep Agent: Alih-alih cuma gonta-ganti file
SOUL.md, aku mau nerapin hierarki Project → Agent → Engine. Konsep ini terinspirasi saat baca tweet Bang Anvie5 tentang bagaimana memisahkan identitas agent dari infrastrukturnya.- Project bakal nentuin working directory (konteks kode).
- Agent bakal jadi “personanya” yang punya identitas unik lewat
SOUL.mdyang bisa di-kustomisasi. - Engine adalah mesin penggeraknya (Pi, Gemini, dsb). Jadi tiap project bisa punya default agent, dan kita bisa ganti “siapa” yang ngerjain project itu dengan mudah tanpa kehilangan konteks direktorinya.
- Logika fallback: Kalau satu engine/model lagi down atau limit, otomatis nyoba fallback ke engine lain yang tersedia di agent tersebut.
Tapi buat sekarang, yang paling penting udah dapet: coding agent yang bisa dipantau, gampang dikelola, dan standby 24/7 di homelab. Mantap!
Proyek laras-bot ini adalah tool personal yang aku bikin buat kebutuhan sendiri. Kodenya belum open-source, tapi konsep dan polanya bisa dipelajari dari tulisan ini.