Rubric
Contents — domains, guide and mocks

Cost and token management

CCDV-F 5.415 min read · checked 21 September 2026

Task statementCost and Token Management (2.8%) — token budgeting, usage tracking, cost modelling, and caching techniques including prompt caching and cache check-pointing

Where the money goes in one request

priced separately, top to bottom

  1. Cache readsa fraction of base input price
  2. Cache writesslightly more than base input price
  3. Uncached inputbase input price, paid every call
  4. Output tokensseveral times the input price
Output is the dearest per token; the front of the input is the largest and the most repeated. Those two facts drive every optimisation here.

Token budgeting starts before the call

Budgeting means deciding what a request is allowed to cost before you send it, rather than discovering it afterwards. The API gives you a free token-counting endpoint for exactly this: client.messages.count_tokens(...) accepts the same model, system, tools and messages you were about to send and returns input_tokens. It is free, separately rate-limited from message creation, and includes system prompts, tools, images and PDFs. The documentation is careful to call it an estimate — close enough to budget with, not a billing oracle.

Check the size before you pay for itpython
# Free, and rate-limited separately from messages.create.
count = client.messages.count_tokens(
    model=MODEL, system=SYSTEM, tools=TOOLS, messages=messages,
)

if count.input_tokens > INPUT_BUDGET:          # your own ceiling, not the API's
    messages = compact(messages)               # summarise or drop older turns

resp = client.messages.create(
    model=MODEL, max_tokens=2000,              # bounds output, and so the worst case
    system=SYSTEM, tools=TOOLS, messages=messages,
)

u = resp.usage
total_input = u.input_tokens + u.cache_read_input_tokens + u.cache_creation_input_tokens
log.info("spend", total_input=total_input, output=u.output_tokens)

max_tokens is the other half of the budget, and the more important one, because output costs several times what input costs on every model. It caps the worst case of a single call. Where thinking is enabled it is a shared ceiling — reasoning tokens are output tokens — so a generous thinking budget inside a tight max_tokens buys reasoning at the expense of the answer.

Usage tracking: per request, and across the organisation

Every response carries a usage object, and it is the only honest per-request record of what you spent. Four fields do the work: input_tokens, output_tokens, cache_creation_input_tokens and cache_read_input_tokens. One detail catches everyone out — once caching is in play, input_tokens counts only the portion after your last cache breakpoint. Total input is the sum of all three input fields, so a monitor that plots input_tokens alone will appear to show costs collapsing at the moment caching starts working.

QuestionWhere the answer lives
What did this one call cost?usage on the response
How much of the output was reasoning?usage.output_tokens_details.thinking_tokens
Which customer or feature is expensive?Your own logs, keyed by metadata.user_id and your correlation id
What did the organisation spend, by model or workspace?The Usage API, grouped by model, workspace, API key or service tier
What is the bill in money, by day?The Cost API — daily granularity, admin credentials

The organisation-level endpoints are /v1/organizations/usage_report/messages and /v1/organizations/cost_report. Both need an Admin API key — a workspace key will not do — and they answer different questions. The usage report gives token counts at minute, hour or day granularity and can be grouped by model, workspace, API key or service tier; the cost report gives money, daily only. Data appears within a few minutes of a request completing, so these are for reporting and alerting, not for enforcing a per-request limit.

Two levels of cost visibility

Per request — your code

  • usage on every response
  • Attribute to a user, tenant or feature
  • Available immediately, enforce limits on it
  • Only as good as what you log

Per organisation — Admin API

  • Usage report: tokens by model, workspace, key
  • Cost report: money, daily
  • Admin credential, not a workspace key
  • A few minutes behind; for reporting, not gating
Neither replaces the other. Attribution needs your own keys and labels; totals need the admin endpoints.

A practical consequence: separate API keys and workspaces per environment and per major workload are a cost-attribution tool as much as a security one. Grouping the usage report by key only tells you something if your keys mean something. Key and workspace hygiene itself is 7.4.

Prompt caching, and where the breakpoint goes

Prompt caching stores a prefix of your request so later requests that begin identically can re-read it instead of reprocessing it. You mark the end of the cacheable prefix with a breakpoint: cache_control with type ephemeral on the last block that stays the same from request to request. Up to four explicit breakpoints are allowed per request.

