SSD Nodes Learn
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-07-24

AI agent kosten beheersen op een VPS

Voorkom onverwachte API-rekeningen door limieten in te stellen voor uw unattended agent. Gebruik prompt caching en task budgets om uw verbruik te controleren.

Hoe u de kosten van een altijd actieve AI agent beperkt

Kostenbeheersing voor een AI agent op een VPS (virtual private server) draait om het instellen van limieten voordat de agent start. Niemand controleert de meter terwijl de agent draait. Stel een limiet in voor elke respons met max_tokens. Beperk het aantal iteraties in uw eigen code. Cache het deel van de prompt dat niet verandert. Log de verbruikscijfers van elke respons om te zien welke taak kosten maakt. De serverhuur is een vast maandelijks bedrag. De model API wordt per token belast. Een onbewaakte loop verbruikt tokens ongemerkt zeer snel.

Dit gaat uit van een bestaande agent die de Messages API aanroept vanaf een eigen server. Een AI agent met Claude op een VPS bouwen behandelt de technische werking.

Waarom een unattended agent een andere kostenstructuur heeft

Een interactieve sessie bevat een menselijke gebruiker. Wanneer het model een foutief pad inslaat of een logbestand van 40.000 regels leest, stopt de toeschouwer het proces. Een unattended agent heeft deze rem niet: deze blijft draaien tot de loop eindigt, waarna een timer het proces opnieuw start.

Frequentie is de vermenigvuldiger die vaak wordt vergeten. Een taak met een interval van vijf minuten wordt 288 keer per dag en ongeveer 8.640 keer per maand uitgevoerd. Vermenigvuldig de kosten van één uitvoering met dit aantal. Veel "always-on" agents hoeven niet constant actief te zijn. Ze moeten binnen een bepaald aantal minuten antwoorden, wat neerkomt op een schema.

Een agent brengt ook kosten met zich mee waar een chatvenster geen last van heeft.

  • Tool definitions worden bij elke request meegestuurd. De tool-use system prompt kost 290 tokens op Claude Opus 4.8 met tool_choice van auto of none, en 410 met any of tool. De bash tool voegt 325 tokens toe. Elke MCP server die u koppelt voegt de bijbehorende schema's toe aan deze belasting; MCP staat voor het model context protocol.
  • Tool results zijn input tokens. Een commando dat 8.000 regels print, plaatst 8.000 regels in de volgende request, en in elke daaropvolgende request binnen die turn.
  • Fetched pages zijn input tokens. Een gemiddelde webpagina van 10 kB is ongeveer 2.500 tokens en een PDF van 500 kB voor onderzoek is ongeveer 125.000 tokens. max_content_tokens knipt alleen tekstbestanden af, omdat dit "geldt voor tekstinhoud, niet voor binaire inhoud zoals PDF's". Gebruik in plaats daarvan max_uses en allowed_domains voor PDF's.
  • Web search wordt per zoekopdracht belast, tegen $10 per 1.000 zoekopdrachten, ongeacht het aantal resultaten. Een zoekopdracht die een fout geeft, wordt niet in rekening gebracht.

Geen van deze factoren is duur bij een eenmalige uitvoering. Al deze factoren zijn duur wanneer ze 8.640 keer worden uitgevoerd.

Hard ceilings en soft ceilings lossen verschillende problemen op

max_tokens is bindend. Dit is een harde limiet op de totale output van één request, inclusief zowel de denkfase als de antwoordtekst. Claude genereert nooit meer dan deze limiet en het model kan dit getal niet zien. Het bereiken van deze limiet veroorzaakt stop_reason: "max_tokens" en een afgebroken antwoord. Dit is een probleem voor agents: elke request in een tool-use loop heeft een eigen max_tokens. Hierdoor wordt één antwoord begrensd, maar niet de gehele taak. Tien tool calls van 4,000 tokens resulteren in een limiet van 40,000 tokens voor de hele beurt.

Een task budget is adviserend. task_budget maakt deel uit van output_config en geeft het model aan hoeveel tokens beschikbaar zijn voor de volledige agentic loop. Dit telt de denkfase, tool calls, tool results en de output mee.

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,
)

"Task budgets zijn een soft hint, geen harde limiet." Claude kan tijdens een actie de limiet overschrijden, terwijl de bindende limiet op de output nog steeds max_tokens is. "De countdown is alleen zichtbaar voor het model" en antwoorden bevatten geen veld met het resterende budget. Het minimale geaccepteerde task_budget.total is 20,000 tokens; een lagere waarde resulteert in een 400 error. Een budget dat te klein is voor de taak leidt tot weigeringsgedrag, waardoor het model de taak verkleint of voortijdig stopt.

