Paano kontrolin ang gastos ng always-on AI agent sa VPS
Alamin kung paano magtakda ng hard caps at task budgets, gumamit ng prompt caching at batching, at i-log ang usage fields para makita ang gastos ng bawat loop.
Paano pigilan ang always-on AI agent na magpalaki ng bill
Ang cost control para sa AI agent sa isang VPS (virtual private server) ay nakabatay sa mga ceiling na itinakda mo bago magsimula ang agent, dahil walang nagbabantay sa meter habang tumatakbo ito. Limitahan ang bawat response gamit ang max_tokens, lagyan ng hangganan ang loop iterations sa sarili mong code, i-cache ang bahagi ng prompt na hindi nagbabago, at i-log ang usage numbers ng bawat response upang makita kung aling job ang gumagastos. Fixed ang buwanang presyo ng server rental. Sinisingil ang model API batay sa bawat token, at mahusay ang unattended loop sa tahimik na paggastos ng tokens.
Ipinapalagay dito na mayroon ka nang agent na tumatawag sa Messages API mula sa sarili mong box. Saklaw ng Pagbuo ng AI agent gamit ang Claude sa isang VPS ang mismong machinery.
Bakit ibang cost shape ang unattended agent
May tao sa interactive session. Kapag napunta ang model sa maling direksiyon o nagbasa ng 40,000-line log, pinipigilan ito ng nagbabantay. Walang ganoong preno ang unattended agent: tatakbo ito hanggang matapos ang loop, at pagkatapos ay muling sisimulan ng timer.
Ang frequency ang multiplier na madalas nakakaligtaan. Ang job na naka-schedule bawat limang minuto ay tumatakbo nang 288 beses bawat araw at humigit-kumulang 8,640 beses bawat buwan. Anuman ang gastos ng isang run, iyon ang halagang imu-multiply mo. Maraming “always-on” agent ang hindi kailangang patuloy na tumakbo. Kailangan lang nilang sumagot sa loob ng itinakdang bilang ng minuto, at schedule iyon.
May mga gastos din ang agent na wala sa chat window.
- Kasama sa bawat request ang mga tool definition. Ang system prompt para sa tool use ay nagkakahalaga ng 290 tokens sa Claude Opus 4.8 kapag may
tool_choicengautoonone, at 410 kapag mayanyotool. Nagdaragdag ang bash tool ng 325 tokens. Idinaragdag ng bawat MCP server na ikinakabit mo ang mga schema nito sa kabuuang iyon; ang MCP ay model context protocol. - Input tokens ang mga resulta ng tool. Kapag nag-print ang isang command ng 8,000 linya, napupunta ang 8,000 linyang iyon sa susunod na request at sa bawat kasunod na request sa turn na iyon.
- Input tokens ang mga kinuhang page. Ang karaniwang 10 kB na web page ay humigit-kumulang 2,500 tokens, at ang 500 kB na research PDF ay humigit-kumulang 125,000. Tine-truncate ng
max_content_tokensang mga text lamang, dahil “naaangkop ito sa text content, hindi sa binary content gaya ng mga PDF.” Limitahan ang PDF gamit angmax_usesatallowed_domains. - Sinisingil ang web search bawat search, sa halagang $10 bawat 1,000 search, gaano man karami ang ibinalik na resulta. Hindi sinisingil ang search na nagkaroon ng error.
Wala sa mga iyon ang mahal kapag isang beses lang. Lahat ng iyon ay magastos kapag ginawa nang 8,640 beses.
Matigas at maluwag na limitasyon ang lumulutas sa magkaibang problema
Ipinapatupad ang max_tokens. Ito ang mahigpit na maximum sa kabuuang output ng isang request, kasama ang thinking at response text. Hindi kailanman lalampas dito si Claude, at hindi nakikita ng model ang numero. Kapag naabot ito, ibinabalik ang stop_reason: "max_tokens" at truncated ang sagot. Para sa mga agent, mahalaga ang sumusunod: bawat request sa tool-use loop ay may sarili nitong max_tokens, kaya nililimitahan nito ang isang response at hindi ang buong task. Ang 10 tool call na may tig-4,000 ay katumbas ng 40,000-token ceiling para sa turn.
Advisory ang task budget. Nasa loob ng output_config ang task_budget at sinasabi nito sa model kung ilang token ang magagamit nito para sa buong agentic loop, kasama ang thinking, tool call, tool result, at 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,
)"Soft hint lamang ang task budget, hindi ito hard cap." Maaaring lumampas dito si Claude habang nagsasagawa ng isang action, at max_tokens pa rin ang ipinapatupad na limitasyon sa output. "Model lamang ang nakakakita sa countdown", at walang remaining-budget field ang mga response. Ang minimum na tinatanggap na task_budget.total ay 20,000 token; kapag mas mababa rito, nagbabalik ito ng 400 error. Kapag masyadong maliit ang budget para sa gawain, nagkakaroon ng gawi na parang pagtanggi, kaya nililimitahan ng model ang saklaw ng task o maagang humihinto.
May isang detalye na gumagastos sa halip na makatipid. Kung binabawasan ng client mo ang task_budget.remaining sa bawat follow-up request, magiging invalid ang anumang cached prefix na naglalaman nito kapag nagbago ang value. Itakda ito nang isang beses, sa unang request.
Nasa beta ang task budgets sa Claude Fable 5, Claude Opus 4.8, at Claude Opus 4.7. Nakalista ang Claude Sonnet 5 at Claude Haiku 4.5 bilang Not supported, at hindi naaangkop ang task budgets sa Claude Code. Dahil dito, nakadepende ang Claude Code session na naka-detach sa tmux sa maayos na session hygiene.
Nasa Claude Console ang ikatlong ceiling: bigyan ang agent ng sarili nitong workspace, pagkatapos ay magtakda rito ng buwanang spend limit at per-minute rate limit. "Hindi ka makakapagtakda ng mga limitasyon sa Default Workspace", at "laging umiiral ang mga limitasyon para sa buong organization, kahit lumampas sa mga ito ang pinagsamang workspace limit". Magdagdag ng mga spend notification upang maalertuhan ka kapag malapit nang maabot ang threshold, bago maabot ang cap.
Pagpili ng modelo sa bawat job, at kung ano talaga ang binabago ng effort
Ang pagpili ng modelo ay desisyon para sa bawat job. Noong July 2026, bawat isang milyong token, input at pagkatapos ay output: Claude Fable 5 sa $10 at $50, Claude Opus 4.8 at Opus 4.7 sa $5 at $25, Claude Sonnet 5 sa $3 at $15, at Claude Haiku 4.5 sa $1 at $5. Sa ngayon, mas mababa muna sa nakalistang presyo ang Sonnet 5, dahil “may bisa ang introductory pricing na $2/$10 bawat isang milyong input/output token hanggang August 31, 2026.” Hindi kailangan ng Opus para sa hakbang na nag-uuri lang ng mga log line. Wala ring libreng allowance para sumalo sa masikip na schedule, dahil walang libreng tier ang Claude API bukod sa maliit na credit na ibinibigay sa signup.
Ang effort ang ikalawang lever. Tumatanggap ang output_config.effort ng low, medium, high, xhigh at max, at ang default ay high, kaya ang tahasang pag-set ng high ay katumbas ng hindi ito pagtatakda. Mas marami pa sa haba ng reasoning ang binabawasan ng mas mababang effort: ayon sa dokumentasyon, mas kaunting tool call ang ginagawa ni Claude at pinagsasama nito ang mga operation sa isang tawag. Sa isang agent, mas malaki ang natitipid dito, dahil ang isang naiwang tool call ay isang buong request na hindi na ipinapadala.
Ang problema ay sumasalungat ang effort sa cache. Kapag binago ang value sa pagitan ng mga request, nava-validate ang prompt caching. Sa halimbawang nasa dokumentasyon, iniulat ng request 2 ang cache_read_input_tokens: 3546; iniulat naman ng request 3, matapos baguhin ang effort mula high tungo sa medium, ang cache_creation_input_tokens sa 3546 at cache_read_input_tokens sa 0. Kaya baguhin ang effort ayon sa workload, pero huwag sa loob ng iisang cached conversation. Para baguhin ang lalim nang hindi sinisira ang cache, gawin ito sa prompt: ang linyang tulad ng “Sumagot nang direkta nang walang deliberation.” sa pinakabagong user message ay nagpapanatili sa mga naunang breakpoint.
Sinisingil ang thinking token sa output rate at ibinibilang ang mga ito sa max_tokens, kaya madalas nangangahulugan ang naputol na sagot na inubos ng thinking ang budget. Basahin ang usage.output_tokens_details.thinking_tokens para makita ang bilang. Sinusuri ng Ano talaga ang bumubuo sa Claude token bill ang bawat bahagi ng meter.
I-cache ang stable prefix at iwasang masira ito nang hindi sinasadya
Ang pagsusulat sa cache ay nagkakahalaga ng 1.25 beses ng base input price sa five-minute cache at 2 beses naman sa one-hour cache. Ang pagbasa mula sa cache ay nagkakahalaga ng 0.1 beses, kaya “magiging sulit ang caching matapos ang isang cache read para sa 5-minute duration (1.25x write), o matapos ang dalawang cache read para sa 1-hour duration (2x write).”
Ipinaliliwanag ng isang linya kung bakit angkop ito sa isang always-on agent: “Nare-refresh ang cache nang walang karagdagang gastos sa tuwing ginagamit ang naka-cache na content.” Kapag may job na tumatakbo bawat dalawang minuto laban sa five-minute cache, nananatiling warm ang prefix nito buong araw sa isang write.
Tatlong paraan upang mawala ang cache nang hindi mo napapansin.
Isang prefix na nagbabago. “Ginagawa ang mga cache prefix sa sumusunod na pagkakasunod-sunod: tools, system, pagkatapos ay messages.” Anumang pagbabago sa byte na mas maaga sa pagkakasunod-sunod na ito ay nag-iinvalidate sa lahat ng kasunod nito, at ang pag-edit sa mga tool definition ay nag-iinvalidate sa buong cache. Ang karaniwang problemang sariling gawa ay timestamp o run id sa system prompt: sa bawat request, ibang prefix ang ipinapadala, nagsusulat ng bagong entry sa 1.25x, at walang binabasang cache entry. Makikita ito sa usage.cache_read_input_tokens na nananatiling 0 sa magkakamukhang call. Ilipat ang pabago-bagong text sa pinakabagong user message.
Isang prefix na masyadong maikli. May minimum cacheable length ang bawat model. Kapag mas maikli rito ang request, pinoproseso ito nang walang caching at “walang ibinabalik na error.” Kabilang sa mga value ang 1,024 tokens sa Claude Opus 4.8 at Claude Sonnet 5, at 4,096 sa Claude Haiku 4.5. Kaya maaaring tahimik na ma-disable ang caching kapag inilipat ang isang job mula Sonnet patungong Haiku.
Isang conversation na lumalampas sa lookback. “Ang lookback window ay 20 blocks.” Sinusuri ng system ang hanggang 20 position lamang sa bawat breakpoint, pagkatapos ay humihinto. Sa dokumentadong halimbawa, ang isang turn na may 35 blocks at breakpoint sa block 35 ay sumusuri sa blocks 35 hanggang 16. Ang entry ng naunang turn sa block 15 ay nasa labas ng window, kaya walang hit. Ang isang agent app na nagdaragdag ng ilang tool-use at tool-result block sa bawat turn ay lalampas sa 20 sa loob ng dalawa o tatlong turn. May apat na breakpoint bawat request, kaya gamitin ang isa para sa mga pinakabagong message.
Ipadala sa Batches API ang anumang maaaring maghintay
"Sinisingil ang lahat ng paggamit sa 50% ng karaniwang presyo ng API", para sa input at output. Asynchronous ang batch processing, at "karamihan sa mga batch ay natatapos sa loob ng wala pang 1 oras", na ibinabalik ang mga resulta kapag natapos na ang bawat request o makalipas ang 24 oras, alinman ang mauna. Karaniwan ito, pero hindi garantisado.
I-poll ang processing_status hanggang maging ended ang value nito. Hindi sinisingil ang mga request na nagbabalik ng errored, canceled, o expired. May isang caveat kung gumagamit ka ng spend cap: "maaaring bahagyang lumampas ang mga batch sa naka-configure na spend limit ng iyong Workspace."
Naiipon ang mga discount. Dahil maaaring tumagal nang higit sa 5 minuto ang isang batch, inirerekomenda ng documentation ang one-hour cache para sa mga batch na may magkakaparehong context. Hatiin ang trabaho: ang anumang hinihintay ng tao o webhook ay manatili sa live path, habang ang nightly digest o pag-classify ng mga log mula kahapon ay ilagay sa batch sa kalahati ng presyo.
I-log sa sarili mong store ang usage fields ng bawat response
Hindi mo maiuugnay ang gastusing hindi mo naitala. Sinasabi ng bawat response kung magkano ang halaga nito.
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,
}Magdagdag ng isang row bawat API call sa isang JSON-lines file, at lagyan ito ng pangalan ng job. Pagkalipas ng isang linggo, matutukoy mo kung aling job ang gumagastos at alin ang mukhang abala lang. Bantayan ang cache_read: ang column na puro zero ang pinakakaraniwang cost bug sa isang self-hosted agent.
Madaling mabasa nang mali ang isang field. input_tokens ang bumibilang lamang sa mga token pagkatapos ng huling cache breakpoint, kaya total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens ang aktuwal na laki ng prompt. Hindi nangangahulugang matipid ang agent na nag-uulat ng input_tokens: 400 sa isang malaking prompt: galing sa cache ang natitira.
Magbilang bago magpadala. Libre ang token counting at hiwalay ang rate limits nito sa message creation, kaya gamitin ang count_tokens upang tanggihan ang sobrang laking attachment sa halip na magbayad muna bago matuklasan ang problema. Tantiya lamang ang resulta, kaya muling magsukat para sa bawat model at huwag gumamit muli ng count mula sa tokenizer ng ibang vendor. Gumagamit ang Claude Opus 4.7 at mga susunod na Opus model, Claude Fable 5, at Claude Sonnet 5 ng mas bagong tokenizer na “gumagawa ng humigit-kumulang 30% mas maraming token para sa parehong text.” Gumagamit naman ang Claude Sonnet 4.6 at mga naunang bersyon, pati ang Claude Haiku 4.5, ng naunang tokenizer.
Para sa awtoritatibong view, iniuulat ng Admin API ang usage sa https://api.anthropic.com/v1/organizations/usage_report/messages at ang cost sa https://api.anthropic.com/v1/organizations/cost_report. Pareho silang tumatanggap ng admin key (sk-ant-admin01-...) bilang x-api-key: $ANTHROPIC_ADMIN_KEY, kasama ang anthropic-version: 2023-06-01, at tumatanggap ng bucket_width=1d, group_by[]=model, at api_key_ids[]=. Isang limitasyon: “Hindi available ang Admin API para sa mga indibidwal na account.”
Ang huling parameter ay isang murang paraan ng attribution: bigyan ang bawat job ng sarili nitong API key, mag-filter gamit ang api_key_ids[], at hatiin ang report ayon sa key gamit ang group_by[]=api_key_id. Plural ang filter, samantalang singular ang grouping dimension. Itago ang mga key sa environment sa halip na sa code, gaya ng paghawak sa mga ito ng unang Claude API app sa isang VPS.
Limitahan ang loop, dahil walang ibang gagawa nito
Hindi opsyonal dito ang pagtatakda ng maximum na bilang ng iteration. Iyo ang loop, kaya iyo rin ang counter:
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)Hindi sapat ang alinman sa dalawang ceiling sa itaas: nililimitahan ng max_tokens ang isang response, at ipinapaalam lang sa model ang task budget. Awtomatikong hihinto rito ang isang hosted product, gaya ng limitasyon ni Claude sa mga tool call sa loob ng isang turn na pumipigil sa session kapag sobra na ang mga tool call nito. Ngunit ang loop na ikaw mismo ang sumulat ay walang ganitong proteksiyon hangga't hindi ka nagdaragdag nito.
Maglagay ng pangalawang proteksiyon sa labas ng process. Patakbuhin ang job mula sa systemd timer sa halip na permanenteng process, at itakda ang RuntimeMaxSec= sa service unit nito. Gamit ang RuntimeMaxSec=600, papatayin ang isang run na hindi tumutugon pagkalipas ng ten minutes sa halip na patuloy itong umikot hanggang sa mapansin mo. Saklaw ng Pagpapatakbo ng program bilang systemd service at timer ang mismong mga unit file. Basahin kung ano ang ginawa ng isang run gamit ang journalctl -u triage-agent.service --since "1 hour ago".
Limitahan din ang mga retry, dahil sisingilin sa bawat attempt ang isang handler na walang katapusang nagre-retry. Ang 429 o 500 ay maaaring subukan nang ilang beses gamit ang backoff. Ang 400 ay hindi dapat i-retry, dahil mabibigo sa parehong paraan ang parehong request.
Magsimula ang cost control ng AI agent sa pagbasa sa sarili mong mga numero
Walang makapagsasabi sa iyo kung magkano ang gastos ng isang agent na laging tumatakbo, dahil ang gastos ay tokens bawat run na pinarami sa bilang ng runs bawat araw, at ikaw ang kumokontrol sa dalawang bahaging ito. Patakbuhin ito nang isang beses, basahin ang usage row na ni-log mo, at i-multiply ito sa schedule mo. Pagkalipas ng dalawang araw, ikumpara ang cost report sa kalkulasyong iyon. Kapag hindi nagtutugma ang dalawa, halos palaging may sirang cache o loop na mas matagal tumakbo kaysa sa inakala mo.
Ipinapalagay nito na mayroon kang API key, dahil ang agent ay sarili mong program na tumatawag sa Messages API. Para sa sarili mong interactive na trabaho, saklaw ng kung aling Claude plan ang angkop sa paraan ng pagtatrabaho mo ang bahagi tungkol sa subscription. Sinuri ang bawat presyo at limit dito batay sa documentation ng Anthropic noong July 2026, kaya basahin muli ang pricing page bago ka gumawa ng budget.
FAQ
Magkano ang gastos sa pagpapatakbo ng always-on AI agent sa isang VPS?
May dalawang bayarin, at isa lamang ang predictable. Fixed ang buwanang presyo ng server. Sinisingil naman ang model API batay sa token, kaya ang gastos ay ang konsumo ng isang run na minultiply sa dalas ng pagpapatakbo nito. Walang inilalabas na halaga ang Anthropic para sa self-hosted always-on agent, kaya ituring na tantiya lamang ang anumang binanggit na numero. I-log ang usage mula sa isang aktuwal na run at i-multiply ito sa iyong schedule.
Ano ang kaibahan ng max_tokens at task budget?
Ipinapatupad ang max_tokens at hindi ito nakikita ng model. Nililimitahan nito ang output ng isang request, kasama ang pag-iisip, at kapag naabot ito, magreresulta ito sa stop_reason: "max_tokens". Kabaligtaran ang task budget: sinasabi sa model ang numero at ina-adjust nito ang agentic loop batay rito, ngunit “maluwag na gabay lamang ang task budget, hindi mahigpit na limitasyon,” at ang aktuwal na ipinapatupad na limitasyon ay max_tokens pa rin.
Bakit palaging zero ang cache_read_input_tokens para sa agent ko?
Dahil nagbabago ang prefix sa pagitan ng mga call, o masyado itong maikli para ma-cache. Karaniwang sanhi ang timestamp o run id na ini-interpolate sa system prompt: naka-key ang cache sa prefix, kaya anumang pagbabago sa byte ay nag-i-invalidate sa lahat ng kasunod na bahagi nito. Ganito rin ang epekto ng pagbabago sa tool definitions o sa value ng effort. Kung hindi iyon ang dahilan, maaaring laki ang isyu, dahil hindi naka-cache ang mas maiikling prompt at walang ibinabalik na error.
Paano ko pipigilan ang AI agent na mag-loop nang walang katapusan?
Bilangin ang mga iteration sa loop code at huminto sa nakatakdang maximum, dahil nililimitahan ng max_tokens ang isang response lamang habang maraming response ang ginagawa ng agent. Magdagdag ng wall-clock limit sa labas ng process: simulan ang job mula sa systemd timer na may nakatakdang RuntimeMaxSec=, upang mapatay ayon sa schedule ang run na hindi na umuusad. Limitahan din ang retries, dahil sinisingil ang bawat attempt sa retry loop.
Maaari ba akong magtakda ng spending limit sa isang Claude API key?
Ang documented spend limit ay para sa workspace, hindi sa bawat key. Kaya bigyan ang agent ng sarili nitong workspace at magtakda roon ng buwanang spend limit. “Hindi ka maaaring magtakda ng limitasyon sa Default Workspace.” Magdagdag ng spend notifications upang maabisuhan ka muna kapag naabot ang isang threshold. Para sa attribution, bigyan ang bawat job ng sarili nitong key, saka pagsama-samahin ang usage report gamit ang group_by[]=api_key_id.