The order the API assembles a request in is fixed — tools, then system, then messages — and caching follows that order. A change at any level invalidates that level and everything after it: edit a tool definition and the system prompt and messages caches go with it. This is why the stable material belongs at the front and the volatile material at the back, which is a prompt-structuring decision more than a caching one.

Cache order: stable at the front, volatile at the back

assembled in this order

  1. Toolsrarely change — cache first
  2. System promptstable instructions and policy
  3. Long contextthe manual, the codebase, the file
  4. Conversation historygrows each turn
  5. The new user turndifferent every time
A breakpoint caches everything above it. Change something high up and every cache below it is discarded too.

Three numbers shape whether caching is worth it. There is a minimum cacheable length that varies by model — from a few hundred tokens on the largest models to a few thousand on the fastest ones — below which nothing is cached at all. A cache write costs slightly more than ordinary input, and more again for the longer time-to-live. A cache read costs a small fraction of base input price. So caching pays as soon as a prefix is reused even a couple of times, and costs you a little if it is never reused.

SettingWhat it doesWhen to use it
{"type": "ephemeral"}Default lifetime of about five minutes, refreshed on each hitInteractive sessions, agent loops, anything with continuous traffic
{"type": "ephemeral", "ttl": "1h"}One-hour lifetime at a higher write costGappy traffic — a document a reviewer returns to every twenty minutes
No breakpointNothing is cached; every token is fresh inputOne-off requests, or prefixes below the model's minimum

The same prompt, cached and uncached

Never hitstext

system=[
 {"text": POLICY_10K_TOKENS},
 {"text": f"Today is {today}",
  "cache_control":
    {"type": "ephemeral"}}
]
# Breakpoint is after a line
# that changes daily, so the
# prefix hash is new each day
# and the 10k policy is
# rewritten, never read.

Hits from the second calltext

