SSD Nodes Learn Hosting plans →
Gidsen Matt ConnorDoor Matt Connor

Kosten van AI-agents op een VPS beheersen

Voorkom onverwachte facturen bij onbeheerde AI-agents. Gebruik max_tokens, prompt caching en taakbudgetten om uw tokenverbruik op een VPS effectief te beperken en te monitoren.

Hoe u voorkomt dat een altijd actieve AI-agent onverwachte kosten veroorzaakt

Kostenbeheersing voor een AI-agent op een VPS (virtual private server) draait om limieten die u instelt voordat de agent start, aangezien niemand continu de meter in de gaten houdt terwijl deze draait. Begrens elk antwoord met max_tokens, beperk het aantal lus-iteraties in uw eigen code, cache het gedeelte van de prompt dat nooit verandert en log de verbruiksgegevens van elk antwoord om te zien welke taak kosten genereert. De serverhuur heeft een vaste maandprijs. De model-API wordt per token afgerekend en een onbeheerde lus is zeer efficiënt in het stilletjes verbruiken van tokens.

Dit gaat uit van een agent die al bestaat en de Messages API aanroept vanaf een server die u beheert. Een AI-agent bouwen met Claude op een VPS behandelt de techniek hierachter.

Waarom een onbeheerde agent een ander kostenplaatje heeft

Een interactieve sessie bevat een menselijke gebruiker. Wanneer het model een verkeerd pad inslaat of een logbestand van 40.000 regels leest, grijpt de toeschouwer in. Een onbeheerde agent heeft geen dergelijke rem: deze draait totdat de lus eindigt, waarna een timer het proces opnieuw start.

Frequentie is de vermenigvuldiger die vaak over het hoofd wordt gezien. Een taak met een schema van vijf minuten draait 288 keer per dag en ongeveer 8.640 keer per maand. Wat één uitvoering ook kost, dat is het getal waarmee u vermenigvuldigt. Veel "always-on" agents hoeven niet continu actief te zijn. Ze moeten binnen een bepaald aantal minuten antwoorden, wat neerkomt op een schema.

Een agent betaalt ook voor zaken waar een chatvenster niet voor betaalt.

  • Tooldefinities reizen mee met elk verzoek. De systeem-prompt voor toolgebruik 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 daar nog eens 325 aan toe. Elke MCP server die u koppelt voegt zijn schema's toe aan dat gewicht, waarbij MCP staat voor het model context protocol.
  • Toolresultaten zijn input-tokens. Een commando dat 8.000 regels print, plaatst 8.000 regels in het volgende verzoek, en in elk verzoek daarna in diezelfde beurt.
  • Opgehaalde pagina's zijn input-tokens. Een gemiddelde webpagina van 10 kB is ongeveer 2.500 tokens en een onderzoeks-PDF van 500 kB ongeveer 125.000. max_content_tokens kapt alleen tekstbestanden af, omdat dit "van toepassing is op tekstinhoud, niet op binaire inhoud zoals PDF's". Begrens een PDF in plaats daarvan met max_uses en allowed_domains.
  • Webzoeken wordt per zoekopdracht geprijsd, tegen $10 per 1.000 zoekopdrachten, ongeacht hoeveel resultaten er terugkomen. Een zoekopdracht die een fout geeft, wordt niet in rekening gebracht.

Niets daarvan is duur als het één keer gebeurt. Alles daarvan is duur als het 8.640 keer gebeurt.

Harde limieten en zachte limieten lossen verschillende problemen op

max_tokens wordt afgedwongen. Dit is een harde limiet op de totale output van één verzoek, inclusief denkwerk en antwoordtekst. Claude genereert nooit voorbij dit punt en het model kan het getal zelf niet zien. Het bereiken van deze limiet resulteert in stop_reason: "max_tokens" en een afgebroken antwoord. Het addertje onder het gras voor agents: elk verzoek in een tool-use loop bevat zijn eigen max_tokens, waardoor deze de limiet per antwoord bepaalt en niet per taak. Tien tool-aanroepen van 4.000 tokens betekenen een limiet van 40.000 tokens voor de gehele beurt.

Een taakbudget is adviserend. task_budget bevindt zich binnen output_config en geeft het model aan hoeveel tokens het heeft voor de gehele agent-loop, inclusief denkwerk, tool-aanroepen, tool-resultaten en 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,
)

