SSD Nodes Learn Hosting plans →
Panduan Matt ConnorOleh Matt Connor · Diperbarui 2026-08-29

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.

Hard ceiling dan soft ceiling menyelesaikan masalah yang berbeda

max_tokens diberlakukan. Ini adalah batas keras pada total output satu permintaan, termasuk teks pemikiran dan respons. Claude tidak pernah menghasilkan teks melebihi batas ini, dan model tidak dapat melihat angkanya. Mencapai batas ini akan menghasilkan stop_reason: "max_tokens" dan jawaban yang terpotong. Peringatan untuk agen: setiap permintaan dalam loop penggunaan alat membawa max_tokens-nya sendiri, sehingga batas ini hanya berlaku untuk satu respons, bukan keseluruhan tugas. Sepuluh panggilan alat pada 4.000 token berarti batas 40.000 token untuk satu giliran.

Anggaran tugas bersifat saran. task_budget berada di dalam output_config dan memberi tahu model berapa banyak token yang tersedia untuk keseluruhan loop agen, termasuk pemikiran, panggilan alat, hasil alat, 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 keras." Claude mungkin melampaui anggaran di tengah tindakan, dan batas yang diberlakukan pada output tetaplah max_tokens. "Hitung mundur hanya terlihat oleh model", dan respons tidak membawa kolom sisa anggaran. task_budget.total minimum yang diterima adalah 20.000 token, dan nilai yang lebih rendah akan mengembalikan error 400. Anggaran yang terlalu kecil untuk pekerjaan tersebut akan menghasilkan perilaku seperti penolakan, sehingga model akan mempersempit cakupan tugas atau berhenti lebih awal.

Satu detail justru memakan biaya alih-alih menghematnya. Jika klien Anda mengurangi task_budget.remaining pada setiap permintaan tindak lanjut, nilai yang diubah akan membatalkan cache prefix apa pun yang memuatnya. Tetapkan nilai tersebut sekali saja, pada permintaan pertama.

Anggaran tugas sedang dalam tahap beta pada Claude Fable 5, Claude Opus 4.8, dan Claude Opus 4.7. Claude Sonnet 5 dan Claude Haiku 4.5 terdaftar sebagai Not supported, dan anggaran tugas tidak berlaku untuk Claude Code, sehingga sesi Claude Code yang terlepas di tmux bergantung pada kebersihan sesi sebagai gantinya.

Batas ketiga terdapat di Claude Console: berikan ruang kerja sendiri untuk agen, lalu tetapkan batas pengeluaran bulanan dan batas tarif per menit di sana. "Anda tidak dapat menetapkan batas pada Ruang Kerja Default", dan "Batas di seluruh organisasi selalu berlaku, meskipun total batas ruang kerja lebih besar". Tambahkan notifikasi pengeluaran agar ambang batas memberi tahu Anda sebelum batas tersebut tercapai.

Pemilihan model per pekerjaan, dan apa yang sebenarnya mengubah upaya

Pemilihan model adalah keputusan per pekerjaan. Per Juli 2026, per satu juta token, input lalu output: Claude Fable 5 seharga $10 dan $50, Claude Opus 4.8 dan Opus 4.7 seharga $5 dan $25, Claude Sonnet 5 seharga $3 dan $15, Claude Haiku 4.5 seharga $1 dan $5. Sonnet 5 berada di bawah harga resminya untuk saat ini, karena "Harga perkenalan $2/$10 per satu juta token input/output berlaku hingga 31 Agustus 2026". Langkah yang hanya mengklasifikasikan baris log tidak memerlukan Opus. Tidak ada kuota gratis untuk menyerap jadwal yang sibuk, karena Claude API tidak memiliki tingkat gratis selain kredit kecil yang diberikan saat pendaftaran.

Upaya adalah tuas kedua. output_config.effort menerima low, medium, high, xhigh dan max, dan default-nya adalah high, jadi menetapkan high secara eksplisit sama dengan menghilangkannya. Upaya yang lebih rendah memangkas lebih dari sekadar panjang penalaran: dokumentasi menyatakan bahwa hal ini membuat Claude melakukan lebih sedikit panggilan alat dan menggabungkan operasi menjadi satu. Pada agen, ini adalah penghematan yang lebih besar, karena panggilan alat yang dihindari adalah satu permintaan utuh yang tidak pernah terjadi.