Eén detail brengt kosten met zich mee in plaats van besparingen. Als uw client bij elke follow-up request task_budget.remaining verlaagt, wordt elke gecachte prefix die deze waarde bevat ongeldig. Stel de waarde eenmalig in bij de eerste request.

Task budgets zijn in beta op Claude Fable 5, Claude Opus 4.8 en Claude Opus 4.7. Claude Sonnet 5 en Claude Haiku 4.5 staan vermeld als Not supported. Task budgets zijn niet van toepassing op Claude Code; een Claude Code session detached in tmux is daarom afhankelijk van session hygiene.

De derde limiet bevindt zich in de Claude Console: geef de agent een eigen workspace en stel daar een maandelijkse spend limit en per-minute rate limits in. "U kunt geen limieten instellen op de Default Workspace" en "Organization-wide limits zijn altijd van toepassing, zelfs als de workspace limieten hoger zijn". Voeg spend notifications toe, zodat u een waarschuwing krijgt voordat de limiet wordt bereikt.

Modelkeuze per taak, en wat de werkelijke inspanning verandert

Modelkeuze is een beslissing per taak. Per juli 2026 zijn de kosten per miljoen tokens (input, dan output): Claude Fable 5 voor $10 en $50, Claude Opus 4.8 en Opus 4.7 voor $5 en $25, Claude Sonnet 5 voor $3 en $15, Claude Haiku 4.5 voor $1 en $5. De prijs van Sonnet 5 ligt momenteel lager dan de standaardprijs, omdat "Introductory pricing of $2/$10 per million input/output tokens is in effect through August 31, 2026". Een stap die enkel logregels classificeert, heeft geen Opus nodig.

Inspanning is de tweede variabele. output_config.effort accepteert low, medium, high, xhigh en max. De standaardwaarde is high, dus het expliciet instellen van high heeft hetzelfde effect als het weglaten ervan. Een lagere inspanning bespaart meer dan alleen de lengte van de redenering: de documentatie vermeldt dat het Claude dwingt om minder tool calls te gebruiken en operaties te combineren tot één actie. Voor een agent levert dit een grotere besparing op, omdat een vermeden tool call een volledige request is die niet plaatsvindt.

De valkuil is dat inspanning conflicteert met de cache. Het wijzigen van de waarde tussen requests zorgt ervoor dat de prompt caching ongeldig wordt. In het gedocumenteerde voorbeeld rapporteerde request 2 cache_read_input_tokens: 3546; request 3, waarbij de inspanning werd gewijzigd van high naar medium, rapporteerde cache_creation_input_tokens van 3546 en cache_read_input_tokens van 0. Varieer de inspanning daarom tussen verschillende workloads, maar nooit binnen één gecachte conversatie. Om de diepgang te sturen zonder de cache te verbreken, moet dit in de prompt gebeuren: een regel als "Answer directly without deliberating." in het nieuwste gebruikersbericht laat de eerdere breakpoints intact.

Thinking tokens worden gefactureerd tegen de output-tarieven en tellen mee voor max_tokens. Dit is de reden waarom een afgebroken antwoord vaak betekent dat het denkproces het budget heeft verbruikt. Lees usage.output_tokens_details.thinking_tokens voor de exacte cijfers. Wat een Claude-rekening daadwerkelijk vult legt de details uit.

Cache de stable prefix, en voorkom onbedoelde fouten

Een cache write kost 1.25 keer de basisprijs bij de five-minute cache en 2 keer bij de one-hour cache. Een cache read kost 0.1 keer de prijs. Dit betekent dat "caching rendabel is na slechts één cache read voor de 5-minute duur (1.25x write), of na twee cache reads voor de 1-hour duur (2x write)".

Eén zin legt uit waarom dit geschikt is voor een always-on agent: "De cache wordt elke keer dat de gecachte content wordt gebruikt ververst zonder extra kosten." Een job die elke twee minuten draait tegen de five-minute cache houdt de prefix de hele dag warm voor slechts één write.

Drie manieren om de cache ongemerkt te verliezen.

Een prefix die verandert. "Cache prefixes worden in de volgende volgorde aangemaakt: tools, system, en vervolgens messages." Elke byte-wijziging eerder in deze volgorde maakt alles daarna ongeldig. Het bewerken van tool definitions maakt de volledige cache ongeldig. Een veelvoorkomende fout is een timestamp of een run id in de system prompt: elke request heeft dan een andere prefix, schrijft een nieuwe entry voor 1.25x, en leest niets terug. Het symptoom is usage.cache_read_input_tokens op 0 bij identiek uitziende calls. Verplaats de volatiele tekst naar het nieuwste user message.

