SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor

Cara Mengontrol Biaya Agen AI di VPS Agar Tidak Boros

Agen AI yang berjalan otomatis dapat menghabiskan saldo API dengan cepat. Pelajari cara menerapkan hard cap, prompt caching, dan pembatasan loop untuk mencegah tagihan membengkak.

Cara menjaga agen AI yang selalu aktif agar tidak membengkak tagihannya

Pengendalian biaya agen AI pada VPS (virtual private server) bergantung pada batasan yang Anda tetapkan sebelum agen dijalankan, karena tidak ada yang memantau penggunaan secara real-time saat agen beroperasi. Batasi setiap respons dengan max_tokens, batasi iterasi loop dalam kode Anda sendiri, lakukan caching pada bagian prompt yang tidak pernah berubah, dan catat angka penggunaan setiap respons untuk mengetahui pekerjaan mana yang memakan biaya. Biaya sewa server bersifat tetap setiap bulan. API model dihitung berdasarkan token, dan loop yang tidak diawasi sangat efektif dalam menghabiskan token secara diam-diam.

Panduan ini mengasumsikan agen sudah ada dan memanggil Messages API dari server milik Anda. Membangun agen AI dengan Claude di VPS membahas mekanisme teknisnya.

Mengapa agen unattended memiliki struktur biaya yang berbeda

Sesi interaktif melibatkan manusia di dalamnya. Saat model mengambil langkah yang salah atau membaca log sepanjang 40.000 baris, orang yang mengawasinya akan menghentikannya. Agen unattended tidak memiliki rem seperti itu: ia berjalan hingga loop berakhir, lalu timer akan menjalankannya kembali.

Frekuensi adalah pengali yang sering dilewatkan orang. Pekerjaan dengan jadwal lima menit berjalan 288 kali sehari dan sekitar 8.640 kali sebulan. Berapapun biaya satu kali eksekusi, itulah angka yang harus Anda kalikan. Banyak agen "always-on" sebenarnya tidak perlu terus menyala. Mereka hanya perlu merespons dalam hitungan menit tertentu, yang berarti itu adalah sebuah jadwal.

Agen juga membayar hal-hal yang tidak dibayar oleh jendela chat.

  • Definisi tool disertakan dalam setiap request. Prompt sistem untuk penggunaan tool memakan 290 token pada Claude Opus 4.8 dengan tool_choice dari auto atau none, dan 410 dengan any atau tool. Tool bash menambah 325 token lagi. Setiap MCP server yang Anda lampirkan menambahkan skemanya ke beban tersebut, di mana MCP adalah model context protocol.
  • Hasil tool adalah input token. Perintah yang mencetak 8.000 baris akan memasukkan 8.000 baris tersebut ke dalam request berikutnya, dan ke dalam setiap request setelahnya dalam giliran tersebut.
  • Halaman yang diambil adalah input token. Halaman web rata-rata 10 kB kira-kira setara dengan 2.500 token dan PDF riset 500 kB kira-kira 125.000 token. max_content_tokens hanya memotong konten teks, karena fitur ini "berlaku untuk konten teks, bukan untuk konten biner seperti PDF". Batasi PDF dengan max_uses dan allowed_domains sebagai gantinya.
  • Pencarian web dikenakan biaya per pencarian, sebesar $10 per 1.000 pencarian, berapapun jumlah hasil yang muncul. Pencarian yang error tidak akan ditagihkan.

Semua itu tidak mahal jika dilakukan sekali. Semuanya menjadi mahal jika dilakukan 8.640 kali.

Batas maksimum absolut dan batas maksimum lunak menyelesaikan masalah yang berbeda

max_tokens diberlakukan. Ini adalah batas maksimum absolut untuk total output satu permintaan, yang mencakup proses berpikir dan teks respons. Claude tidak pernah menghasilkan output yang melewati batas ini, dan model tidak dapat melihat nilainya. Jika batas ini tercapai, sistem mengembalikan stop_reason: "max_tokens" dan respons yang terpotong. Hal yang perlu diperhatikan untuk agent: setiap permintaan dalam loop penggunaan tool memiliki max_tokens masing-masing. Jadi, batas ini berlaku untuk satu respons, bukan keseluruhan tugas. Sepuluh pemanggilan tool dengan batas 4,000 menghasilkan batas maksimum 40,000 token untuk satu giliran.