"Taakbudgetten zijn een zachte hint, geen harde limiet." Claude kan een budget halverwege een actie overschrijden, terwijl de afgedwongen limiet op output nog steeds max_tokens is. "Het aftellen is alleen zichtbaar voor het model" en antwoorden bevatten geen veld voor het resterende budget. Het minimaal geaccepteerde task_budget.total is 20.000 tokens; een lagere waarde resulteert in een 400-foutmelding. Een budget dat te klein is voor de taak leidt tot gedrag dat lijkt op een weigering, waardoor het model de taak inkort of voortijdig stopt.

Eén detail kost geld in plaats van dat het besparingen oplevert. Als uw client task_budget.remaining verlaagt bij elk vervolgverzoek, maakt de gewijzigde waarde elke gecachte prefix die deze waarde bevat ongeldig. Stel het budget één keer in, bij het eerste verzoek.

Taakbudgetten bevinden zich in bèta op 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 en Claude Haiku 5.5. Claude Sonnet 5 en Claude Haiku 4.5 staan vermeld als Not supported, en taakbudgetten zijn niet van toepassing op Claude Code, dus een Claude Code-sessie losgekoppeld in tmux is afhankelijk van sessiehygiëne.

De derde limiet bevindt zich in de Claude Console: geef de agent een eigen werkruimte en stel vervolgens een maandelijkse bestedingslimiet en tarieflimieten per minuut in. "U kunt geen limieten instellen op de standaardwerkruimte" en "Organisatiebrede limieten zijn altijd van toepassing, zelfs als de som van de werkruimtelimieten hoger uitvalt". Voeg bestedingsmeldingen toe zodat een drempelwaarde u waarschuwt voordat de limiet wordt bereikt.

Modelkeuze per taak en de werkelijke invloed van effort

De modelkeuze is een beslissing die per taak wordt genomen. Per oktober 2026 gelden de volgende prijzen per miljoen tokens (input gevolgd door output): Claude Fable 5.1 en Fable 5 kosten $10 en $50, Claude Opus 5.5 kost $4 en $20, Claude Opus 5, Opus 4.8 en Opus 4.7 kosten $5 en $25, Claude Sonnet 5.5 en Sonnet 5 kosten $2 en $10, Claude Haiku 5.5 kost $0,10 en $0,50 voor prompts tot 100.000 tokens ($0,50 en $2,50 daarboven, inclusief gecachte tokens in de telling), en Claude Haiku 4.5 kost $1 en $5. Anthropic bood Sonnet 5 aanvankelijk aan tegen dit tarief als introductieprijs, maakte dit vervolgens de standaardprijs en annuleerde de geplande verhoging naar $3 en $15. Een stap die enkel logregels classificeert, heeft geen Opus nodig.

Reken er niet op dat gratis gebruik een druk schema opvangt. Afgezien van het kleine tegoed dat de Claude API bij aanmelding verstrekt, is de enige periodieke toelage het maandelijkse API-tegoed dat is inbegrepen bij Claude Max- en Team-abonnementen: $100 bij Max 5x, $200 bij Max 20x en tot $500 gezamenlijk bij Team, dat elke factureringscyclus wordt ververst. U kunt dit na 7 dagen op een in aanmerking komend abonnement claimen; een betaalmethode is niet vereist. Het dekt de Claude API, Managed Agents, de Agent SDK en de playground, maar niet Claude Code. Het tegoed vervalt aan het einde van elke cyclus en wordt niet meegenomen naar de volgende. Het verbruik telt mee voor uw bestedingslimiet; zodra het tegoed op is, stoppen verzoeken tenzij de organisatie ook aangekochte tegoeden bezit.

Effort is de tweede variabele. output_config.effort accepteert low, medium, high, xhigh en max, hoewel niet elk model elk niveau ondersteunt. De standaardwaarde is high op de meeste modellen en medium op Claude Opus 5.5 en Claude Haiku 5.5. Het expliciet instellen van de standaardwaarde van een model is gelijk aan het weglaten ervan. Een lagere effort-instelling bespaart meer dan alleen de redeneerduur: volgens de documentatie zorgt het ervoor dat Claude minder tool-aanroepen doet en meerdere operaties combineert in minder aanroepen. Bij een agent levert dit de grootste besparing op, omdat een vermeden tool-aanroep een volledig verzoek is dat niet plaatsvindt.