Jebakannya adalah upaya melawan cache. Mengubah nilai antar permintaan akan membatalkan caching prompt. Dalam contoh yang didokumentasikan, permintaan 2 melaporkan cache_read_input_tokens: 3546; permintaan 3, dengan upaya diubah dari tinggi ke sedang, melaporkan cache_creation_input_tokens dari 3546 dan cache_read_input_tokens dari 0. Jadi, variasikan upaya di seluruh beban kerja, jangan pernah di dalam satu percakapan yang di-cache. Untuk mengarahkan kedalaman tanpa merusak cache, lakukan di dalam prompt: baris seperti "Jawab langsung tanpa mempertimbangkan." pada pesan pengguna terbaru membiarkan breakpoint sebelumnya tetap utuh.

Token pemikiran ditagihkan dengan tarif output dan dihitung terhadap max_tokens, itulah sebabnya jawaban yang terpotong sering kali berarti pemikiran menghabiskan anggaran. Baca usage.output_tokens_details.thinking_tokens untuk angkanya. Apa yang sebenarnya mengisi tagihan token Claude membedah meternya.

Simpan prefix stabil dalam cache, dan jangan sampai merusaknya secara tidak sengaja

Penulisan cache memakan biaya 1,25 kali harga input dasar pada cache lima menit dan 2 kali pada cache satu jam. Pembacaan cache memakan biaya 0,1 kali, jadi "caching memberikan keuntungan setelah hanya satu kali pembacaan cache untuk durasi 5 menit (1,25x penulisan), atau setelah dua kali pembacaan cache untuk durasi 1 jam (2x penulisan)".

Satu baris menjelaskan mengapa hal ini cocok untuk agen yang selalu aktif: "Cache diperbarui tanpa biaya tambahan setiap kali konten yang di-cache digunakan." Pekerjaan yang berjalan setiap dua menit terhadap cache lima menit akan menjaga prefix tetap hangat sepanjang hari hanya dengan satu kali penulisan.

Tiga cara kehilangan cache tanpa disadari.

Prefix yang berubah. "Prefix cache dibuat dalam urutan berikut: tools, system, kemudian messages." Perubahan byte apa pun yang terjadi lebih awal dalam urutan tersebut akan membatalkan semua yang ada setelahnya, dan mengedit definisi alat akan membatalkan seluruh cache. Kesalahan umum yang sering terjadi adalah menyertakan timestamp atau run id dalam system prompt: setiap permintaan kemudian membawa prefix yang berbeda, menulis entri baru pada 1,25x, dan tidak membaca apa pun kembali. Indikasinya adalah usage.cache_read_input_tokens pada angka 0 di panggilan yang terlihat identik. Pindahkan teks yang berubah-ubah ke dalam pesan pengguna yang paling baru.

Prefix yang terlalu pendek. Setiap model memiliki panjang minimum yang dapat di-cache, dan di bawah panjang tersebut, permintaan diproses tanpa caching dan "tidak ada error yang dikembalikan". Angka-angkanya mencakup 1.024 token pada Claude Opus 4.8 dan Claude Sonnet 5, serta 4.096 pada Claude Haiku 4.5, jadi memindahkan pekerjaan dari Sonnet ke Haiku dapat mematikan caching secara diam-diam.

Percakapan yang melebihi batas lookback. "Jendela lookback adalah 20 blok." Sistem memeriksa paling banyak 20 posisi per breakpoint, lalu berhenti. Dalam contoh yang didokumentasikan, giliran yang menampung 35 blok dengan breakpoint pada blok 35 akan memeriksa blok 35 hingga 16, dan entri giliran sebelumnya pada blok 15 berada di luar jendela, sehingga tidak ada hit. Agen yang menambahkan beberapa blok penggunaan alat dan hasil alat per giliran akan melewati angka 20 dalam dua atau tiga giliran. Anda mendapatkan empat breakpoint per permintaan, jadi gunakan satu untuk pesan-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 kolom penggunaan setiap respons ke penyimpanan Anda sendiri