Anggaran tugas bersifat anjuran. task_budget berada di dalam output_config dan memberi tahu model jumlah token yang tersedia untuk seluruh loop agentic, termasuk proses berpikir, pemanggilan tool, hasil tool, dan output.

resp = client.beta.messages.create(
    model="claude-opus-4-8",
    max_tokens=4096,
    betas=["task-budgets-2026-03-13"],
    output_config={"task_budget": {"type": "tokens", "total": 64000}},
    messages=messages,
)

"Anggaran tugas adalah petunjuk lunak, bukan batas maksimum absolut." Claude dapat melampaui anggaran tersebut di tengah tindakan, sedangkan batas output yang diberlakukan tetap max_tokens. "Hitung mundur hanya terlihat oleh model", dan respons tidak menyertakan kolom sisa anggaran. Nilai minimum task_budget.total yang diterima adalah 20,000 token; nilai yang lebih kecil menghasilkan error 400. Anggaran yang terlalu kecil untuk pekerjaan tersebut dapat menyebabkan perilaku seperti penolakan. Model kemudian mempersempit cakupan tugas atau berhenti lebih awal.

Ada satu detail yang menambah biaya, bukan menghematnya. Jika client Anda mengurangi task_budget.remaining pada setiap permintaan lanjutan, nilai yang berubah akan membatalkan prefix cache yang memuatnya. Tetapkan nilai tersebut satu kali, pada permintaan pertama.

Anggaran tugas masih berstatus beta pada Claude Fable 5.1, Claude Fable 5, Claude Opus 5.5, Claude Opus 5, Claude Opus 4.8, Claude Opus 4.7, Claude Sonnet 5.5, dan Claude Haiku 5.5. Claude Sonnet 5 dan Claude Haiku 4.5 tercantum sebagai Not supported, dan anggaran tugas tidak berlaku untuk Claude Code. Karena itu, sesi Claude Code yang dipisahkan di tmux bergantung pada pengelolaan sesi yang baik.

Batas maksimum ketiga terdapat di Claude Console. Berikan workspace khusus kepada agent, lalu tetapkan batas pengeluaran bulanan dan batas laju per menit untuk workspace tersebut. "Anda tidak dapat menetapkan batas pada Default Workspace", dan "Batas tingkat organisasi selalu berlaku, meskipun total batas workspace melebihi batas tersebut". Tambahkan notifikasi pengeluaran agar Anda menerima peringatan saat ambang batas tercapai, sebelum batas maksimum terlampaui.

Pemilihan model per tugas dan dampak nyata dari effort

Pemilihan model ditentukan untuk setiap tugas. Per Oktober 2026, tarif per juta token, masing-masing untuk input dan output, adalah: Claude Fable 5.1 dan Fable 5 sebesar $10 dan $50, Claude Opus 5.5 sebesar $4 dan $20, Claude Opus 5, Opus 4.8, dan Opus 4.7 sebesar $5 dan $25, Claude Sonnet 5.5 dan Sonnet 5 sebesar $2 dan $10, Claude Haiku 5.5 sebesar $0.10 dan $0.50 untuk prompt hingga 100,000 token ($0.50 dan $2.50 di atas jumlah tersebut; token yang di-cache tetap dihitung), serta Claude Haiku 4.5 sebesar $1 dan $5. Anthropic awalnya menjual Sonnet 5 dengan tarif tersebut sebagai harga perkenalan, lalu menjadikannya tarif standar dan membatalkan rencana kenaikan menjadi $3 dan $15. Langkah yang hanya mengklasifikasikan baris log tidak memerlukan Opus.

Jangan mengandalkan penggunaan gratis untuk menanggung jadwal yang padat. Selain kredit kecil yang diberikan Claude API saat pendaftaran, satu-satunya alokasi berulang adalah kredit API bulanan yang termasuk dalam paket Claude Max dan Team: $100 pada Max 5x, $200 pada Max 20x, dan hingga $500 yang digunakan bersama pada Team. Kredit tersebut diperbarui setiap siklus penagihan. Anda dapat mengklaimnya setelah 7 hari menggunakan paket yang memenuhi syarat, dan metode pembayaran tidak diperlukan. Kredit ini mencakup Claude API, Managed Agents, Agent SDK, dan playground, tetapi tidak mencakup Claude Code. Kredit berakhir pada akhir setiap siklus dan tidak dibawa ke siklus berikutnya. Penggunaannya dihitung dalam batas pengeluaran. Setelah kredit habis, permintaan akan dihentikan kecuali organisasi juga memiliki kredit yang dibeli.

