Install
openclaw skills install @panthrocorp/panthrocorp-token-usageMulti-agent token burn analysis across all registered OpenClaw agents
openclaw skills install @panthrocorp/panthrocorp-token-usageAnalyse token usage and estimated costs across all registered OpenClaw agents. Dynamically discovers agents, groups sessions by channel category, flags anomalies, and presents a per-agent breakdown with combined totals.
List the contents of ~/.openclaw/agents/. Each subdirectory is an agent.
For each agent directory, attempt to read sessions/sessions.json. If the file does not exist, is empty, or is not valid JSON, skip that agent and note it as "(no session data)" in the output.
Each sessions.json is a JSON object. The keys are session key strings with the format:
agent:<agentId>:<channel>:<subtype>[:<identifier>]
For each session entry, extract these fields (all may be absent):
| Field | Type | Description |
|---|---|---|
totalTokens | integer | Total tokens consumed in this session |
inputTokens | integer | Input/prompt tokens |
outputTokens | integer | Output/completion tokens |
estimatedCostUsd | float | Estimated cost in USD |
model | string | Model identifier (e.g. provider/model-name) |
updatedAt | integer | Last update timestamp in epoch milliseconds |
The category is the third segment of the session key (index 2 when splitting on :).
Examples:
agent:alice:discord:channel:123456789 -> category = discordagent:alice:telegram:direct:987654321 -> category = telegramagent:bob:cron:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx -> category = cronagent:alice:main -> category = mainThe user specifies a time window. If not specified, default to "this week".
| Window | Behaviour |
|---|---|
| "this week" | Include sessions where updatedAt is within the last 7 days |
| "all time" | No filter; include all sessions |
| "last N days" | Include sessions where updatedAt is within the last N days |
If updatedAt is absent or 0, include the session only when the window is "all time". For all other windows, exclude it.
Convert updatedAt from epoch milliseconds to a date for comparison.
For each agent, group the filtered sessions by category. Within each group, compute:
totalTokens (skip entries where the field is absent)inputTokens (skip entries where the field is absent)outputTokens (skip entries where the field is absent)estimatedCostUsd (skip entries where the field is absent)model values (skip entries where the field is absent)Apply two flags to each category group:
SINKHOLE: totalTokens > 10,000 AND (estimatedCostUsd is absent across all entries in the group, or the summed cost is less than $0.01).
This indicates high token volume on free or untracked models and may signal wasted computation.
EXPENSIVE: summed estimatedCostUsd > $5.00.
This indicates a high-spend category. Review whether the spend is justified.
A single category can have both flags (high tokens on a mix of free and paid models).
For each agent that has session data, print a heading with the agent name and total session count, then a table with one row per category:
## alice (120 sessions)
| Category | Sessions | Tokens | Input | Output | Est. Cost | Models | Flags |
|----------|----------|--------|-------|--------|-----------|--------|-------|
| discord | 80 | 1.2M | 800K | 400K | $42.50 | model-a | EXPENSIVE |
| telegram | 25 | 120K | 80K | 40K | $3.20 | model-a | |
| cron | 10 | 95K | 60K | 35K | $0.00 | model-b | SINKHOLE |
| main | 5 | 20K | 15K | 5K | $0.32 | model-a | |
Sort rows by estimated cost descending within each agent.
For agents skipped in Step 1, print: ## <agent> (no session data)
After all agent sections, print:
## Combined Totals
- **Total sessions**: <count>
- **Total tokens**: <sum> (input: <sum>, output: <sum>)
- **Total estimated cost**: $<sum>
### Top 3 by cost
1. <agent>/<category>: $<cost> (<tokens> tokens)
2. ...
3. ...
### Top 3 by token volume
1. <agent>/<category>: <tokens> tokens ($<cost>)
2. ...
3. ...
1.2M, 45K, 320)$- not 0Append exactly one JSON line to:
~/.openclaw/workspace/memory/token-usage-history.ndjson
Create the file if it does not exist. Never modify existing lines.
This step always runs. It does not require explicit user request.
The line is a compact JSON object (no newlines within the record):
{"date":"YYYY-MM-DD","window":"<time window>","runAt":<epoch ms>,"agents":[...],"combined":{...}}
| Field | Type | Description |
|---|---|---|
date | string | UTC date of this run (YYYY-MM-DD) |
window | string | Time window used (e.g. "last 1 day", "this week") |
runAt | integer | Epoch milliseconds when the skill ran |
agents | array | One entry per agent that has session data |
combined | object | Aggregated totals across all agents |
Each agent entry:
{
"id": "<agentId>",
"categories": [
{
"category": "<category>",
"sessions": 80,
"totalTokens": 1200000,
"inputTokens": 800000,
"outputTokens": 400000,
"estimatedCostUsd": 42.50,
"models": ["model-a"],
"flags": ["EXPENSIVE"]
}
],
"totals": {
"sessions": 120,
"totalTokens": 1435000,
"inputTokens": 955000,
"outputTokens": 480000,
"estimatedCostUsd": 46.02
}
}
The combined object mirrors the totals shape without an id field.
Use null for any numeric field where all entries in the group had the field absent. Use [] for flags when no flags apply. Agents with no session data are omitted from the record entirely.
Only if the user explicitly requests logging, append a timestamped summary to:
~/.openclaw/workspace/memory/token-diet-log.md
Create the file if it does not exist.
Append in this format:
## YYYY-MM-DD -- Token Usage Report (window: <time window>)
- Total: <tokens> tokens, $<cost> estimated
- <agent>: <tokens> tokens, $<cost> (<flags if any>)
- ...
- Anomalies: <comma-separated list of flagged agent/category pairs with flag name>
Do not write to this file unless the user explicitly asks.
| Access | Path | Required |
|---|---|---|
| Read | ~/.openclaw/agents/*/sessions/sessions.json | Always |
| Write | ~/.openclaw/workspace/memory/token-usage-history.ndjson | Always |
| Write | ~/.openclaw/workspace/memory/token-diet-log.md | Only when user requests logging |
No environment variables. No network access. No credentials.