Usage Reporting
Zero-config local token and cost reporting for PraisonAI sessions
See how many tokens and dollars your agents have spent โ locally, with one command, no external service.
praisonai usageQuick Start
- See your spend
bash praisonai usage - Change the grouping
bash praisonai usage --by model praisonai usage --by project - Narrow the window or script it
bash praisonai usage --days 7 praisonai usage --json - See per-tool reliability
bash praisonai usage --by toolReports calls, success rate, average latency, and the last error for each tool used.
How It Works
The command reads the already-persisted total_tokens and cost fields on each session record in the local session store, filters by --days, groups by --by, and renders a table or JSON. No new data is written, no network calls, no configuration.
| Behaviour | Detail |
|---|---|
| Two stores read | Without --project, both the current-project store and the global default store are read, tagged current / global. |
| De-duplication | Sessions shared across both stores are collapsed by session_id. |
| Bounded scan | Up to 100,000 sessions per store are read. |
| Cost source | The persisted cost uses the same ModelPricing table as praisonai tracker, so numbers match. |
Choosing --by
Pick the dimension that answers your question.
day sorts chronologically; model and project sort by highest token count first. tool sorts by most-called first, so your busiest (or busiest-failing) tool rises to the top.
Options
| Option | Short | Type | Default | Values | Description | |||
|---|---|---|---|---|---|---|---|---|
--days | -d | int | 30 | any int; 0 = all | Only include sessions updated in the last N days. | |||
--by | -b | str | day | day \ | model \ | project \ | tool | Group rows by dimension. Invalid values exit 1. |
--project | -p | str | None | any project id | Restrict to a specific project’s session store. | |||
--json | โ | bool | False | flag | Emit machine-readable JSON instead of a table. |
An invalid --by value prints --by must be one of: day, model, project, tool and exits with code 1.
Per-Tool Reliability
praisonai usage --by tool reports per-tool call counts, success rate, average and last latency, and the last error โ read from the local session store, same as every other grouping.
Tool usage
โโโโโโโโโโโโโโณโโโโโโโโณโโโโโโโโโโณโโโโโโโโโณโโโโโโโโโโณโโโโโโโโโโโโโ
โ Tool โ Calls โ Success โ Avg ms โ Last ms โ Last error โ
โกโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโฉ
โ search โ 3 โ 66.7% โ 200 โ 200 โ timeout โ
โ write_file โ 1 โ 100.0% โ 5 โ 5 โ - โ
โโโโโโโโโโโโโโดโโโโโโโโดโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโดโโโโโโโโโโโโโ| Column | Meaning |
|---|---|
Tool | Tool name as the runtime saw it |
Calls | How many times the tool was invoked |
Success | Percentage of calls that returned without an error |
Avg ms | Average execution time across all calls |
Last ms | Latency of the most recent call |
Last error | Last error message (truncated to 60 chars in the table, 500 in JSON) |
Last ms and Last error are picked by when the tool itself last ran, not by when the session was last updated. If no tool calls are recorded, the command prints No tool usage recorded yet.
Python: read the same data with a hook
Prefer Python? The same per-call data is available via the AFTER_TOOL hook โ no new API is needed.
from praisonaiagents.hooks import add_hook, HookEvent
def on_tool(data):
print(data.tool_name, data.execution_time_ms, data.tool_error)
add_hook(HookEvent.AFTER_TOOL, on_tool)The CLI tally reads exactly these three fields.
Output Formats
Table
โโโโโโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโ
โ Day โ Tokens โ Cost โ
โโโโโโโโโโโโโโผโโโโโโโโโผโโโโโโโโโโค
โ 2026-07-19 โ 12,345 โ $0.1234 โ
โ Total โ 12,345 โ $0.1234 โ
โโโโโโโโโโโโโโดโโโโโโโโโดโโโโโโโโโโZero values render as -, and a final Total row sums the report.
JSON
{
"by": "day",
"days": 30,
"project": null,
"rows": [{"key": "2026-07-19", "total_tokens": 12345, "cost": 0.1234}],
"total_tokens": 12345,
"cost": 0.1234,
"errors": []
}JSON (–by tool)
{
"by": "tool",
"days": 30,
"project": null,
"rows": [
{
"tool": "search",
"calls": 3,
"successes": 2,
"errors": 1,
"success_rate": 0.6667,
"avg_ms": 200.0,
"last_ms": 200.0,
"last_error": "timeout"
}
],
"errors": []
}Tool mode omits the top-level total_tokens / cost fields โ it reports outcomes, not spend.
Empty Stores and Warnings
Empty and broken reports are always distinguishable.
- No sessions yet? The command prints
No usage recorded yetand exits0. - A damaged or unreadable store surfaces as
Usage may be incomplete: ...in table mode, or in the top-levelerrorsarray in JSON mode.
Best Practices
Alert on spend in CI
Wire praisonai usage --days 7 --json into a cron or CI job and alert if cost exceeds a threshold.
Find your most expensive model
Run praisonai usage --by model weekly to see which model your agents actually spend the most on.
Compare workspaces
Use praisonai usage --project <id> inside a workspace and praisonai usage --by project in the default shell to compare workloads.
Spot flaky or slow tools before users notice
Run praisonai usage --by tool --days 7 as part of your weekly review. Rows are sorted by call count first, so the busiest tool is on top โ and the Success column immediately shows which ones are quietly failing. Pipe --json into jq in CI to fail a build when any tool drops below your target success rate.
Script with jq
--json is stable for scripting โ pipe into jq or a small dashboard rather than parsing the table.