Skip to main content

traceroutine

Process mining for LLM agent traces — where the tokens and the time actually go.

Observability platforms attribute spend by who: per user, per team, per API key. traceroutine attributes it by how — per execution path.

An agent's cost is a property of its trajectory, not of its request.

The report: where the money went, path by path

One command, zero instrumentation

If you use Claude Code, the data is already on your disk. No exporter, no collector, no account, no arguments:

$ uvx traceroutine
reading ~/.claude/projects as claude-code — nothing leaves this machine
483 cases · 335 paths · $849.06 at list prices · rework 89.2% -> report.html
  1. Results of `tool:Bash` carry 12% of the budget through context (up to $105.23)
  2. Loop `chat → tool:Edit` runs an extra time (up to $51.33)
  3. Working rhythm `chat → tool:Bash` — 41% of the budget

Three seconds, and that is my own history. The first finding is the whole thesis:

Results of tool:Bash carry 12% of the budget through context. The step itself burns no tokens and shows as $0.00 in every cost breakdown. But each of its results adds ~1,391 tokens to the prompt, and those are re-read on every subsequent turn: 129M tokens carried in total. Fix by truncating output, not by switching models.

A tool call costs nothing when it happens and keeps costing for the rest of the run. That is why the unit of cost is the path, not the request.

Context re-reading is a known phenomenon — vendors document it. What is missing everywhere else is the attribution: not "context grows", but which step's results carried how many dollars across the rest of the trajectory.

The dollars are API list prices, not an invoice. I pay a $20 subscription, so this is what those tokens would have cost — which is its own small finding: a flat fee hides a month that prices out at $849. Cross-checked against ccusage on the same instant: the two agree to 0.05% on the total and to within 0.25% on every token category.

The shape of the work

A usage dashboard gives you a number. This gives you the shape it came from — the same run as above, rendered by GitHub straight out of report -f md, no image involved:

flowchart TD
    S(["▶ start"])
    n0["chat<br/>7,096× · $849.06"]
    n1["tool:Bash<br/>4,422×"]
    n2["tool:Edit<br/>1,060×"]
    n3["tool:Read<br/>617×"]
    n4["tool:Write<br/>392×"]
    E(["■ end"])
    n0 -->|4257| n1
    n1 -->|4237| n0
    n0 -->|1049| n2
    n2 -->|1049| n0
    n0 -->|603| n3
    n3 -->|596| n0
    S -->|483| n0
    n0 -->|440| E
    n0 -->|390| n4
    n4 -->|388| n0
    n1 -->|143| n1
    classDef hot fill:#b4322e,stroke:#7d1f1c,color:#fff
    classDef err stroke:#d97706,stroke-width:3px
    class n0 hot
    class n1,n2,n3,n4 err

Everything returns to chat, because that is what a coding agent is: 4,257 calls out to tool:Bash and 4,237 back. That traffic is the 41% of the budget in finding 3 — not an anomaly but the working rhythm, and it only reads as a rhythm once it is drawn. tool:Bash also follows itself 143 times: commands issued back to back with no model turn in between. Amber outlines mark activities that produced errors.

Steps shown without a dollar figure spend no tokens at the moment of the call. That is not the same as free — their results stay in the prompt and are re-read on every later turn, which is finding 1 above.

That graph is the transitions. The picture at the top of this page is the trajectories: runs merged by their common start, each block as wide as the share of the bill that went down that branch. It is a flame graph with the stack replaced by the run, and it is there because a list of paths stops working on long runs — past step 16 in that log, most runs are already on a path no other run takes. Prefixes still agree long after whole paths have stopped.

Does it read my code?

A fair question: you are pointing a tool at your entire working history.

Nothing leaves your machine. The command above makes no network calls at all. There is no telemetry, no config in your home directory, no account.

What the event log holds: activity names (tool:Bash, chat), timestamps, token counters, cost, opaque IDs, and the basename of the project directory. No message text, no tool arguments, no file paths, no commands. That is enforced in the adapter rather than in the report — because reports get shared — and it is tested: test_no_message_content_leaks_into_spans, test_project_name_is_basename_only.

One command can talk to a cloud, and only if you ask it to. traceroutine abstract --backend anthropic sends the list of distinct activity names — a few dozen short strings — to group them semantically. Nothing else: no events, no counters, no content. The default path above never runs it. To see that list before trusting anyone with it, look at the mapping: keys in activity_map.yaml; they are exactly what would be sent. --backend ollama keeps the step on your own machine.

Install

uvx traceroutine                 # no install
pip install traceroutine         # or into your environment

When there is more to ask

The one-shot is ingest → abstract → report with sensible defaults. Each is also a command, for when the defaults are not what you want:

ingest <src> traces → a canonical event log (parquet)
abstract <log> raw span labels → activity_map.yaml, a semantic vocabulary
report <log> findings + process graph: -f html or -f md
check <log> conformance against a declared process.yaml; exit codes for CI
diff <a> <b> compare two logs: a prompt release, a model swap, two cohorts
  • The guide — sources, the case notion that decides everything, the abstraction layer, what gets computed, architecture.
  • Conformance — declaring how the agent is supposed to work, and failing CI when it stops doing that. This is the part no dashboard does.

Reading a log other than Claude Code's: traceroutine --from <file-or-directory>. OpenTelemetry JSON and OpenAI-style chat transcripts are detected automatically.

When this will not help you

Stated up front, because a tool that always returns five findings eventually returns five invented ones.

Variant analysis has a measured limit. Path uniqueness climbs from 17% at 1–3 steps to 100% at 26+. Above roughly 13 steps trajectories stop repeating, and "rare paths eat the budget" becomes the tautology "expensive runs are expensive". So the variant lens fits short structured agents — RAG, support, routing — and not long ones. When repeated paths drop below 50%, traceroutine says so and suppresses those findings instead of dressing up a tautology.

What still works on long runs: context inflation, cohort diff, and conformance — all three get stronger with trace length rather than degenerating.

Status

Alpha, and honest about it: it runs end to end on three sources, its cost accounting agrees with an independently written tool to within 0.1%, and it has 153 tests. The interactive graph renderer is not built yet.

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

traceroutine-0.4.0.tar.gz (297.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

traceroutine-0.4.0-py3-none-any.whl (93.9 kB view details)

Uploaded Python 3

File details

Details for the file traceroutine-0.4.0.tar.gz.

File metadata

  • Download URL: traceroutine-0.4.0.tar.gz
  • Upload date:
  • Size: 297.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for traceroutine-0.4.0.tar.gz
Algorithm Hash digest
SHA256 abddeb8c9e5053082cbef47dd2528fc46df6ecd3e378051fef17e00a97be90c0
MD5 a7289b30a7bee75c25ce2db67013515b
BLAKE2b-256 c65af72e6ef07b69ab8d577880c30ce4ea999a2788ee61dbbac1270f5862c30c

See more details on using hashes here.

File details

Details for the file traceroutine-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: traceroutine-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 93.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.7 {"installer":{"name":"uv","version":"0.10.7","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}

File hashes

Hashes for traceroutine-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 907d1c3ecac6ce1baac3e9deb5fccde2a713bb5516bd2fd29ed49e54dce641f9
MD5 8e473990b6e583551591055f22db9e65
BLAKE2b-256 bab2e7c02259952fcb550f13ac1a4e5eeac3d2aeead92b4a558c051c9c735139

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 files

0.3.0

2 files

0.2.1

2 files

0.2.0

2 files

0.1.2

2 files

0.1.1

2 files

0.1.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page