# Token Desk > Read a prompt written one part at a time and see what the whole thing costs. A > conversation bills the SQUARE of its own turn count, because every turn re-sends the > whole history: a 2,000-token prompt over 30 turns bills 327,000 input tokens while > the final context is only 20,000. A few-shot example is a per-call cost, not a > one-off. The window holds input AND output, so the input ceiling is the window minus > the maximum output. A cache breakpoint covers a PREFIX, so one volatile line at the > top makes all of it uncacheable - and below one call per TTL caching is a 25% > surcharge rather than a saving. Free browser-side arithmetic, five paid lanes, and no > model is called. Live at https://token-desk.skillsafe.ai/ · API at https://token-desk.skillsafe.ai/api.html Derived from the `context-window-management` and `prompt-caching` skills in `sickn33/antigravity-awesome-skills` and the `token-budget-advisor` skill in `affaan-m/everything-claude-code`. Not affiliated with or endorsed by their authors. ## The one thing to know **A prompt is priced per call and a conversation is priced per turn - and the second one is quadratic.** ```text turns billed in final context ratio 5 17,000 5,000 3.4× 10 49,000 8,000 6.13× 20 158,000 14,000 11.3× 30 327,000 20,000 16.4× 50 845,000 32,000 26.4× ``` A 2,000-token prompt with 200 in and 400 out per turn. Every turn re-sends the whole history, so the bill is `N × (fixed + in) + traffic × N(N−1)/2` while the context you can see is `fixed + N × traffic`. At 30 turns that is 327,000 billed against 20,000 held - 16.4×. A linear guess would have been 66,000. **A few-shot example is a per-call cost, not a one-off.** ```text examples per call per day per year 2 500 5,000,000 $5,475 4 1,000 10,000,000 $10,950 8 2,000 20,000,000 $21,900 16 4,000 40,000,000 $43,800 32 8,000 80,000,000 $87,600 ``` 8 examples at 250 tokens is 2,000 tokens on every single call, or $21,900 a year at 10,000 calls a day - for the setup half of the prompt. **The window is not the input budget.** ```text model shape input ceiling turns fit if you forget 8k window, 4k output 4,096 4 10 128k window, 4k output 123,904 203 210 200k window, 8k output 191,808 317 330 200k window, 64k output 136,000 224 330 1M window, 64k output 936,000 1557 1664 ``` It holds input AND output, so a 200k window with a 64k maximum output leaves 136,000 for input: 224 turns fit where planning against the whole window promised 330, an overestimate of 47.3% - discovered mid-session as a rejected request rather than as a warning. **Caching below a call rate is a surcharge, not a saving.** ```text rate hits/write cached uncached saving 6/h 0 2,500 2,000 +25% 12/h 0 2,500 2,000 +25% 30/h 2 2,900 6,000 51.7% 1/min 4 3,300 10,000 67% 5/min 24 7,300 50,000 85.4% 60/min 299 62,300 600,000 89.6% ``` A write costs 1.25× and a hit 0.1×, so one hit pays for one write - but a hit needs the next call inside the 5m TTL. At or below 12/h (`rate × ttl` must be strictly greater than 1) every call is a write and caching costs exactly 25% more (2 of the 6 rates above) , while at 30/h it is 51.7% cheaper. Two other things stop a cache silently: a prefix below 1,024 tokens cannot be cached at all, and a breakpoint covers a PREFIX - so a volatile line at the top makes all of the prompt below it uncacheable, however it is marked. **And output is the expensive token, with an exact cross-over.** ```text model class in/out ratio output = 10,000 input cheap class $0.25/$1.25 5× 2,000 mid class $3/$15 5× 2,000 frontier class $15/$75 5× 2,000 reasoning class $3/$60 20× 500 ``` At 5× the output half of the bill overtakes the input half at `out = in ÷ 5`, so 10,000 in and 2,000 out is exactly 50/50; on a reasoning class at 20× it is 500 out. Past that point shortening the prompt cannot move the bill much and shortening the answer can. ## What a conversation bills | Turns | Input tokens billed | Final context | Billed ÷ context | A linear guess | | --- | --- | --- | --- | --- | | 5 | **17,000** | 5,000 | 3.4× | 11,000 | | 10 | **49,000** | 8,000 | 6.13× | 22,000 | | 20 | **158,000** | 14,000 | 11.3× | 44,000 | | 30 | **327,000** | 20,000 | 16.4× | 66,000 | | 50 | **845,000** | 32,000 | 26.4× | 110,000 | One prompt shape: 2,000 fixed, 200 in and 400 out per turn. **Every turn re-sends the whole history**, so the bill is `N × (fixed + in) + traffic × N(N−1)/2` while the context you can see is `fixed + N × traffic`. At 50 turns that is 845,000 billed against 32,000 held - **26.4×**. The last column is what a reader who assumed it was linear would have budgeted, and it is wrong in the cheap direction. ## The window against the input budget | Model shape | Input ceiling | Reserved for output | Turns that fit | Turns if you forget | Overestimate | | --- | --- | --- | --- | --- | --- | | 8k window, 4k output | **4,096** | 50% | 4 | 10 | 150% | | 128k window, 4k output | **123,904** | 3.2% | 203 | 210 | 3.45% | | 200k window, 8k output | **191,808** | 4.1% | 317 | 330 | 4.1% | | 200k window, 64k output | **136,000** | 32% | 224 | 330 | 47.3% | | 1M window, 64k output | **936,000** | 6.4% | 1557 | 1664 | 6.87% | **The window holds input AND output.** The input ceiling is the window minus the maximum output, so planning a conversation against the number in the model card overestimates how many turns fit by exactly the reservation's share - up to 150% on the 8k window, 4k output row. The conversation then dies at the lower number, mid-session, as a rejected request rather than as a warning. ## When caching pays | Request rate | Hits per write | Cached | Uncached | Saving | | --- | --- | --- | --- | --- | | 6/h | 0 | 2,500 | 2,000 | **25% DEARER** | | 12/h | 0 | 2,500 | 2,000 | **25% DEARER** | | 30/h | 2 | 2,900 | 6,000 | 51.7% cheaper | | 1/min | 4 | 3,300 | 10,000 | 67% cheaper | | 5/min | 24 | 7,300 | 50,000 | 85.4% cheaper | | 60/min | 299 | 62,300 | 600,000 | 89.6% cheaper | A 2,000-token prefix on a 5m cache, in token-equivalents per TTL window. A write costs 1.25× an ordinary input token and a hit 0.1×, so **one hit pays for one write** - but a hit needs the next call to arrive INSIDE the TTL. At or below 12/h - `rate × ttl` has to be strictly greater than 1 - there is never a hit and caching is a flat 25% surcharge. The sign of the answer is a property of your traffic, not of your prompt. ## Where output overtakes input | Model class | In / out per Mtok | Ratio | Output that equals 10,000 input | Each half | | --- | --- | --- | --- | --- | | cheap class | $0.25 / $1.25 | 5× | **2,000 tokens** | $0.0025 | | mid class | $3 / $15 | 5× | **2,000 tokens** | $0.03 | | frontier class | $15 / $75 | 5× | **2,000 tokens** | $0.15 | | reasoning class | $3 / $60 | 20× | **500 tokens** | $0.03 | Output costs several times input, so **the output half of the bill overtakes the input half at a ratio rather than at a size**: at `out = in ÷ ratio`. Past that point shortening the prompt cannot move the bill much and shortening the answer can - and people optimise the prompt, because it is the part they wrote. ## What a few-shot block costs | Examples | Tokens per call | Tokens per day | Cost per day | Cost per year | | --- | --- | --- | --- | --- | | 2 | **500** | 5,000,000 | $15 | $5,475 | | 4 | **1,000** | 10,000,000 | $30 | $10,950 | | 8 | **2,000** | 20,000,000 | $60 | $21,900 | | 16 | **4,000** | 40,000,000 | $120 | $43,800 | | 32 | **8,000** | 80,000,000 | $240 | $87,600 | 250 tokens per example at 10,000 calls a day and $3/Mtok in. **An example is a per-call cost, not a one-off.** It reads as one line on a sheet and as setup in a review, and it is re-sent in full on every single request - so its cost scales with the traffic rather than with the number of examples. Doubling the examples doubles a line item that nobody has a line item for. ## Constants and thresholds | Constant | Value | What it decides | | --- | --- | --- | | `BIG_PART_SHARE` | 25% | how much of one call a repeated part can be before it is worth naming | | `BIG_RESERVE_SHARE` | 25% | how much of the window the output reservation can take before it is worth naming | | `DEFAULT_WINDOW` | 200k | the assumed window | | `DEFAULT_MAX_OUTPUT` | 64k | the assumed output reservation, which the input cannot use | | `DEFAULT_PRICE_IN` / `OUT` | $3 / $15 | the assumed prices per million tokens | | `DEFAULT_CACHE_TTL_S` | 5m | the cache lifetime, which sets the rate floor at 12/h | | `DEFAULT_CACHE_WRITE` / `READ` | 1.25× / 0.1× | what a write and a hit cost against an ordinary input token | | `DEFAULT_CACHE_MIN` | 1,024 | the shortest prefix that can be cached at all | | `DEFAULT_TURNS` | 20 | the assumed conversation length | | `DEFAULT_RATE_PER_MIN` | 1/min | the assumed request rate, which is the whole of the cache question | None of these changes a token count, a price or a ratio - those are arithmetic on the sheet you pasted. The thresholds decide only which of the exact facts gets called a warning, and the defaults decide only what is assumed when the sheet is silent - which is always said out loud rather than folded in. ## Sheet grammar A sheet is a header of `KEY: value` lines, then a `PROMPT:` block with **one part per line, in the order the prompt is assembled**. The order is load-bearing: it is what decides where the cacheable prefix ends. ```text JOB: the support assistant, as it is deployed today WINDOW: 200k the model's context window MAX-OUTPUT: 64k what the input may NOT use PRICE: in=3 out=15 dollars per million tokens TURNS: 30 how long a conversation runs RATE: 10/day the request rate - the whole cache question CACHE: ttl=5m min=1024 write=1.25 read=0.1 PROMPT: timestamp tokens=40 volatile=yes system tokens=1800 cached=yes examples tokens=250 count=8 cached=yes tools tokens=600 cached=yes question tokens=200 per=turn answer tokens=400 per=turn kind=output ``` **Header keys.** `WINDOW:` and `MAX-OUTPUT:` take `8192`, `128k` or `1M`; assumed 200k and 64k. `PRICE:` takes `in=` and `out=` in dollars per million tokens; assumed $3 and $15. `TURNS:` is a count; assumed 20. `RATE:` takes `10/min`, `600/h` or `10000/day`; assumed 1/min. `CACHE:` takes `ttl=`, `min=`, `write=` and `read=`. `JOB:` and `NOTE:` are free prose and are read as headers rather than as broken lines. Anything else is reported by name rather than ignored. **Part properties.** `tokens=` is required and takes `1800`, `1.8k` or `2M`. `count=` multiplies it - that is what makes a few-shot block a per-call cost. `per=turn` says the part is re-sent as the conversation grows. `kind=output` says it is generated rather than sent, and is priced at the output price. `volatile=yes` says it changes every call, which ends the cacheable prefix at its position. `cached=yes` is what you INTENDED - whether it can be is what this page works out. **What a part with no `tokens=` does.** It is dropped, and named. Every total is then smaller than the truth, which is the direction that matters - so it is an error rather than a note. ## Lanes | Lane | What it produces | | --- | --- | | `plan` | Design a prompt the window and the budget can pay for | | `read` (primary) | What this prompt actually costs, per call and per conversation | | `turns` | The conversation: what it bills as it grows, and where it stops fitting | | `cache` | The cache: where the prefix really ends, and whether it pays | | `decide` | Decide what changes: a part, the order, or the model | ## A worked sheet ```text JOB: the support assistant, as it is deployed today WINDOW: 200k MAX-OUTPUT: 64k PRICE: in=3 out=15 TURNS: 30 RATE: 10000/day CACHE: ttl=5m min=1024 PROMPT: timestamp tokens=40 volatile=yes system tokens=1800 cached=yes examples tokens=250 count=8 cached=yes tools tokens=600 cached=yes question tokens=200 per=turn answer tokens=400 per=turn kind=output ``` | Part | Written as | Adds to one call | Share of the input | In the prefix? | | --- | --- | --- | --- | --- | | `timestamp` | 40, **volatile** | 40 | 0.86% | no | | `system` | 1,800 | 1,800 | 38.8% | **no, though marked cached** | | `examples` | 250 × 8 | 2,000 | 43.1% | **no, though marked cached** | | `tools` | 600 | 600 | 12.9% | **no, though marked cached** | | `question` | 200, per turn | 200 | 4.31% | no | | `answer` | 400, output | — (generated) | — | — | The sheet in the worked example. 6 parts, 4,640 in / 400 out, $0.0199 a call, $1.38 over 30 turns, 17.8× the final context, prefix ends at timestamp, prefix below the cache minimum. **Read the last column against the second**: the prefix ends at the first part that changes, so `timestamp` decides how much of the rest can be cached - and three parts here are marked cached that never are. ## Findings | Finding | Severity | Scope | What it says | | --- | --- | --- | --- | | `NO-PROMPT-TO-READ` | error | sheet | The sheet declares no parts | | `A-PART-HAS-NO-TOKEN-COUNT` | error | part | A part declares no token count | | `THE-SHEET-HAS-LINES-THIS-PAGE-COULD-NOT-READ` | warning | sheet | Some lines were not understood | | `THE-WINDOW-WAS-NOT-DECLARED` | note | sheet | The window and the maximum output were assumed | | `THE-PRICE-WAS-NOT-DECLARED` | note | sheet | The prices were assumed | | `THE-RATE-WAS-NOT-DECLARED` | note | sheet | The request rate was assumed | | `WHAT-EACH-PART-COSTS` | note | part | Every part, its multiplier and what it adds to one call | | `A-FEW-SHOT-BLOCK-IS-A-PER-CALL-COST` | warning | part | A repeated part is a large share of every call | | `A-PART-IS-SENT-EVERY-TURN` | note | part | A part is re-sent as the conversation grows | | `WHAT-ONE-CALL-COSTS` | note | call | One call, in tokens and in money, input against output | | `THE-OUTPUT-HALF-IS-THE-LARGER-ONE` | warning | call | Output is the larger half of this bill | | `THE-CALL-DOES-NOT-FIT-THE-WINDOW` | error | call | One call's input already exceeds the input ceiling | | `THE-CONVERSATION-IS-QUADRATIC` | note | turns | What the conversation bills against what it holds | | `WHAT-THE-WHOLE-CONVERSATION-COSTS` | note | turns | The conversation's own bill, input and output | | `THE-CONVERSATION-RUNS-OUT-OF-WINDOW` | warning | turns | The conversation stops fitting before the turn count asked for | | `THE-WINDOW-IS-NOT-THE-INPUT-BUDGET` | warning | turns | The output reservation takes a large share of the window | | `THE-CACHEABLE-PREFIX-IS-SHORTER-THAN-IT-LOOKS` | warning | cache | A part that changes ends the cacheable prefix early | | `A-VOLATILE-PART-IS-MARKED-CACHED` | warning | cache | A part marked cached falls outside the prefix | | `THE-PREFIX-IS-BELOW-THE-CACHE-MINIMUM` | warning | cache | The prefix is too short to cache at all | | `CACHING-IS-A-SURCHARGE-AT-THIS-RATE` | warning | cache | At this request rate caching costs more than not caching | | `WHAT-CACHING-SAVES` | note | cache | What the cache does to the bill at this rate | | `THE-BREAK-EVEN-HIT-COUNT` | note | cache | How many hits pay for one write | 22 findings: 3 errors, 9 warnings and 10 notes. **Nothing that fires on every usable sheet is a warning.** Every prompt has a per-call cost, a conversation total and a prefix that ends somewhere - so those are notes. What gets a warning is a repeated part that dominates the call, a conversation that stops fitting, an output reservation large enough to change the turn count, a prefix cut shorter than the prompt allows, a `cached=yes` that can never take effect, a prefix below the minimum, and caching at a rate where it is a surcharge. ## What this page cannot do **A token count is whatever your tokeniser said.** This page does not tokenise and cannot: it has no model's vocabulary, and the same text is a different count on every family. Every figure here is arithmetic on the counts YOU pasted, so a count that is 10% out makes every figure 10% out in the same direction. **Every figure is the worst case of its own shape, not a measurement.** The conversation total assumes every turn happens and every turn is the size you gave. A real conversation ends early, varies per turn, and is cheaper - the point of the number is the SHAPE, which is quadratic whatever the constants are. **The cache terms are the published ones, not a measurement of your account.** A write at 1.25×, a hit at 0.1×, a 5m TTL and a 1,024-token minimum. They differ by provider and by tier, and the whole cache answer moves with them - so state your own in `CACHE:` rather than trusting the defaults. **A request rate is not a traffic model.** Real traffic is bursty, so a rate below the floor can still produce cache hits inside a burst and a rate above it can still miss during a lull. What this page gives you is the AVERAGE case and, more usefully, the sign of the answer - which flips at a rate you can now name. **It has not seen your code, your gateway or your bill.** No claim about whether the history is really re-sent in full, whether your client trims it, whether your framework sets a cache breakpoint at all, or what your negotiated prices are. The quadratic assumes a plain re-send, which is the default in every SDK and the thing worth checking first. **And it models one linear conversation.** Branching, retries, tool loops and parallel sub-agents each multiply the call count on top of everything here, and none of them is on this sheet. ## API `POST https://api.skillsafe.ai/v1/app-api/run` with an app session token. The body IS the input object — never wrapped in an `input` key. Fields: `task` (one of `plan`, `read`, `turns`, `cache`, `decide`), `rules`, `prescan`, plus the lane's own fields. `POST .../estimate` with the same body returns `hold_credits` and costs nothing. ## Provenance Every table and every figure above is generated from `spend.js` by `build-skill.js`. Nothing is typed twice, so nothing can drift.