从轨迹日志中按OpenClaw 代理汇总每日 LLM token 使用量,展示输入、输出、缓存读取/写入、总计以及可选的可计费 token 估算
Accurately attribute LLM token consumption across all OpenClaw agents for a given day.


Ships two things in one skill:
scripts/agent_token_usage.py, always works, zero setupapply-ui.sh injects a 📊 button into Control UI's header next to Search; clicking shows today's per-agent table in a modalsessions_list returns each session's totalTokens field which is the last context window size, NOT the cumulative consumption across all LLM calls in that session. For long-running sessions, real consumption can be 100×+ larger. This skill reads the canonical session log ( <id>.jsonl, NOT <id>.trajectory.jsonl) and sums every type=="message" / role=="assistant" row's usage object — exactly one entry per real LLM API call. This matches pew / openclaw's own accounting.
bash
# default = today, UTC date (matches pew / openclaw accounting)
python ~/.openclaw/workspace/skills/agent-token-usage/scripts/agent_token_usage.py
# local-tz date instead of UTC
python …/agent_token_usage.py --tz local
# specific date
python …/agent_token_usage.py --date 2026-05-20
# equivalent billable (cacheRead × 0.1 + cacheWrite × 1.25 + input + output)
python …/agent_token_usage.py --date 2026-05-20 --billable
# JSON
python …/agent_token_usage.py --format json
bash
bash ~/.openclaw/workspace/skills/agent-token-usage/apply-ui.sh
Then refresh the Control UI tab. The button appears next to Search; clicking shows the modal.
Uninstall:
bash
bash ~/.openclaw/workspace/skills/agent-token-usage/remove-ui.sh
Per-browser toggle:
js
localStorage.setItem('milly.tokenUsageBtn', 'off')
localStorage.removeItem('milly.tokenUsageBtn')
text
launchd (5min) → refresh-data.sh → <ui>/data/agent-token-usage.json
│ same-origin fetch
▼
Control UI bundle (patched IIFE)
📊 button → modal table
CSP-friendly ( connect-src 'self') because data is served from the UI's own origin. No extra daemon, no extra port. After openclaw update overwrites dist/control-ui/*, just re-run apply-ui.sh — idempotent.
FieldMeaningBilling weightinputnew, non-cached prompt tokens1.0×outputmodel-generated tokens1.0× (typically 5× input price)cacheReadprompt tokens served from prompt cache0.1×1.25×cacheWriteprompt tokens written to cachetotalsum of all four (real LLM throughput)—~billweighted billable-equivalent tokens—
Use total to see "who's burning the most LLM compute"; use ~bill to see "who's actually most expensive". High-cacheRead agents look huge but are cheap; high-input agents look small but cost more.
~/.openclaw/agents/<agent>/sessions/*.jsonl (excluding *.trajectory.jsonl, *.deleted*, *.bak)type=="message" and message.role=="assistant"timestamp against target date in chosen timezone ( --tz utc default, --tz local available)message.usage.{input,output,cacheRead,cacheWrite} per agent; track sessions and modelsEach LLM call produces several trajectory events ( prompt.submitted, context.compiled, model.completed, trace.artifacts, …) and every one of them embeds the same usage snapshot. A DFS sum over trajectory inflates the real number by ~2.6×. The canonical <id>.jsonl has exactly one type=="message" row per call — 1:1 with the API call, no de-dup needed.
usage object) — non-LLM tool calls excluded by designmodel-usage skill for $ amounts--date matches ISO timestamps in session logs (UTC by default). Use --tz local to bucket by your local day insteadscripts/refresh-data.sh via cron/systemd timerFilePurposescripts/agent_token_usage.pyCLI aggregatorscripts/refresh-data.shWrites JSON into every patched Control UI distscripts/token-usage-button.iife.jsUI patch payload (button + modal + same-origin fetch)apply-ui.shInject IIFE, cache-bust, install launchd refresh jobremove-ui.shRestore bundle, remove launchd job, delete data dir