Menjalankan Hermes Agent sebagai Coder Otonom di VPS

Empat hal: identitas untuk melakukan commit dengan token bercakupan sempit, ruang kerja miliknya sendiri yang direset sebelum setiap run, jadwal tetap yang dipilih mengikuti reset kuota penyedia model, dan cara berhenti — batas giliran, batas jam dinding, dan watchdog. Mode kegagalan agen tanpa pengawasan bukan crash, melainkan berjalan selamanya.
Karena itu mengubah isolasi container menjadi akses root di host. Agen yang menjalankan perintah shell dari keluaran model adalah beban kerja tidak tepercaya yang punya akses sah, jadi ia sebaiknya mendapat sistem berkas, jaringan, dan batas memori — dan tidak mendapat apa pun yang memungkinkannya menjangkau host. Kalau ia harus membangun image, beri builder rootless di dalam container-nya sendiri.
Banyak runtime agen menyanitasi environment yang diserahkan ke subproses shell, membuang variabel yang namanya tampak seperti rahasia. Itu perilaku yang benar untuk perkakas yang menjalankan perintah karangan model, tetapi membuat autentikasi lewat variabel lingkungan tidak terlihat oleh agen. Persistensikan kredensial ke disk saat boot dengan izin ketat, lalu verifikasi dengan variabelnya dihapus secara eksplisit.
Tepat setelah reset kuota harian penyedia, yang biasanya berupa waktu UTC tetap. Run yang mulai saat itu mendapat jatah penuh; run yang sama pada malam hari mendapat sisanya. Beri jarak antar pekerjaan berat juga, karena dua pekerjaan berat di jendela yang sama akan saling men-rate-limit lebih efektif daripada beban eksternal mana pun.
Batas keras jam dinding per run agar pekerjaan yang menggantung tidak memblokir penjadwal, langkah clean-start yang mereset ruang kerja dan menghapus berkas tak terlacak, watchdog tanpa akses model yang menuai proses macet serta memangkas disk, dan peringatan yang terpisah agar laporan rutin dan kegagalan nyata tidak tiba di kanal yang sama.

Ringkasan Utama
Menjalankan agen coding tanpa pengawasan di VPS kecil membutuhkan empat hal: container terkunci tanpa Docker socket, kredensial yang dipersistensikan ke disk alih-alih variabel lingkungan, cron yang dijadwalkan mengikuti reset kuota penyedia model, dan watchdog yang menuai run macet sebelum disk penuh.
Pada Juli saya menaruh sebuah agen coding open-source di VPS dua gigabyte dan memberinya tugas: setiap pagi, perbaiki salah satu pustaka saya, buka pull request, dan merge kalau tesnya lolos. Ia berjalan sejak saat itu, dan bagian yang menarik sama sekali bukan modelnya. Yang menarik adalah semua yang mengelilinginya — container, kredensial, jadwal, dan penanganan kegagalan.
Ini separuh infrastruktur dari proyek itu, ditulis sebagai catatan yang saya harap saya punya di hari pertama. Nama-namanya generik karena bentuk yang sama berlaku untuk runtime agen mana pun yang mungkin Anda jalankan seperti ini.
Agen yang Anda awasi butuh terminal. Agen yang tidak Anda awasi butuh empat hal yang akan Anda berikan kepada rekan kerja junior, dan semuanya urusan infrastruktur, bukan prompt.
Tiga dari empat hal itu adalah yang mula-mula saya salah lakukan lalu perbaiki belakangan, dan karena itulah mereka mendapat porsi terbesar di bawah ini.