Een prefix die te kort is. Elk model heeft een minimale cacheable lengte. Onder deze lengte wordt de request verwerkt zonder caching en "wordt er geen error geretourneerd". De limieten zijn 1,024 tokens voor Claude Opus 4.8 en Claude Sonnet 5, en 4,096 voor Claude Haiku 4.5. Het verplaatsen van een job van Sonnet naar Haiku kan de caching dus stilzwijgend uitschakelen.

Een gesprek dat groter wordt dan de lookback. "De lookback window is 20 blocks." Het systeem controleert maximaal 20 posities per breakpoint en stopt daarna. In het gedocumenteerde voorbeeld controleert een turn met 35 blocks met een breakpoint op block 35 de blocks 35 tot en met 16. De entry van de vorige turn op block 15 valt buiten het venster, waardoor er geen hit is. Een agent die per turn meerdere tool-use en tool-result blocks toevoegt, overschrijdt de 20 blocks binnen twee of drie turns. U krijgt vier breakpoints per request; gebruik er daarom één voor de recente messages.

Stuur alles wat kan wachten naar de Batches API

"Alle verwerking wordt in rekening gebracht tegen 50% van de standaard API-prijzen", zowel voor input als output. Batchverwerking is asynchroon. "De meeste batches zijn binnen 1 uur voltooid". De resultaten zijn beschikbaar zodra elke aanvraag is voltooid of na 24 uur, afhankelijk van wat het eerst komt. Dit is een gemiddelde, geen garantie.

Poll processing_status tot de waarde ended is. Aanvragen met de status errored, canceled of expired worden niet in rekening gebracht. Let op als u een budgetlimiet gebruikt: "batches kunnen iets boven de geconfigureerde spend limit van uw Workspace uitkomen."

De kortingen zijn cumulatief. Omdat een batch langer dan vijf minuten kan duren, adviseert de documentatie om de eenuurs cache te gebruiken voor batches met dezelfde context. Verdeel de taken: zaken waar een persoon of een webhook op wacht, moeten via het live-pad gaan. Een nachtelijk overzicht of de classificatie van de logs van gisteren kan tegen de halve prijs in een batch worden verwerkt.

Log alle usage fields van elke response naar uw eigen opslag

U kunt geen kosten toewijzen aan uitgaven die niet zijn geregistreerd. Elke response bevat informatie over de kosten.

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,
}

Voeg per API-call één regel toe aan een JSON-lines bestand, voorzien van uw job name. Zo kunt u na een week zien welke job kosten maakt en welke job alleen maar actief leek. Let op cache_read: een kolom met alleen nullen is de meest voorkomende fout bij de kostenberekening van een self-hosted agent.

Eén veld is lastig te interpreteren. input_tokens telt alleen de tokens na het laatste cache breakpoint, waardoor de werkelijke prompt size total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens is. Een agent die input_tokens: 400 rapporteert bij een grote prompt is niet goedkoop: de rest kwam uit de cache.

Tel tokens voordat u de request verzendt. Token counting is gratis en de rate limits zijn gescheiden van message creation. Gebruik daarom count_tokens om een te groot attachment te weigeren in plaats van te betalen om het te ontdekken. Het resultaat is een schatting; meet daarom per model opnieuw en hergebruik nooit een count van de tokenizer van een andere vendor. Claude Opus 4.7 en latere Opus modellen, Claude Fable 5 en Claude Sonnet 5 gebruiken een nieuwere tokenizer die "ongeveer 30% meer tokens produceert voor dezelfde tekst". Claude Sonnet 4.6 en oudere versies, waaronder Claude Haiku 4.5, gebruiken de vorige versie.

Voor de definitieve gegevens rapporteert de Admin API usage bij https://api.anthropic.com/v1/organizations/usage_report/messages en kosten bij https://api.anthropic.com/v1/organizations/cost_report. Beide vereisen een admin key (sk-ant-admin01-...) als x-api-key: $ANTHROPIC_ADMIN_KEY met anthropic-version: 2023-06-01, en accepteren bucket_width=1d, group_by[]=model en api_key_ids[]=. Eén beperking: "The Admin API is unavailable for individual accounts."

Die laatste parameter is een eenvoudige methode voor attributie: geef elke job een eigen API key, filter met api_key_ids[], en splits het rapport per key met group_by[]=api_key_id. De filter is meervoudig, de grouping dimension is enkelvoudig. Bewaar de keys in de environment in plaats van in de code, zoals de eerste Claude API app op een VPS dit doet.

Beperk de loop, omdat niets anders dit doet