De valkuil is dat effort de cache tegenwerkt. Het wijzigen van de waarde op het hoogste niveau tussen verzoeken maakt prompt-caching ongeldig. In het gedocumenteerde voorbeeld bij Claude Opus 5.5 rapporteerde verzoek 2 cache_read_input_tokens: 3546. Verzoek 3 wijzigde de effort van medium, de standaardwaarde van dat model, naar low, en rapporteerde cache_creation_input_tokens van 3546 en cache_read_input_tokens van 0. Varieer de effort op het hoogste niveau dus per werklast, nooit binnen één gecachte conversatie. Twee methoden wijzigen de diepte zonder de cache te verbreken. Op Claude Fable 5.1, Opus 5.5, Opus 5, Sonnet 5.5 en Haiku 5.5 stelt een effort-wijziging per bericht (bèta, header mid-conversation-output-config-2026-07-01) een nieuw niveau in zonder het gecachte voorvoegsel aan te tasten. Bij elk model kunt u in de prompt zelf sturen: een regel als "Antwoord direct zonder na te denken." in het nieuwste gebruikersbericht laat de eerdere breakpoints intact. Op Claude Haiku 5.5 zorgt die zin er echter niet betrouwbaar voor dat het denkproces wordt verminderd.

Denk-tokens worden gefactureerd tegen outputtarieven en tellen mee voor max_tokens; daarom betekent een afgebroken antwoord vaak dat het denkproces het budget heeft verbruikt. Lees usage.output_tokens_details.thinking_tokens voor het aantal. Wat daadwerkelijk een Claude-tokenfactuur vult ontleedt de meter.

Cache het stabiele voorvoegsel en voorkom onbedoelde ongeldigverklaring

Een cache-schrijfactie kost 1,25 keer de basisprijs voor invoer bij de cache van vijf minuten en 2 keer bij de cache van één uur. Bij de meeste modellen kost een cache-leesactie 0,1 keer de prijs, waardoor "caching loont na één leesactie voor de duur van 5 minuten (1,25x schrijven), of na twee leesactie voor de duur van 1 uur (2x schrijven)". Leesacties zijn nog goedkoper bij de nieuwste modellen: 0,05 keer bij Claude Opus 5.5 en Claude Sonnet 5.5, en 0,025 keer bij Claude Fable 5.1.

Eén regel verklaart waarom dit geschikt is voor een altijd actieve agent: "De cache wordt zonder extra kosten ververst telkens wanneer de gecachte inhoud wordt gebruikt." Een taak die elke twee minuten wordt uitgevoerd tegen de cache van vijf minuten, houdt het voorvoegsel de hele dag warm voor slechts één schrijfactie.

Drie manieren om de cache te verliezen zonder het te merken.

Een voorvoegsel dat wijzigt. "Cache-voorvoegsels worden in de volgende volgorde aangemaakt: tools, system, vervolgens messages." Elke wijziging van een byte eerder in die volgorde maakt alles daarna ongeldig, en het bewerken van tool-definities maakt de gehele cache ongeldig. De klassieke fout is het opnemen van een tijdstempel of een run id in de system prompt: elk verzoek draagt dan een ander voorvoegsel, schrijft een nieuw item tegen 1,25x, en leest niets terug. De indicator is usage.cache_read_input_tokens op 0 bij verzoeken die er identiek uitzien. Verplaats de vluchtige tekst naar het nieuwste gebruikersbericht.

Een voorvoegsel dat te kort is. Elk model heeft een minimale cachebare lengte; daaronder wordt het verzoek verwerkt zonder caching en "wordt er geen foutmelding geretourneerd". De cijfers omvatten 512 tokens bij Claude Fable 5.1, Fable 5, Opus 5.5, Opus 5, Sonnet 5.5 en Haiku 5.5, 1.024 bij Claude Opus 4.8 en Claude Sonnet 5, en 4.096 bij Claude Haiku 4.5. Het verplaatsen van een taak van Sonnet 5 naar Haiku 4.5 kan caching dus geruisloos uitschakelen.

Een conversatie die buiten het terugkijkvenster groeit. "Het terugkijkvenster is 20 blokken." Het systeem controleert maximaal 20 posities per breakpoint en stopt daarna. In het gedocumenteerde voorbeeld controleert een beurt met 35 blokken met een breakpoint op blok 35 de blokken 35 tot en met 16; het item van de vorige beurt op blok 15 valt buiten het venster, waardoor er geen hit is. Een agent die per beurt meerdere tool-use en tool-result blokken toevoegt, overschrijdt de 20 blokken in twee of drie beurten. U krijgt vier breakpoints per verzoek, dus besteed er één aan de recente berichten.