Effort adalah pengungkit kedua. output_config.effort menerima low, medium, high, xhigh, dan max, tetapi tidak semua model mendukung setiap tingkat. Nilai default pada sebagian besar model adalah high, sedangkan pada Claude Opus 5.5 dan Claude Haiku 5.5 adalah medium. Menetapkan default model secara eksplisit sama dengan tidak menetapkannya. Effort yang lebih rendah mengurangi lebih dari sekadar panjang penalaran. Dokumentasi menyatakan bahwa Claude akan melakukan lebih sedikit tool call dan menggabungkan beberapa operasi menjadi lebih sedikit panggilan. Pada agent, penghematan ini lebih besar karena tool call yang dihindari berarti satu permintaan penuh tidak pernah dijalankan.

Perangkapnya adalah effort dapat mengganggu cache. Mengubah nilai tingkat atas antarpemintaan akan membatalkan prompt caching. Dalam contoh yang didokumentasikan pada Claude Opus 5.5, permintaan 2 melaporkan cache_read_input_tokens: 3546. Permintaan 3 mengubah effort dari medium, yaitu default model tersebut, menjadi low, lalu melaporkan cache_creation_input_tokens dari 3546 dan cache_read_input_tokens dari 0. Karena itu, ubah effort tingkat atas antar-workload, bukan di dalam satu percakapan yang di-cache. Ada 2 cara untuk mengubah kedalaman tanpa merusak cache. Pada Claude Fable 5.1, Opus 5.5, Opus 5, Sonnet 5.5, dan Haiku 5.5, perubahan effort per pesan (beta, header mid-conversation-output-config-2026-07-01) menetapkan tingkat baru dan membiarkan prefix yang di-cache tetap utuh. Pada model apa pun, Anda juga dapat mengarahkannya melalui prompt. Misalnya, baris seperti "Answer directly without deliberating." pada pesan pengguna terbaru tidak mengubah breakpoint sebelumnya. Namun, pada Claude Haiku 5.5, frasa tersebut tidak selalu mengurangi proses berpikir.

Token thinking ditagihkan dengan tarif output dan dihitung terhadap max_tokens. Karena itu, jawaban yang terpotong sering kali berarti anggarannya habis untuk thinking. Baca usage.output_tokens_details.thinking_tokens untuk melihat jumlahnya. Bagian yang sebenarnya mengisi tagihan token Claude menguraikan cara penghitungannya.

Simpan prefix yang stabil dan jangan merusaknya secara tidak sengaja

Penulisan cache memerlukan biaya sebesar 1.25 kali harga input dasar pada cache lima menit dan 2 kali pada cache satu jam. Pada sebagian besar model, pembacaan cache memerlukan biaya sebesar 0.1 kali. Jadi, "caching mulai menguntungkan setelah satu pembacaan cache untuk durasi 5 menit (penulisan 1.25x), atau setelah dua pembacaan cache untuk durasi 1 jam (penulisan 2x)". Biaya pembacaan bahkan lebih rendah pada model terbaru: 0.05 kali pada Claude Opus 5.5 dan Claude Sonnet 5.5, serta 0.025 kali pada Claude Fable 5.1.

Satu baris menjelaskan alasan fitur ini sesuai untuk agent yang selalu aktif: "Cache diperbarui tanpa biaya tambahan setiap kali konten yang disimpan dalam cache digunakan." Job yang berjalan setiap dua menit menggunakan cache lima menit akan mempertahankan prefix tetap aktif sepanjang hari dengan satu penulisan.

Berikut tiga cara cache dapat hilang tanpa Anda sadari.