Een beperkt aantal iteraties is hier verplicht. De loop is van u, dus de teller is van u:

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)

Geen van de bovenstaande limieten lost dit voor u op: max_tokens beperkt één respons, en het model krijgt alleen een taakbudget door.

Plaats een tweede beveiliging buiten het proces. Voer de taak uit via een systemd timer in plaats van een permanent proces, en stel RuntimeMaxSec= in op de service unit. Met RuntimeMaxSec=600 wordt een vastgelopen proces na tien minuten beëindigd in plaats van dat het blijft draaien tot u het merkt. Een programma uitvoeren als een systemd service en timer behandelt de unit files zelf. Lees wat een uitvoering heeft gedaan met journalctl -u triage-agent.service --since "1 hour ago".

Beperk ook het aantal retries, omdat een handler die oneindig probeert het aantal pogingen verhoogt. Een 429 of een 500 verdient enkele pogingen met backoff. Een 400 verdient geen pogingen, aangezien dezelfde aanvraag op dezelfde manier zal falen.

AI agent kostenbeheersing begint bij het analyseren van uw eigen gegevens

Niemand kan de kosten van een constant actieve agent voorspellen. De kosten bestaan uit het aantal tokens per uitvoering vermenigvuldigd met het aantal uitvoeringen per dag. Beide variabelen zijn afhankelijk van uw eigen gebruik. Voer de agent eenmaal uit en bekijk de geregistreerde verbruikscijfers. Vermenigvuldig dit met uw geplande schema. Vergelijk het kostenrapport twee dagen later met deze berekening. Als de resultaten verschillen, komt dit bijna altijd door een defecte cache of een loop die langer draaide dan verwacht.

Dit gaat uit van een API-key, aangezien de agent uw eigen programma is dat de Messages API aanroept. Voor interactief gebruik biedt welk Claude-abonnement bij uw werkwijze past informatie over de abonnementen. Elke prijs en limiet is in juli 2026 gecontroleerd aan de hand van de documentatie van Anthropic. Controleer de prijzenpagina opnieuw voordat u een budget opstelt.

FAQ

Wat zijn de kosten voor een altijd actieve AI-agent op een VPS?

Er zijn twee facturen en slechts één is voorspelbaar. De server heeft een vaste maandprijs. De model API wordt afgerekend per token, dus de kosten zijn het verbruik van één run vermenigvuldigd met de frequentie van de runs. Anthropic publiceert geen cijfers voor een zelfgehoste altijd actieve agent, dus beschouw elk genoemde bedrag als een schatting. Log usage van een echte run en vermenigvuldig dit met uw schema.

Wat is het verschil tussen max_tokens en een task budget?

max_tokens wordt afgedwongen en is onzichtbaar voor het model. Het beperkt de output van één verzoek, inclusief het denken, en het bereiken van deze limiet resulteert in stop_reason: "max_tokens". Een task budget werkt andersom: het model krijgt het aantal te weten en past de agentic loop hierop aan, maar "Task budgets are a soft hint, not a hard cap" en de afgedwongen limiet blijft max_tokens.

Waarom is cache_read_input_tokens altijd nul voor mijn agent?

Omdat de prefix verandert tussen calls, of omdat deze te kort is om te cachen. De gebruikelijke oorzaak is een timestamp of een run id die in de system prompt wordt ingevoegd: de cache is gebaseerd op de prefix, dus elke wijziging in een byte maakt alles daarna ongeldig. Het wijzigen van tool definitions of de effort waarde heeft hetzelfde effect. Een andere oorzaak is de grootte, aangezien kortere prompts niet worden gecached en er geen foutmelding wordt gegeven.

Hoe voorkom ik dat een AI-agent in een oneindige loop terechtkomt?

Tel het aantal iteraties in uw loop code en stop bij een vast maximum, omdat max_tokens één respons beperkt en een agent er vele uitvoert. Voeg een tijdlimiet toe buiten het proces: start de taak via een systemd timer met RuntimeMaxSec= ingesteld, zodat een vastgelopen run volgens schema wordt beëindigd. Beperk ook het aantal retries, aangezien een retry loop kosten per poging genereert.

Kan ik een uitgavenlimiet instellen voor een enkele Claude API key?

De gedocumenteerde uitgavenlimiet geldt per workspace in plaats van per key, dus geef de agent een eigen workspace en stel daar het maandelijkse budget in. "You cannot set limits on the Default Workspace". Voeg spend notifications toe zodat een drempelwaarde u eerst waarschuwt. Gebruik voor de toerekening een eigen key voor elke taak en groepeer het verbruik met group_by[]=api_key_id.

#claude#ai#agents#api#cost