awtoll
Aither World Toll — what every tool call costs you in context, measured from your own agent transcripts rather than claimed in a README.
Every agent stack asserts that its search / graph / memory tool is cheaper than grepping and re-reading files. Almost nobody measures it. The claim ends up in a code comment, measured once during development and gated by nothing — so a tool can regress into costing more than the thing it replaced and every signal stays green.
awtoll reads the transcripts already on your disk and prints what you actually paid.
pip install awtoll # zero dependencies
pip install 'awtoll[exact]' # + tiktoken, for exact counts instead of estimates
awtoll scan # toll table: what each tool shape cost
awtoll repeats # toll you paid more than once
awtoll versus 'awgraph callers foo' 'grep -rn foo .'
awtoll check # gate: expensive shapes decided, waste ratcheting down
The unit
The toll is the number of tokens a tool call's result adds to your context. It is deterministic, needs no API key, and can be recomputed from a transcript months later.
shape calls ok total median p90
--------------------------------------------------------------------------------------
$ sed 650 645 271,868 308 827
$ grep 938 925 200,441 142 476
$ python -c (inline) 1927 1800 199,267 67 219
Read 63 63 46,586 378 1,265
The rule everything here is built around
A tool that answers nothing is the cheapest tool there is.
Rank tools by cost alone and the winner is whichever one is broken. So an ok toll is
never averaged together with an error, empty or truncated one. Those are counted,
printed, and held out — and a shape whose calls are mostly not-ok is flagged as
suspicious rather than celebrated as cheap.
There is a sixth outcome, opaque, and it exists because of a real false positive on this
tool's first run: a result made of structured blocks carrying no text is not an empty
answer, it is a cost a transcript cannot see. Rendering it to "" reported 36 perfectly
healthy tool-loading calls as broken. Opaque calls are excluded from the judgement, not
counted as failures.
Repeats — the strongest savings signal
The most defensible number here is not a model of what some other tool would have returned. It is the toll you demonstrably paid twice:
wasted x each shape / target
8,332 2 8,332 Read :: .../resume-all.md
3,675 8 525 Read :: .../swebench_awdk.py
Eight reads of one file in one session is 3,675 tokens of pure re-purchase. Repeats are scoped to a single session on purpose — re-reading a file next week is a new question, not waste, and counting it would flood the report.
Amplification: the toll is not what it costs
Every turn re-sends the whole context, so a token a tool admits early is paid for again on every turn after it. Measured across 12 real sessions: 1.67M tokens of tool results sat under 205M cumulative prompt tokens — a 123x multiple.
That figure is not a denominator and awtoll refuses to print it as one. An earlier version divided the two and displayed "1%", which reads as tool output is a rounding error when it means the opposite.
Counts are labelled
With tiktoken installed, counts are exact. Without it, awtoll uses 3.459 chars/token
— measured across 7,690 real tool results (median 3.463; the two agree, so the constant is
stable) — and labels every number ESTIMATED. Note that the folk constant of 4.0 would
understate every toll by ~13%: tool output is denser than prose.
Exit codes
| code | meaning |
|---|---|
| 0 | measured, nothing violated |
| 1 | a rule was violated |
| 2 | could not judge — no transcripts, no tool calls, unreadable ledger |
2 is never 0. A meter that found nothing and a meter that measured a healthy system look identical unless the tool refuses to call silence a pass.
The ledger
awtoll check turns the measurement into a gate. A toll table nobody decides anything
about is a dashboard: read twice, then never again.
awtoll check --init # writes awtoll.json pinned to today's waste ratio
awtoll check # gate
{
"decide_above_tokens": 50000,
"waste_ratio_pin": 0.012,
"decisions": {
"$ sed": { "status": "keep", "reason": "reading file slices is the job; the alternative is a whole-file Read" },
"Read": { "status": "replace", "with": "awgraph context — 8 reads of one file in one session" }
}
}
| rule | asserts |
|---|---|
| TL001 | every decision has a known status (replace, keep, watch) |
| TL002 | every status carries its second field — a reasonless decision is a hole dressed as a decision |
| TL003 | every shape above the threshold is decided |
| TL004 | no duplicate decision rows |
| TL005 | the repeat-waste ratio is pinned and ratchets down only |
Reading transcripts other than Claude Code's
The default root is ~/.claude/projects. Point somewhere else with --root (repeatable,
accepts a file or a directory) or AWTOLL_TRANSCRIPTS. The parser wants JSONL records with
tool_use / tool_result blocks paired by tool_use_id.
Results are paired by id, never by adjacency. Interleaved calls and sub-agent turns mean the next record is frequently not the answer to the previous call, and positional pairing produces a table that looks entirely reasonable while attributing every cost to the wrong tool.
Proving it still works
awtoll self-test
Every arm asserts a positive (the rule fires on the broken shape) and, where the rule could over-fire, a negative (it stays quiet on the healthy one). A rule that always fires is as useless as one that never does — the first floods and gets switched off, the second is decoration.
License
Apache-2.0
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file awtoll-0.1.1.tar.gz.
File metadata
- Download URL: awtoll-0.1.1.tar.gz
- Upload date:
- Size: 41.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b09b105485231da5cf3e882700d08c83690611fef83e81e333323baa70ab2a1
|
|
| MD5 |
4b7e8ac027c10e9c8f34c3eff9b337d1
|
|
| BLAKE2b-256 |
b154e05e211e9400aed63fe6040d9f40c73d8061a94486cc6e85813e9c2ea781
|
File details
Details for the file awtoll-0.1.1-py3-none-any.whl.
File metadata
- Download URL: awtoll-0.1.1-py3-none-any.whl
- Upload date:
- Size: 40.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a499661f8ba4e1f4421bb03bb12f6d699acd133c3880420606d1dd23c17135ba
|
|
| MD5 |
64b78814101fdd480bc37e2cd8e0c6a9
|
|
| BLAKE2b-256 |
28b33e65174c32c13936bff9882bedd496507098ed366bb0cafc9dc8893c5e33
|