system=[
 {"text": POLICY_10K_TOKENS,
  "cache_control":
    {"type": "ephemeral"}}
]
messages=[
 {"role": "user",
  "content": f"Today is {today}.
    {question}"}
]
# Stable prefix cached;
# the volatile line moved
# behind the breakpoint.
The only difference is which block carries cache_control — and whether the changing line sits before or after it.

Cache checkpointing across a conversation

A conversation is the awkward case, because it grows. Each turn appends the assistant's reply and a new user message, so a prefix that ended at the last turn is no longer the whole of the stable part. The technique the objective calls cache check-pointing is to move the breakpoint forward each turn: cache up to the end of the previous turn, so the next request reads everything up to there and writes only what is new.

Moving the checkpoint forward each turn

  1. Turn 1system + turn 1 written to cache
  2. Turn 2read turn 1; write turn 2 only
  3. Turn 3read turns 1–2; write turn 3
  4. Breakpoint movesalways ends at the last stable block

each turn: read the prefix, write the increment

Each turn reads the whole conversation so far from cache and writes only the increment — instead of reprocessing the history at full price.

With four breakpoints available, a typical agent uses them as a hierarchy rather than all at once: one after the tool definitions, one after the system instructions, one after any long retrieved context, and one moving forward through the conversation. They then invalidate independently and at the rate each one actually changes.

Traps the wrong answers are built from

Tempting but wrongDo this instead
Placing the cache breakpoint after a timestamp or user nameMark the last block that is identical between requests; move volatile text behind it.
Plotting input_tokens alone as your cost metricSum input_tokens, cache_read_input_tokens and cache_creation_input_tokens.
Estimating tokens by character count for a budgetUse the free token-counting endpoint against the model you will actually call.
Caching a prefix below the model's minimum cacheable lengthCheck the model's minimum; a short prefix is never cached and the breakpoint does nothing.
Reordering tools or editing the system prompt per requestKeep the prefix byte-identical; changes high in the order invalidate everything after them.
Using the Cost API to enforce a per-request spend limitGate on usage in your own code; the admin endpoints are minutes behind and are for reporting.

You should now be able to

  • Budget a request with the token-counting endpoint and an explicit max_tokens.
  • Read every usage field correctly, including what input_tokens excludes when caching is on.
  • Build a cost model from measured usage and current per-token prices.
  • Place cache breakpoints on the last stable block, and order tools, system and messages to suit.
  • Apply cache check-pointing across conversation turns and explain what invalidates a cache.
  • Choose between per-request tracking and the organisation Usage and Cost APIs for a given question.

Practice questions

Original questions written for this lesson, in the exam’s style. Answer first, then open the reasoning — every option is explained, including why the wrong ones are tempting.

  1. Question 1

    A documentation assistant sends a 30,000-token product manual in the system prompt, followed by a block containing the current date, which carries cache_control. The user's question is in messages. Cache creation tokens are high on every request and cache read tokens are always zero.

    What explains this, and what fixes it?

    1. AThe manual is larger than the cache limit; split it across two breakpoints.
    2. BThe breakpoint sits after content that changes daily; move it onto the manual.
    3. CThe five-minute lifetime expires between requests; request the one-hour lifetime.
    4. DCaching requires the content to be in messages rather than system.
    Show answer and reasoning
    1. AIncorrect. There is no size ceiling being hit here, and splitting would not change the hash of a prefix that varies.
    2. BCorrect. The cache matches on a hash of the whole prefix ending at the breakpoint, so a changing date makes every prefix unique.
    3. CIncorrect. Expiry would show occasional reads, not permanent zeroes, and would not explain writes on every call.
    4. DIncorrect. System blocks are cacheable; order matters, location within system does not disqualify it.
  2. Question 2

    After enabling prompt caching, a dashboard that plots input_tokens per request shows a dramatic drop, and the team reports a 95% cost saving to their manager. The monthly invoice falls by rather less.

    What is wrong with the measurement?

    1. ACached tokens are free, so the invoice should have fallen by the full amount.
    2. Binput_tokens excludes cached tokens, so the dashboard is not measuring total input.
    3. CThe invoice lags usage by several days, so the saving has not appeared yet.
    4. DOutput tokens rose to compensate for the shorter input.
    Show answer and reasoning
    1. AIncorrect. Cache reads are charged at a reduced rate, not at zero, and writes cost slightly more than base input.
    2. BCorrect. Once a breakpoint is set, input_tokens counts only the portion after it; the cache fields hold the rest.
    3. CIncorrect. Usage data appears within minutes; a persistent gap is a measurement error, not a delay.
    4. DIncorrect. Nothing about caching changes how much output the model generates.
  3. Question 3

    A finance team asks for a monthly report of spend per product team. Each team has its own API key, and all of them share one workspace. An engineer proposes summing the usage fields their services already log.

    Which two approaches will answer the question? (Select 2.)

    1. AQuery the Usage API grouped by API key, using an Admin API key.
    2. BAggregate the logged usage fields per service and price them per model.
    3. CQuery the Cost API grouped by API key for money rather than tokens.
    4. DUse a workspace API key to call the Usage API for each team.
    5. ERead the per-request usage object from the Console after the fact.
    6. FPoll the Cost API every minute and attribute spend by arrival time.
    Show answer and reasoning
    1. ACorrect. The usage report supports grouping by API key, which maps directly onto teams in this setup.
    2. BCorrect. Per-request usage is authoritative for attribution, provided every call is logged and priced correctly.
    3. CIncorrect. The cost report groups by workspace and description; it does not break spend down by key.
    4. DIncorrect. The organisation endpoints require admin credentials; workspace keys are rejected.
    5. EIncorrect. The Console shows aggregate reporting; it does not retain per-request usage objects for you to attribute.
    6. FIncorrect. Arrival time does not identify a team, and the endpoint is daily-granularity anyway.
  4. Question 4

    An agent holds long conversations with a stable system prompt, a fixed set of tools and a history that grows by roughly 800 tokens per turn. Today it sets a single breakpoint at the end of the system prompt.

    What change most reduces cost over a twenty-turn conversation?

    1. AAdvance a second breakpoint to the end of the previous turn on each request.
    2. BRaise the cache lifetime to one hour on the system prompt breakpoint.
    3. CSummarise the conversation into the system prompt every few turns.
    4. DMove the tool definitions after the system prompt in the request.
    Show answer and reasoning
    1. ACorrect. This is cache check-pointing: the growing history is read from cache and only the newest increment is written.
    2. BIncorrect. It helps across gaps, but the history — the part that grows — is still reprocessed at full price every turn.
    3. CIncorrect. It shortens history but rewrites the cached prefix each time, invalidating the cache it depends on.
    4. DIncorrect. The assembly order is fixed at tools, system, then messages; you cannot reorder those levels.

Sources

Drafted with AI assistance and checked against the sources above; expert review is in progress. Spotted an error? Tell us and it gets fixed, dated and listed on how this is written.