Verstuur taken die kunnen wachten naar de Batches API

"Al het gebruik wordt gefactureerd tegen 50% van de standaard API-tarieven", zowel voor input als output. Batchverwerking is asynchroon, "waarbij de meeste batches binnen 1 uur zijn voltooid", met resultaten zodra elk verzoek is afgerond of na 24 uur, afhankelijk van wat zich het eerst voordoet. Dit is een indicatie, geen garantie.

Poll processing_status totdat de status ended aangeeft. Verzoeken die errored, canceled of expired retourneren, worden niet in rekening gebracht. Een kanttekening als u gebruikmaakt van een bestedingslimiet: "batches kunnen het geconfigureerde bestedingslimiet van uw Workspace licht overschrijden."

De kortingen zijn cumulatief, en omdat een batch langer dan vijf minuten kan duren, adviseert de documentatie de cache van één uur voor batches die context delen. Splits het werk daarom op: alles waar een persoon of een webhook op wacht, blijft op het live-pad, terwijl een nachtelijk overzicht of de classificatie van logbestanden van gisteren in een batch tegen de halve prijs wordt verwerkt.

Registreer elk gebruiksveld van een response in uw eigen opslag

U kunt geen kosten toewijzen die u niet heeft vastgelegd. Elke response geeft aan wat deze heeft gekost.

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-aanroep één rij toe aan een JSON-lines bestand, voorzien van uw jobnaam. Een week later kunt u bepalen welke job kosten maakt en welke alleen inactief lijkt. Let op cache_read: een kolom met nullen is de meest voorkomende kostenfout bij een zelfgehoste agent.

Eén veld is makkelijk verkeerd te interpreteren. input_tokens telt alleen de tokens na het laatste cache-breekpunt, dus de werkelijke promptgrootte is total_input_tokens = cache_read_input_tokens + cache_creation_input_tokens + input_tokens. Een agent die input_tokens: 400 rapporteert bij een grote prompt is niet goedkoop: de rest kwam uit de cache.

Tel voordat u verstuurt. Het tellen van tokens is gratis en de rate limits staan los van het aanmaken van berichten. Gebruik daarom count_tokens om een te groot bestand te weigeren in plaats van te betalen om erachter te komen. Het resultaat is een schatting, dus meet opnieuw per model en hergebruik nooit een telling van de tokenizer van een andere leverancier. Claude 4.7 en latere modellen, waaronder 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 eerder, waaronder Claude Haiku 4.5, gebruiken de vorige versie.

Voor een officieel overzicht rapporteert de Admin API het gebruik op https://api.anthropic.com/v1/organizations/usage_report/messages en de kosten op 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. Het gebruiksrapport accepteert bucket_width=1d, group_by[]=model en api_key_ids[]=. Het kostenrapport is alleen dagelijks beschikbaar en groepeert op workspace_id of description. Eén beperking: "De Admin API is niet beschikbaar voor individuele accounts."

Die api_key_ids[] parameter is een goedkope truc voor toewijzing: geef elke job een eigen API key, filter het gebruiksrapport met api_key_ids[] en splits het per key met group_by[]=api_key_id. Het filter is meervoudig, de groeperingsdimensie is enkelvoudig. Bewaar de keys in de omgeving in plaats van in de code, zoals een eerste Claude API app op een VPS ze verwerkt.

Begrens de lus, want niets anders doet dat

Een begrensde iteratieteller is hier niet optioneel. De lus is van u, dus de teller is ook 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 volstaat: max_tokens begrenst slechts één antwoord en het model wordt enkel geadviseerd over een taakbudget. Een gehost product zou u hier stoppen, op de manier waarop Claude's limiet op tool-aanroepen binnen één sessie een sessie beëindigt die er te veel heeft uitgevoerd, maar een lus die u zelf hebt geschreven wordt zonder dergelijke beveiliging geleverd totdat u deze toevoegt.

Plaats een tweede rem buiten het proces. Voer de taak uit via een systemd timer in plaats van een permanent proces en geef de service-unit een tijdslimiet. Een timer-taak is meestal Type=oneshot, en RuntimeMaxSec= "heeft geen effect op Type=oneshot services", dus stel daar TimeoutStartSec=600 in. Gebruik RuntimeMaxSec=600 alleen op een Type=simple unit. Hoe dan ook, een vastgelopen uitvoering wordt na tien minuten beëindigd in plaats van door te draaien totdat u het opmerkt. Een programma uitvoeren als systemd service en timer behandelt de unit-bestanden zelf. Lees wat een uitvoering heeft gedaan met journalctl -u triage-agent.service --since "1 hour ago".