Pengerasannya biasa saja dan tetap layak dilakukan, karena agen yang menjalankan perintah shell dari keluaran model adalah definisi beban kerja tidak tepercaya yang punya akses sah.
# docker-compose.yml — the hardening that costs nothing and matters
services:
agent:
image: agent:local
container_name: agent
env_file: .env # chmod 600, never committed
cap_drop: [ALL] # no capabilities at all
security_opt: [no-new-privileges:true]
mem_limit: 1g # a 2 GB box cannot afford a runaway
read_only: false # the workspace needs writes; the host does not
user: "1000:1000" # never root
volumes:
- agent-state:/home/agent/state # one volume, all persistence
networks: [agent-net] # its own network
# deliberately absent: /var/run/docker.sock
volumes: { agent-state: }
networks: { agent-net: }Dua pilihan layak disebut. Batas memori bukan opsional di mesin kecil: tanpanya, satu build yang lepas kendali menjatuhkan seluruh mesin, termasuk apa pun yang Anda inangi di sana. Dan semua persistensinya masuk ke satu volume bernama, artinya rebuild menjadi aman dan pemulihan cukup satu penyalinan volume alih-alih penggalian arkeologis.
Jangan pernah memasang Docker socket host ke dalam container agen. Itu satu-satunya pemberian yang mengubah isolasi container menjadi akses root di host, dan instruksi tingkat prompt sebanyak apa pun tidak menggantikannya. Kalau agen memang perlu membangun image, beri ia builder rootless di dalam container-nya sendiri.
Kegagalan paling membingungkan sepanjang proyek: agen tidak bisa push ke GitHub, sementara perintah yang persis sama dijalankan tangan di dalam container yang sama berjalan mulus. Bukan masalah token, bukan masalah jaringan — tokennya valid dan jaringannya baik-baik saja.
# The failure that cost me two days: the agent could not push, while an
# identical command run by hand worked perfectly.
#
# Cause: the runtime sanitises its subprocess environment and strips
# variables matching *_TOKEN and *_API_KEY before handing the shell to
# the agent. Environment-variable auth is therefore invisible to it.
# Fix: persist credentials to DISK at boot, not to the environment.
git config --global credential.helper store
printf 'https://%s:[email protected]\n' "$GITHUB_TOKEN" \
> ~/.git-credentials && chmod 600 ~/.git-credentials
mkdir -p ~/.config/gh && cat > ~/.config/gh/hosts.yml <<YAML
github.com:
oauth_token: $GITHUB_TOKEN
git_protocol: https
YAML
chmod 600 ~/.config/gh/hosts.yml
# Verified the right way: unset the variable, then try.
env -u GITHUB_TOKEN gh auth status && env -u GITHUB_TOKEN git pushPenyebabnya adalah sebuah fitur keamanan. Runtime menyanitasi environment yang ia serahkan ke subproses shell, membuang variabel yang namanya tampak seperti rahasia, dan itu justru tepat untuk perkakas yang menjalankan perintah karangan model. Konsekuensinya, autentikasi lewat variabel lingkungan tidak terlihat oleh agen meski terlihat oleh Anda. Perbaikannya adalah mempersistensikan kredensial ke disk saat boot, dengan izin ketat, agar perkakasnya menemukannya tanpa perlu environment. Jebakan yang sama menggigit saya kedua kalinya lewat kunci penyedia model, dan perbaikan yang sama berlaku.
Uji perbaikan kredensial dengan menghapus variabelnya secara eksplisit lebih dulu. Menjalankan perintah dengan variabel lingkungan masih ada tidak membuktikan apa pun, karena itulah jalur yang memang sudah bekerja; menghapusnyalah yang membuktikan kredensial di disk benar-benar bekerja.
Dengan tingkatan model gratis atau murah, jadwal adalah keputusan anggaran. Kuota harian biasanya direset pada waktu UTC tetap, dan pekerjaan yang berjalan tepat setelah reset itu mendapat jatah penuh, sementara pekerjaan yang sama pada malam hari mendapat sisanya.
| Pekerjaan | Irama | Kenapa slot itu |
|---|---|---|
| Run perbaikan utama | Harian, sesaat setelah reset kuota | Pekerjaan termahal mendapat anggaran paling segar dan persaingan paling sedikit |
| Run perbaikan kedua | Harian, awal sore | Berangkat dari branch main yang sudah dimajukan run pagi, jadi tidak menduplikasi pekerjaan |
| Watchdog | Tiap beberapa jam, tanpa melibatkan model | Menuai proses macet dan memangkas disk sebelum keduanya menjadi gangguan |
| Laporan harian | Malam hari | Merangkum commit dan merge hari itu, dan hanya inilah yang rutin saya baca |
Laporannya lebih penting daripada kedengarannya. Agen tanpa pengawasan yang tidak punya ringkasan harian adalah sistem yang akan berhenti Anda percayai dalam seminggu, karena Anda tidak punya bukti ia mengerjakan apa pun. Satu surel per malam berisi jumlah commit dan pull request yang ter-merge adalah pembeda antara eksperimen dan rekan kerja.

Agen tanpa pengawasan gagal dengan cara yang tak pernah dialami agen interaktif, karena tak seorang pun menekan escape. Empat mekanisme menutup hampir semuanya.
Langkah clean-start adalah yang pertama akan saya tambahkan di pembangunan ulang mana pun. Satu berkas tes tak terlacak yang ditinggalkan run yang crash membuat hasil tiga hari berturut-turut terlihat seperti regresi, padahal kodenya baik-baik saja sepanjang waktu.
Lima langkah, dan dua yang pertama justru paling sering dilewati.
Kalau installer Anda menarik versi terbaru agen saat build alih-alih versi yang dipatok, tambahkan argumen build pemecah cache yang Anda naikkan secara sengaja. Kalau tidak, versi Anda adalah apa pun yang kebetulan terbaru saat perubahan tak berhubungan memaksa rebuild terakhir — dan itu bukan sifat yang Anda inginkan pada sesuatu yang me-merge kodenya sendiri.
Agen coding otonom di VPS kecil adalah sembilan puluh persen rekayasa operasi biasa dan sepuluh persen konfigurasi model. Kurung dengan benar, beri kredensial yang benar-benar bisa ia pakai, jadwalkan mengikuti kuota yang ia andalkan, dan awasi dengan sesuatu yang lebih bodoh darinya — maka ia menjadi kontributor harian yang sungguh berguna, bukan demo yang sekali berhasil.