Prefix yang berubah. "Prefix cache dibuat dalam urutan berikut: tools, system, lalu messages." Perubahan satu byte pun pada bagian yang lebih awal dalam urutan tersebut akan membatalkan semua bagian setelahnya, dan pengeditan definisi tool akan membatalkan seluruh cache. Kesalahan yang sering terjadi adalah menambahkan timestamp atau run id ke system prompt. Akibatnya, setiap request membawa prefix yang berbeda, menulis entri baru dengan biaya 1.25x, dan tidak membaca entri cache apa pun. Indikasinya adalah usage.cache_read_input_tokens tetap 0 pada panggilan yang tampak identik. Pindahkan teks yang berubah-ubah ke user message terbaru.

Prefix yang terlalu pendek. Setiap model memiliki panjang minimum yang dapat disimpan dalam cache. Jika lebih pendek dari batas ini, request diproses tanpa caching dan "tidak ada error yang dikembalikan". Nilainya adalah 512 token pada Claude Fable 5.1, Fable 5, Opus 5.5, Opus 5, Sonnet 5.5, dan Haiku 5.5; 1,024 pada Claude Opus 4.8 dan Claude Sonnet 5; serta 4,096 pada Claude Haiku 4.5. Jadi, memindahkan job dari Sonnet 5 ke Haiku 4.5 dapat menonaktifkan caching secara diam-diam.

Percakapan yang melebihi lookback. "Jendela lookback terdiri atas 20 blok." Sistem memeriksa paling banyak 20 posisi untuk setiap breakpoint, lalu berhenti. Dalam contoh yang didokumentasikan, sebuah turn yang berisi 35 blok dengan breakpoint pada blok 35 akan memeriksa blok 35 hingga 16. Entri dari turn sebelumnya pada blok 15 berada di luar jendela, sehingga tidak terjadi cache hit. Agent yang menambahkan beberapa blok tool-use dan tool-result pada setiap turn akan melewati batas 20 dalam dua atau tiga turn. Anda mendapatkan empat breakpoint per request, jadi gunakan salah satunya untuk pesan terbaru.

Kirimkan tugas yang tidak mendesak ke Batches API

"Semua penggunaan dikenakan biaya sebesar 50% dari harga API standar", baik untuk input maupun output. Pemrosesan batch bersifat asinkron, "dengan sebagian besar batch selesai dalam waktu kurang dari 1 jam", dan hasilnya tersedia setelah setiap permintaan selesai atau setelah 24 jam, mana saja yang lebih dulu. Ini adalah kondisi umum, bukan jaminan.

Lakukan polling pada processing_status sampai statusnya terbaca ended. Permintaan yang mengembalikan errored, canceled, atau expired tidak akan ditagihkan. Satu peringatan jika Anda mengandalkan batas pengeluaran (spend cap): "batch mungkin sedikit melebihi batas pengeluaran yang dikonfigurasi pada Workspace Anda."

Diskon ini bersifat akumulatif, dan karena sebuah batch dapat memakan waktu lebih dari lima menit, dokumentasi menyarankan penggunaan cache satu jam untuk batch yang berbagi konteks. Oleh karena itu, bagi pekerjaan Anda: tugas yang ditunggu oleh pengguna atau webhook tetap berada di jalur langsung (live path), sedangkan ringkasan harian atau klasifikasi log hari kemarin dapat dimasukkan ke dalam batch dengan harga setengahnya.

Catat semua kolom penggunaan dari setiap respons ke penyimpanan Anda sendiri

Anda tidak dapat mengatribusikan biaya yang tidak pernah Anda catat. Setiap respons memberi tahu biaya yang ditimbulkannya.

u = resp.usage
row = {
    "job": job_name,
    "model": resp.model,
    "uncached_input": u.input_tokens,
    "cache_write": u.cache_creation_input_tokens,
    "cache_read": u.cache_read_input_tokens,
    "output": u.output_tokens,
    "stop_reason": resp.stop_reason,
}

Tambahkan satu baris untuk setiap pemanggilan API ke file JSON-lines, lalu beri tag dengan nama job Anda. Seminggu kemudian, Anda dapat mengetahui job mana yang benar-benar menghabiskan biaya dan mana yang hanya tampak sibuk. Perhatikan cache_read: kolom yang seluruhnya berisi angka nol merupakan bug biaya yang paling umum pada agent yang di-host sendiri.