Begrens ook het aantal pogingen, want een handler die oneindig blijft proberen, brengt elke poging in rekening. Een 429 of een 500 verdient enkele pogingen met backoff. Een 400 verdient er geen, aangezien hetzelfde verzoek op dezelfde manier zal falen.

Kostenbeheersing voor AI-agents begint bij het inzien van uw eigen cijfers

Niemand kan u vertellen wat een altijd actieve agent kost, omdat de kosten bestaan uit tokens per uitvoering vermenigvuldigd met het aantal uitvoeringen per dag, en beide variabelen zijn afhankelijk van uw gebruik. Voer de agent één keer uit, lees de gebruiksregel die u heeft gelogd en vermenigvuldig dit met uw planning. Controleer twee dagen later het kostenoverzicht en vergelijk dit met uw berekening. Wanneer deze niet overeenkomen, wordt het verschil bijna altijd veroorzaakt door een defecte cache of een lus die langer liep dan u had aangenomen.

Dit gaat uit van een API key, omdat de agent uw eigen programma is dat de Messages API aanroept. Voor uw eigen interactieve werkzaamheden behandelt welk Claude-abonnement past bij uw manier van werken de abonnementskant. Elke prijs en limiet in dit document is in oktober 2026 gecontroleerd aan de hand van de documentatie van Anthropic; lees daarom de prijspagina opnieuw door voordat u een budget opstelt.

FAQ

Wat kost het om een altijd actieve AI-agent op een VPS te draaien?

Er zijn twee kostenposten, waarvan er slechts één voorspelbaar is. De server heeft een vaste maandelijkse prijs. De model-API wordt per token afgerekend; de kosten zijn dus het verbruik van één run vermenigvuldigd met de frequentie. Anthropic publiceert geen cijfers voor een zelfgehoste, altijd actieve agent, dus beschouw elk genoemd bedrag als een schatting. Log usage van één echte run en vermenigvuldig dit met uw planning.

Wat is het verschil tussen max_tokens en een taakbudget?

max_tokens wordt afgedwongen en is onzichtbaar voor het model. Het begrenst de output van één verzoek, inclusief het denkproces, en het bereiken van deze limiet resulteert in stop_reason: "max_tokens". Een taakbudget is het tegenovergestelde: het model wordt op de hoogte gesteld van dit getal en stemt de agent-loop hierop af, maar "taakbudgetten zijn een zachte richtlijn, geen harde limiet" en de afgedwongen grens blijft max_tokens.

Waarom is cache_read_input_tokens altijd nul voor mijn agent?

Omdat het voorvoegsel verandert tussen aanroepen, of omdat het te kort is om te cachen. De gebruikelijke oorzaak is een tijdstempel of een run-id die in de systeem-prompt wordt geïnterpoleerd: de cache is gekoppeld aan het voorvoegsel, dus elke wijziging in een byte maakt alles wat daarna komt ongeldig. Het wijzigen van tool-definities of de effort-waarde op het hoogste niveau heeft hetzelfde effect. Anders is het de grootte, aangezien kortere prompts niet worden gecachet en er geen foutmelding wordt geretourneerd.

Hoe voorkom ik dat een AI-agent in een oneindige lus raakt?

Tel de iteraties in uw loop-code en stop bij een vast maximum, omdat max_tokens slechts één respons begrenst en een agent er vele maakt. Voeg een tijdslimiet toe buiten het proces: start de taak vanuit een systemd-timer en stel TimeoutStartSec= in op een oneshot-unit, of RuntimeMaxSec= op een eenvoudige unit, zodat een vastgelopen run volgens schema wordt beëindigd. Begrens ook het aantal pogingen, aangezien een retry-loop elke poging in rekening brengt.

Kan ik een bestedingslimiet instellen op een enkele Claude API-sleutel?

De gedocumenteerde bestedingslimiet geldt per werkruimte in plaats van per sleutel; geef de agent dus een eigen werkruimte en begrens daar de maandelijkse uitgaven. "U kunt geen limieten instellen op de Default Workspace". Voeg bestedingsmeldingen toe zodat een drempelwaarde u eerst waarschuwt. Voor toewijzing kunt u voor elke taak een eigen sleutel uitgeven en vervolgens het gebruiksrapport groeperen met group_by[]=api_key_id.