agentsec · Tools · runledger

Offline · stdlib-only · MIT

runledger: detect token and cost overruns in agent runs in AI agents


Offline, stdlib-only Python CLI for token and cost accounting of AI agent runs, computed from transcripts and usage logs you already have.

What it detects

Offline, stdlib-only Python CLI for token and cost accounting of AI agent runs, computed from transcripts and usage logs you already have.

Honesty note. runledger counts what your logs report. It cannot see your provider's bill, cannot verify billing, and does not know about discounts, batch pricing, tiers, minimums, taxes, or price changes. Every dollar figure is an estimate from a price table *you* control. The shipped prices.json is an EXAMPLE only - prices change and those numbers are not authoritative. Models missing from the table are reported as unpriced, never guessed.

Rules

This tool does not publish a numbered rules table; see the README for what it flags.

Usage

python3 runledger.py examples/                          # table report for a directory
python3 runledger.py run.jsonl --json > report.json     # machine-readable
python3 runledger.py logs/ --csv > turns.csv            # one row per turn
python3 runledger.py logs/ --csv --csv-group tool       # one row per tool
cat run.jsonl | python3 runledger.py - --top 10         # stdin
python3 runledger.py logs/ --budget 5.00                # exit 1 if estimate > $5
python3 runledger.py logs/ --prices my_prices.json      # your own price table
python3 runledger.py logs/ --no-prices                  # tokens only

After pip install of the kit, the same options work as agentsec runledger …. Every tool also accepts --help and almost every tool accepts --json.

Example output

Real run on the bundled fake logs (python3 runledger.py examples):

* marks totals that exclude unpriced turns. With --budget 0.05 --top 3 the exit code is 1 and stderr says:

--csv --csv-group model:

runledger 0.1.0 - token & cost ESTIMATES from logs (not a bill)

Turns: 11   Input: 18,812   Cache read: 23,528   Cache write: 8,000   Output: 3,795 (reasoning 896)
Total tokens: 54,135   Cache hit ratio: 46.7%   Estimated cost: $0.0758*
* 1 turn(s) unpriced (models not in price table: mystery-model-x) - excluded from cost

By run:
run                  turns  input  cache_rd  cache_wr  output   total  cache%      cost
-------------------  -----  -----  --------  --------  ------  ------  ------  --------
anthropic_run.jsonl      4  9,150    16,000     8,000     770  33,920    48.3   $0.0590
run-oa-2                 2  1,924     5,376         0   1,300   8,600    73.6   $0.0108
run-oa-1                 2  1,338     1,152         0      75   2,565    46.3   $0.0055
tr-local-1               3  6,400     1,000         0   1,650   9,050    13.5  $0.0005*

By model:
model                      turns  input  cache_rd  cache_wr  output   total  cache%      cost
-------------------------  -----  -----  --------  --------  ------  ------  ------  --------
claude-sonnet-4-20250514       3  3,950    16,000     8,000     460  28,410    57.2   $0.0536
o3-mini                        2  1,924     5,376         0   1,300   8,600    73.6   $0.0108
gpt-4o                         2  1,338     1,152         0      75   2,565    46.3   $0.0055
claude-3-5-haiku-20241022      1  5,200         0         0     310   5,510     0.0   $0.0054
gpt-4o-mini                    1  1,500     1,000         0     300   2,800    40.0   $0.0005
mystery-model-x                1  4,000         0         0   1,200   5,200     0.0  unpriced
example-local-7b               1    900         0         0     150   1,050     0.0   $0.0000

By tool:
tool         turns  input  cache_rd  cache_wr  output   total  cache%      cost
-----------  -----  -----  --------  --------  ------  ------  ------  --------
bash             1  2,100         0     8,000     120  10,220     0.0   $0.0381
read_file        2  1,850    16,000         0     340  18,190    89.6   $0.0155
search_docs      2  1,924     5,376         0   1,300   8,600    73.6   $0.0108
get_weather      2  1,338     1,152         0      75   2,565    46.3   $0.0055
fetch_url        1  5,200         0         0     310   5,510     0.0   $0.0054
(none)           1  1,500     1,000         0     300   2,800    40.0   $0.0005
coder            1  4,000         0         0   1,200   5,200     0.0  unpriced
planner          1    900         0         0     150   1,050     0.0   $0.0000

By session:
session     turns  input  cache_rd  cache_wr  output   total  cache%      cost
----------  -----  -----  --------  --------  ------  ------  ------  --------
sess-gamma      3  3,950    16,000     8,000     460  28,410    57.2   $0.0536
sess-beta       2  1,924     5,376         0   1,300   8,600    73.6   $0.0108
sess-alpha      2  1,338     1,152         0      75   2,565    46.3   $0.0055
sess-delta      1  5,200         0         0     310   5,510     0.0   $0.0054
tr-local-1      3  6,400     1,000         0   1,650   9,050    13.5  $0.0005*

Top 5 most expensive turns:
turn                                       model         tool  tokens     cost
---------------------  -------------------------  -----------  ------  -------
anthropic_run.jsonl:1   claude-sonnet-4-20250514         bash  10,220  $0.0381
anthropic_run.jsonl:3   claude-sonnet-4-20250514    read_file   9,760  $0.0108
openai_run.jsonl:3                       o3-mini  search_docs   4,300  $0.0066
anthropic_run.jsonl:4  claude-3-5-haiku-20241022    fetch_url   5,510  $0.0054
anthropic_run.jsonl:2   claude-sonnet-4-20250514    read_file   8,430  $0.0046

SARIF and CI

agentsec runledger path/to/input --json > runledger.json
# runledger does not yet emit SARIF; use --json and keep --fail-on for CI.

# GitHub Actions (composite action ships with the repo)
- uses: dunkleschitz/agentsec@v0
  with:
    tools: runledger
    paths: path/to/input
    fail-on: high

--sarif is not available on this tool yet (resultguard and toolpoison are reserved as good first issues). Use --json and a --fail-on exit gate instead.

OWASP mapping

Heuristic mapping of what this tool helps a reviewer look for. Not an official OWASP endorsement, and not complete coverage of any item. Sources: OWASP Top 10 for LLM Applications 2025 and OWASP Top 10 for Agentic Applications 2026.

Known limits

Heuristic scanner, not a security boundary. A clean result does not mean something is safe. All example secrets in this repository are fake.

Full source, tests, and fixtures: tools/runledger/ in the repository. Install the kit with pip install git+https://github.com/dunkleschitz/agentsec.git.