- Seiring meningkatnya adopsi agen AI belakangan ini, penggunaan stack hibrida berbasis bahasa Go juga cenderung meningkat
- Agen memiliki karakteristik waktu eksekusi yang panjang, biaya yang tinggi, dan sering mengalami penantian I/O
- Go menyediakan model konkurensi berperforma tinggi seperti goroutine ringan, mekanisme pembatalan terpusat, dan messaging berbasis channel
- Pustaka standar sangat luas, dan alat profiling (
pprof) memudahkan pelacakan kebocoran memori dan thread
- Namun, Go juga memiliki keterbatasan seperti kurangnya ekosistem machine learning, performa puncak yang tidak terlalu menonjol, dan dukungan pihak ketiga yang lebih rendah dibanding bahasa lain
Apa itu agen
- Agen berjalan dalam loop berulang dan berarti proses yang dapat menentukan sendiri langkah eksekusi berikutnya
- Berbeda dari workflow dengan jalur yang telah ditentukan, agen menentukan apakah harus berhenti berdasarkan kondisi (misalnya: “tes lolos”) atau jumlah iterasi maksimum
- Dalam layanan nyata, agen dapat berjalan lama dari beberapa detik hingga beberapa jam, dan biayanya tinggi karena pemanggilan LLM, pengoperasian browser, dan lainnya
- Karena harus memproses input dari pengguna (atau agen lain), terdapat banyak waktu tunggu input/output (I/O)
Mengapa bahasa Go cocok untuk agen
Konkurensi berperforma tinggi
- Goroutine di Go dapat menjalankan ribuan hingga puluhan ribu thread ringan secara bersamaan hanya dengan memori 2KB
- Setiap goroutine memanfaatkan multi-core untuk pemrosesan paralel, sehingga agen yang berada dalam status I/O atau menunggu pun dapat dijalankan tanpa beban besar
- Melalui komunikasi berbasis channel, sinkronisasi diimplementasikan lewat pengiriman pesan alih-alih berbagi memori (meminimalkan penggunaan Mutex)
- Cocok untuk agen yang saling bertukar pesan secara asinkron dan mengelola status
Mekanisme pembatalan terpusat
- Saat memanfaatkan context.Context di Go, sebagian besar pustaka dan API mendukung sinyal pembatalan sehingga menghentikan eksekusi menjadi sangat mudah
- Node.js atau Python memiliki berbagai pola pembatalan yang bercampur, tetapi Go memungkinkan pembatalan dan pelepasan resource secara aman dengan cara yang konsisten
Pustaka standar yang kaya
- Go memiliki pustaka standar yang sangat luas dan mendukung hampir semua area seperti HTTP/web, file, dan network I/O
- Semua I/O mengasumsikan operasi blocking di dalam goroutine, sehingga logika bisnis dapat ditulis secara lurus (straight-line)
- Python lebih kompleks karena berbagai pola konkurensi seperti asyncio, threading, dan process bercampur
Alat profiling dan diagnosis
- Dengan alat bawaan seperti pprof di Go, kebocoran memori dan kebocoran goroutine (thread) dapat dilacak secara real time
- Ini menjadi keunggulan untuk mendiagnosis masalah kebocoran yang dapat muncul pada agen yang berjalan lama dan secara bersamaan
Dukungan coding LLM yang baik
- Berkat sintaks yang sederhana dan pustaka standar yang kaya, LLM dapat menulis kode bergaya Go yang khas dengan baik
- Ketergantungan pada framework rendah, sehingga LLM tidak terlalu perlu memikirkan versi atau pola tertentu
Keterbatasan Go
- Pustaka pihak ketiga dan ekosistemnya masih kurang dibanding Python dan TypeScript
- Tidak cocok untuk implementasi machine learning secara langsung (karena keterbatasan performa dan dukungan)
- Jika membutuhkan performa puncak, Rust dan C++ lebih baik
- Bagi pengembang yang terbiasa longgar dalam error handling, ini bisa terasa agak merepotkan
2 komentar
Daripada Java, pilih Go; daripada Go, pilih Rust :)
Opini Hacker News
Menekankan bahwa faktor latensi terbesar di sebagian besar sistem agen pada akhirnya adalah pemanggilan LLM. Keunggulan yang disebutkan dalam artikel tidak benar-benar menguntungkan bahasa tertentu; sebagian besar pekerjaan justru dihabiskan untuk menunggu lama, memakai resource mahal, menerima input dari pengguna atau agen lain, serta menunggu I/O. Karena karakteristik ini, dibanding kecepatan atau efisiensi eksekusi server, keunggulan yang lebih penting justru ekosistem library AI dan dukungan yang sangat luas di bahasa seperti Python. Ada juga yang menunjukkan bahwa di Python kita perlu memikirkan
asyncioatau library multithreading, tetapi menurutnya pengembangan agen sebenarnya tidak terlalu sulit, dan karena sudah ada orang yang lebih dulu mengembangkan workflow terkait, memulainya pun cukup mudahSaat membangun agen dengan Go, saya merasakan bahwa pola konkurensi dan pengelolaan backpressure yang sudah mapan merupakan keunggulan besar. Agen umumnya melibatkan transaksi dengan layanan eksternal yang lambat, dan untuk pekerjaan seperti ini pola konkurensi Go sangat berguna. Tentu saja bahasanya sendiri bukan faktor yang terlalu penting, dan JavaScript tampaknya paling banyak digunakan. Namun, untuk code generation, rasanya ada sinergi yang bagus antara Go dan LLM
Go berbeda dari Python dalam hal kemampuan menangani konkurensi yang sangat baik dan kemudahan deployment. Go cukup mendistribusikan static binary, sehingga bebas dari masalah environment dan dependency seperti di Python
Agen berperan sebagai lapisan orkestrasi, dan menurut saya Go, Erlang, serta Node sangat cocok untuk itu. Tidak harus punya banyak library AI; pekerjaan yang heavy pada IO bisa diabstraksikan di balik tool interface per domain, lalu subsistemnya dibuat dengan bahasa yang diperlukan
Go cenderung tidak memberi banyak keuntungan untuk workload seperti ini karena sebagian besar waktu habis menunggu IO. Sistem tipe Go terbatas, dan banyak fitur yang tersedia secara bawaan di bahasa modern harus diakali di Go. TypeScript adalah bahasa glue yang sangat baik untuk AI, dan bersama Python dukungan library-nya sangat bagus. Alasan saya lebih memilih TypeScript daripada Python adalah karena sistem tipenya jauh lebih kuat dan matang. Python juga berkembang cepat. Klaim bahwa menghentikan pekerjaan long-running di Node.js dan Python itu sangat sulit menurut saya tidak punya dasar yang kuat. Sebagian besar tool sudah mendukung fitur ini, dan bahasa utamanya tetap Python dan JS
Saya sudah bereksperimen dengan framework agen berbasis Elixir dan BEAM, dan menurut saya kombinasi BEAM dan SQLite saat ini adalah yang paling ideal untuk agen. Agen bisa diganti dengan aman tanpa redeploy aplikasi, dan konkurensi BEAM punya ruang lebih dari cukup untuk pekerjaan ini. Implementasi agen berbasis state maupun agen sementara juga sangat mudah. Ke depannya saya berencana membangun base agent dengan Python, Typescript, dan Rust, lalu juga membuat server MCP agar pengembangan agen kompleks bisa dilakukan sesuai preferensi bahasa masing-masing
Saya merekomendasikan proyek Extism dan Elixir SDK. Dengan kombinasi ini, kita bisa membangun core service, routing, dan message passing di Elixir sambil memanfaatkan keunggulan BEAM/OTP, lalu juga menyematkan agen dalam bentuk modul Wasm kecil dan ringan yang ditulis dalam bahasa lain layaknya plugin
Extism
Elixir SDK
Saya penasaran apakah ada alasan khusus memilih SQLite alih-alih mnesia, data store bawaan BEAM
mnesia docs
Sebagian besar waktu agen digunakan untuk menunggu respons LLM dan memanggil layanan eksternal (API, DB). Dampak performa runtime bahasa pada praktiknya hampir tidak ada. Jika ada fitur bahasa yang benar-benar penting untuk performa dan skalabilitas agen, itu kemungkinan adalah performa serialisasi dan deserialisasi JSON
Karena itu, saya pikir lebih baik memakai bahasa seperti TypeScript yang menangani JSON secara native. Sistem tipe TypeScript juga jauh lebih kuat daripada Go
Dari pengalaman saya, selain pemanggilan LLM, hal paling mahal di agen adalah penyelesaian konflik pada pengeditan asinkron (
merge,diff,patch). Pekerjaan ini memang bisa didelegasikan ke library level rendah, tetapi sama seperti serialisasi, ini juga masalah yang sulit dioptimalkanIni mengingatkan saya pada panduan membangun agen dari ampcode.com. Berkat sifatnya sebagai bahasa dinamis, Python terasa alami untuk penggunaan seperti mengubah method langsung menjadi pemanggilan tool dengan decorator, menghasilkan list lewat iterasi fungsi tool, atau cepat mengonversinya ke skema JSON. Sebaliknya, struktur yang memicu eksekusi agen baru dari berbagai trigger eksternal (misalnya input pengguna, email Gmail, pesan Slack, dan sebagainya) terasa jauh lebih intuitif di Go dengan pemanfaatan channel dan
switch for loop. Di Python, kita harus membuat banyak queue dan threading secara terpisah sehingga lebih rumitJika mengikuti logika artikel, maka Elixir adalah bahasa yang ideal untuk agen
Sistem tipe Go yang terbatas dan kurang memadai tidak cocok untuk hampir semua aplikasi. Bahkan, kelemahan terbesar Go menurut saya adalah bahasanya sendiri. Justru faktor-faktor di luar bahasa itulah yang membuat Go masih bisa ditoleransi
Saya sudah memprogram dengan Go selama beberapa tahun, dan setuju bahwa masalah sistem tipenya cukup banyak. Orang-orang di ranah LLM tampaknya hampir semuanya hanya memakai Python atau JavaScript. Saya rasa semua orang seharusnya beralih ke bahasa modern, tetapi Go mungkin tetap pilihan yang lumayan dibanding kekacauan import dan paket di Python/JavaScript
Saya ingin mendengar lebih spesifik bagaimana keterbatasan sistem tipe Go menjadi hambatan dalam pembuatan agen
Kenyataannya, Go diberi sistem tipe statis karena tidak menemukan cara lain untuk mencapai kebutuhan performa. Dalam praktiknya lebih tepat dianggap digunakan seperti bahasa dengan dynamic typing, dan hasil ini muncul dari kesalahpahaman terhadap tujuan desain bahasanya. Orang bisa saja berargumen bahwa bahasa dengan dynamic typing secara umum tidak cocok, tetapi fakta bahwa Python, Erlang, Elixir, dan bahasa dynamic typing lain dipakai secara aktif justru menunjukkan bahwa dynamic typing lebih sesuai dengan domain masalah ini
Multiple return value tidak bisa dikomposisikan, dukungan error memang lebih baik daripada exception tetapi sangat verbose, channel mudah disalahgunakan, dan tipe enum terasa mengecewakan. Meski begitu, interface ternyata bekerja cukup baik, dan sistem packaging juga cukup mulus. Saat belajar Rust, saya menyadari bahwa file structure-nya jauh lebih kompleks daripada Go. Bahkan karena bahasanya sederhana, membuat berbagai linter dan alat code generation juga lebih mudah. Untuk maintenance jangka panjang, kode Go terasa lebih tidak mengkhawatirkan dibanding Python/JS
Akan sangat bagus jika ada dialek LISP/Scheme yang terawat baik dan bisa dikompilasi ke Go
Pada proses yang berjalan lama dan mahal untuk dieksekusi, ada kelemahan bahwa jika proses mati maka semua pekerjaan hilang. Bisa jadi lebih aman untuk menserialisasi state ke database selama masa tunggu, tetapi tampaknya belum ada bahasa yang membuat ini mudah. Menulis state machine berbasis checkpoint itu tidak sederhana
Menjelaskan bahwa state machine berbasis checkpoint adalah fitur inti yang disediakan platform seperti Hatchet(hatchet.run) dan Temporal(temporal.io). Riwayat eksekusi fungsi di dalam workflow disimpan, lalu saat terjadi interupsi riwayat itu otomatis diputar ulang. Ia berargumen bahwa riwayat progres per output jauh lebih efisien daripada sinkronisasi memori. (Pendiri Hatchet)
Goroutine, thread, maupun rantai eksekusi jangka panjang pada akhirnya harus dipecah menjadi unit kerja yang atomic, dan serialisasi state itu wajib. Ini diperlukan untuk memenuhi kebutuhan pemulihan kegagalan, pelacakan error, referensi ulang hasil, distribusi multi-node, dan sebagainya. Framework Oban(github.com/oban-bg/oban) di Elixir memakai pendekatan ini, dan saya juga merekomendasikan artikel Oban yang menekankan pentingnya persistensi pekerjaan asinkron. (Penulis Oban)
Saya sedang mengembangkan library agen berbasis golang, dan rasanya jika logging-nya cukup lengkap maka state agen bisa dipulihkan kapan saja. Selama tahu timestamp dan run induk, kita bisa menyusun tree eksekusi anak/cabang. Session dikelola dengan kombinasi map dan DB, lalu dapat dibangun ulang bila perlu. Struktur ini tidak menyimpan object individual; object stateless dicari dari map berdasarkan id, sementara action sebelumnya, step, dan context disimpan di object state. Konsistensi agen/workflow juga diatasi dengan mengelola hasil memakai hash. Untuk sekarang saya baru mengimplementasikan agen/tool dasar, dan logging, pemulihan, serta logika pembatalan masih belum dibuat
Temporal cukup berguna untuk checkpointing proses jangka panjang, dan juga netral terhadap bahasa
Saya juga sempat memikirkan job queue, dan sedang mempertimbangkan membuat queue sederhana di Postgres. Keuntungannya adalah distribusi workload antarserver, mencegah task hilang saat proses mati, dan visibilitas yang lebih baik. Namun, kompleksitas kode bisa meningkat besar sehingga terasa sulit merancang arsitektur yang tetap sederhana
Para engineer AI sangat enggan memakai JavaScript. Dihentikannya TensorFlow for Swift adalah akhir dari keberagaman bahasa di AI
Saya rasa keengganan terhadap JavaScript bukan hanya terjadi pada engineer AI. Dari sudut pandang seseorang yang sudah menulis JS lebih dari 30 tahun, saya setuju
JS sebagai bahasa sangat buruk, dan membawanya ke backend menurut saya adalah kesalahan. TypeScript pada akhirnya juga tidak menyelesaikan masalah mendasar JS di bawahnya. Saya berusaha menghindari JS maupun TS, dan lebih memilih alternatif lain seperti Go, Rust, Python, Ruby, Elixir, atau F#
Saya penasaran apa yang membuat JS terasa sangat cocok untuk agen
Saya merasa bidang ML membutuhkan model konkurensi yang lebih baik. Saya pernah mencoba ML dengan Go, tetapi karena minimnya dukungan library dan harus bergantung pada pemanggilan gRPC eksternal atau wrapper, praktiknya jadi hampir mustahil. Python punya keterbatasan, dan C++ terlalu verbose sehingga banyak mengurangi produktivitas