Satu kolom mudah disalahartikan. input_tokens hanya menghitung token setelah breakpoint cache terakhir, sehingga ukuran prompt sebenarnya adalah total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. Agent yang melaporkan input_tokens: 400 untuk prompt besar bukan berarti hemat biaya: token lainnya berasal dari cache.

Hitung sebelum mengirim. Penghitungan token tidak dikenai biaya dan batas lajunya terpisah dari pembuatan pesan, jadi gunakan count_tokens untuk menolak lampiran yang terlalu besar, alih-alih membayar untuk mengetahuinya. Hasilnya merupakan perkiraan, jadi ukur ulang untuk setiap model dan jangan pernah menggunakan kembali hasil penghitungan dari tokenizer milik vendor lain. Model Claude 4.7 dan yang lebih baru, termasuk Claude Fable 5 dan Claude Sonnet 5, menggunakan tokenizer yang lebih baru dan "menghasilkan sekitar 30% lebih banyak token untuk teks yang sama". Claude Sonnet 4.6 dan yang lebih lama, termasuk Claude Haiku 4.5, menggunakan tokenizer sebelumnya.

Untuk mendapatkan tampilan otoritatif, Admin API melaporkan penggunaan di https://api.anthropic.com/v1/organizations/usage_report/messages dan biaya di https://api.anthropic.com/v1/organizations/cost_report. Keduanya menerima admin key (sk-ant-admin01-...) sebagai x-api-key: $ANTHROPIC_ADMIN_KEY dengan anthropic-version: 2023-06-01. Laporan penggunaan menerima bucket_width=1d, group_by[]=model, dan api_key_ids[]=. Laporan biaya hanya tersedia secara harian dan mengelompokkan data berdasarkan workspace_id atau description. Satu batasan: "Admin API tidak tersedia untuk akun individual."

Parameter api_key_ids[] tersebut merupakan cara praktis dan murah untuk melakukan atribusi: berikan setiap job API key sendiri, filter laporan penggunaan dengan api_key_ids[], lalu pisahkan hasilnya per key dengan group_by[]=api_key_id. Filter tersebut berbentuk jamak, sedangkan dimensi pengelompokan berbentuk tunggal. Simpan key di environment, bukan di kode, seperti yang dilakukan aplikasi Claude API pertama pada VPS untuk menanganinya.

Batasi loop, karena tidak ada yang akan melakukannya

Jumlah iterasi yang dibatasi bersifat wajib di sini. Loop tersebut milik Anda, jadi penghitungnya juga milik Anda:

for step in range(MAX_STEPS):          # MAX_STEPS = 12, never "while True"
    resp = client.messages.create(...)
    if resp.stop_reason != "tool_use":
        break
else:
    log.warning("job %s hit MAX_STEPS=%d, giving up", job_name, MAX_STEPS)

Kedua batas di atas tidak melakukannya untuk Anda: max_tokens membatasi satu respons, sedangkan model hanya diberi tahu tentang anggaran tugas. Produk terkelola akan menghentikan proses pada titik ini, seperti batas Claude untuk pemanggilan tool dalam satu giliran yang menghentikan sesi setelah terlalu banyak pemanggilan, tetapi loop yang Anda tulis sendiri tidak memiliki pengaman seperti itu sampai Anda menambahkannya.

Tambahkan rem kedua di luar proses. Jalankan job dari systemd timer, bukan sebagai proses permanen, lalu berikan batas waktu wall-clock pada service unit-nya. Job timer biasanya Type=oneshot, dan RuntimeMaxSec= "does not have any effect on Type=oneshot services", jadi tetapkan TimeoutStartSec=600 di sana. Gunakan RuntimeMaxSec=600 hanya pada unit Type=simple. Dengan cara apa pun, run yang macet akan dihentikan setelah sepuluh menit, bukan terus berjalan sampai Anda menyadarinya. Menjalankan program sebagai service dan timer systemd membahas unit file itu sendiri. Baca hasil suatu run dengan journalctl -u triage-agent.service --since "1 hour ago".

Batasi juga retry, karena handler yang melakukan retry tanpa batas akan menagihkan biaya untuk setiap percobaan. Error 429 atau 500 layak dicoba beberapa kali dengan backoff. Error 400 tidak layak dicoba ulang, karena request yang sama akan gagal dengan cara yang sama.