Anda tidak dapat mengatribusikan pengeluaran yang tidak pernah Anda catat. Setiap respons memberi tahu Anda berapa biayanya.

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 per panggilan API ke file JSON-lines, yang ditandai dengan nama job Anda. Seminggu kemudian, Anda dapat menentukan job mana yang menghabiskan biaya dan mana yang hanya terlihat sibuk. Pantau cache_read: kolom berisi angka nol adalah bug biaya yang paling umum terjadi pada agen yang di-host sendiri.

Satu kolom mudah disalahartikan. input_tokens hanya menghitung token setelah breakpoint cache terakhir, jadi ukuran prompt yang sebenarnya adalah total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. Agen yang melaporkan input_tokens: 400 pada prompt besar tidak berarti murah: sisanya berasal dari cache.

Hitung sebelum Anda mengirim. Penghitungan token tidak dipungut biaya dan limit rate-nya terpisah dari pembuatan pesan, jadi gunakan count_tokens untuk menolak lampiran yang terlalu besar alih-alih membayar untuk mengetahuinya. Hasilnya adalah estimasi, jadi lakukan pengukuran ulang per model dan jangan pernah menggunakan kembali hitungan dari tokenizer vendor lain. Claude Opus 4.7 dan model Opus setelahnya, Claude Fable 5, serta Claude Sonnet 5 menggunakan tokenizer yang lebih baru yang "menghasilkan sekitar 30% lebih banyak token untuk teks yang sama". Claude Sonnet 4.6 dan versi sebelumnya, termasuk Claude Haiku 4.5, menggunakan tokenizer yang lama.

Untuk tampilan yang 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 memerlukan kunci admin (sk-ant-admin01-...) sebagai x-api-key: $ANTHROPIC_ADMIN_KEY dengan anthropic-version: 2023-06-01, serta menerima bucket_width=1d, group_by[]=model, dan api_key_ids[]=. Satu batasan: "Admin API tidak tersedia untuk akun individu."

Parameter terakhir tersebut adalah trik atribusi yang murah: berikan setiap job kunci API-nya sendiri, filter dengan api_key_ids[], dan bagi laporan per kunci dengan group_by[]=api_key_id. Filternya bersifat jamak, dimensi pengelompokannya bersifat tunggal. Simpan kunci di environment alih-alih di dalam kode, seperti cara aplikasi Claude API pertama di VPS menanganinya.

Batasi perulangan, karena tidak ada mekanisme lain yang melakukannya

Jumlah iterasi yang dibatasi bukanlah hal opsional di sini. Perulangan tersebut adalah milik Anda, jadi penghitungnya pun 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)

Tidak ada batasan atas yang akan melakukannya untuk Anda: max_tokens hanya membatasi satu respons, dan model hanya diberi tahu tentang anggaran tugas. Produk yang di-hosting akan menghentikan Anda di sini, seperti cara Claude's cap on tool calls within a single turn menghentikan sesi yang melakukan terlalu banyak panggilan, tetapi perulangan yang Anda tulis sendiri tidak memiliki pengaman seperti itu sampai Anda menambahkannya.

Pasang rem kedua di luar proses tersebut. Jalankan tugas dari systemd timer alih-alih proses permanen, dan atur RuntimeMaxSec= pada unit servicenya. Dengan RuntimeMaxSec=600, proses yang menggantung akan dihentikan setelah sepuluh menit alih-alih terus berjalan sampai Anda menyadarinya. Running a program as a systemd service and timer membahas file unit itu sendiri. Baca apa yang dilakukan oleh suatu proses dengan journalctl -u triage-agent.service --since "1 hour ago".

Batasi juga percobaan ulang, karena penangan yang mencoba ulang selamanya akan menagih setiap upaya. Kode 429 atau 500 layak mendapatkan beberapa kali percobaan dengan backoff. Kode 400 tidak layak mendapatkan percobaan ulang, karena permintaan yang sama akan gagal dengan cara yang sama.

Kontrol biaya agen AI dimulai dengan membaca angka Anda sendiri