Pengendalian biaya AI agent dimulai dengan membaca angka Anda sendiri

Tidak ada yang dapat memberi tahu biaya agent yang selalu aktif, karena biayanya adalah jumlah token per eksekusi dikalikan jumlah eksekusi per hari, dan kedua komponen tersebut ditentukan oleh Anda. Jalankan agent sekali, baca baris penggunaan yang Anda catat, lalu kalikan dengan jadwal Anda. Periksa laporan biaya dua hari kemudian dan bandingkan dengan perhitungan tersebut. Jika hasilnya berbeda, penyebabnya hampir selalu cache yang rusak atau loop yang berjalan lebih lama dari perkiraan Anda.

Ini mengasumsikan penggunaan API key, karena agent tersebut adalah program Anda sendiri yang memanggil Messages API. Untuk pekerjaan interaktif Anda sendiri, paket Claude mana yang sesuai dengan cara Anda bekerja membahas sisi langganan. Semua harga dan batas di sini telah diperiksa berdasarkan dokumentasi Anthropic pada Oktober 2026. Baca kembali halaman harga sebelum menyusun anggaran.

FAQ

Berapa biaya menjalankan AI agent yang selalu aktif pada VPS?

Ada dua tagihan dan hanya satu yang dapat diprediksi. Server memiliki harga bulanan tetap. API model ditagih berdasarkan jumlah token, sehingga biayanya adalah konsumsi satu eksekusi dikalikan frekuensi eksekusi. Anthropic tidak memublikasikan angka untuk agent yang di-host sendiri dan selalu aktif. Karena itu, anggap setiap angka yang disebutkan sebagai perkiraan. Catat usage dari satu eksekusi nyata, lalu kalikan dengan jadwal Anda.

Apa perbedaan antara max_tokens dan anggaran tugas?

max_tokens diberlakukan oleh sistem dan tidak terlihat oleh model. Nilai ini membatasi output dari satu request, termasuk proses berpikir, dan jika batas tersebut tercapai, hasilnya adalah stop_reason: "max_tokens". Anggaran tugas memiliki fungsi yang berlawanan: model diberi tahu nilainya dan mengatur loop agentic berdasarkan nilai tersebut. Namun, "Task budgets are a soft hint, not a hard cap", dan batas yang tetap diberlakukan adalah max_tokens.

Mengapa cache_read_input_tokens selalu bernilai nol untuk agent saya?

Hal itu terjadi karena prefix berubah di antara pemanggilan, atau karena ukurannya terlalu pendek untuk di-cache. Penyebab yang umum adalah timestamp atau run id yang diinterpolasikan ke dalam system prompt. Cache menggunakan prefix sebagai kunci, sehingga perubahan satu byte pun membatalkan seluruh bagian setelahnya. Mengubah definisi tool atau nilai effort tingkat atas juga menghasilkan efek yang sama. Jika bukan itu penyebabnya, masalahnya adalah ukuran, karena prompt yang lebih pendek tidak di-cache dan tidak ada error yang dikembalikan.

Bagaimana cara menghentikan AI agent agar tidak terus melakukan loop?

Hitung jumlah iterasi dalam kode loop Anda dan hentikan pada maksimum tetap, karena max_tokens membatasi satu response, sedangkan agent dapat menghasilkan banyak response. Tambahkan batas waktu berdasarkan jam dinding di luar proses. Jalankan job dari systemd timer dan tetapkan TimeoutStartSec= pada unit oneshot, atau RuntimeMaxSec= pada unit simple, sehingga eksekusi yang macet dihentikan sesuai jadwal. Batasi jumlah retry juga, karena setiap percobaan dalam loop retry tetap ditagihkan.

Dapatkah saya menetapkan batas pengeluaran pada satu API key Claude?

Batas pengeluaran yang didokumentasikan berlaku per workspace, bukan per key. Karena itu, berikan agent workspace khusus dan tetapkan batas pengeluaran bulanannya di sana. "You cannot set limits on the Default Workspace". Tambahkan notifikasi pengeluaran agar Anda menerima peringatan ketika ambang batas tercapai. Untuk atribusi, terbitkan key khusus untuk setiap job, lalu kelompokkan laporan penggunaan dengan group_by[]=api_key_id.