Tidak ada yang bisa memberi tahu Anda berapa biaya agen yang selalu aktif, karena biayanya adalah token per eksekusi dikalikan dengan jumlah eksekusi per hari, dan kedua variabel tersebut adalah milik Anda. Jalankan agen satu kali, baca baris penggunaan yang Anda catat, lalu kalikan dengan jadwal Anda. Periksa laporan biaya dua hari kemudian terhadap perhitungan tersebut. Jika keduanya tidak sesuai, selisihnya hampir selalu disebabkan oleh cache yang rusak atau loop yang berjalan lebih lama dari yang Anda asumsikan.

Hal ini mengasumsikan penggunaan API key, karena agen tersebut adalah program Anda sendiri yang memanggil Messages API. Untuk pekerjaan interaktif Anda sendiri, paket Claude mana yang sesuai dengan cara kerja Anda membahas sisi langganan. Setiap harga dan batas di sini telah diperiksa terhadap dokumentasi Anthropic pada Juli 2026, jadi bacalah kembali halaman harga sebelum Anda menyusun anggaran.

FAQ

Berapa biaya untuk menjalankan agen AI yang selalu aktif di VPS?

Terdapat dua tagihan dan hanya satu yang dapat diprediksi. Server memiliki harga bulanan tetap. API model dihitung berdasarkan token, sehingga biayanya adalah hasil perkalian antara konsumsi satu kali eksekusi dengan frekuensi eksekusinya. Anthropic tidak memublikasikan angka untuk agen yang di-host sendiri dan selalu aktif, jadi anggaplah angka apa pun yang dikutip sebagai perkiraan. Catat usage dari satu eksekusi nyata dan kalikan dengan jadwal Anda.

Apa perbedaan antara max_tokens dan anggaran tugas (task budget)?

max_tokens diberlakukan dan tidak terlihat oleh model. Ini membatasi output dari satu permintaan, termasuk proses berpikir, dan jika tercapai akan menghasilkan stop_reason: "max_tokens". Anggaran tugas adalah kebalikannya: model diberitahu mengenai angka tersebut dan menyesuaikan loop agen terhadapnya, namun "Anggaran tugas adalah petunjuk lunak, bukan batasan keras" dan batas yang diberlakukan tetaplah max_tokens.

Mengapa cache_read_input_tokens selalu nol untuk agen saya?

Karena prefiks berubah di antara panggilan, atau terlalu pendek untuk di-cache. Penyebab umum adalah stempel waktu atau id eksekusi yang disisipkan ke dalam system prompt: cache dikunci berdasarkan prefiks, sehingga perubahan byte apa pun akan membatalkan semua data setelahnya. Mengubah definisi alat atau nilai effort juga menyebabkan hal yang sama. Jika bukan itu, penyebabnya adalah ukuran, karena prompt yang lebih pendek tidak di-cache dan tidak ada error yang dikembalikan.

Bagaimana cara menghentikan agen AI agar tidak melakukan loop selamanya?

Hitung iterasi dalam kode loop Anda dan hentikan pada batas maksimum yang tetap, karena max_tokens membatasi satu respons dan agen melakukan banyak respons. Tambahkan batas waktu dinding (wall-clock limit) di luar proses: jalankan tugas dari systemd timer dengan RuntimeMaxSec= diatur, sehingga eksekusi yang macet akan dihentikan sesuai jadwal. Batasi juga percobaan ulang (retries), karena loop percobaan ulang akan menagih setiap upaya.

Bisakah saya menetapkan batas pengeluaran pada satu kunci API Claude?

Batas pengeluaran yang didokumentasikan berlaku per ruang kerja (workspace) dan bukan per kunci, jadi berikan agen ruang kerjanya sendiri dan batasi pengeluaran bulanannya di sana. "Anda tidak dapat menetapkan batas pada Ruang Kerja Default". Tambahkan notifikasi pengeluaran agar ambang batas memberi tahu Anda terlebih dahulu. Untuk atribusi, berikan setiap tugas kuncinya sendiri, lalu kelompokkan laporan penggunaan dengan group_by[]=api_key_id.