Documentation Index
Fetch the complete documentation index at: https://docs.upsonic.ai/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Every agent exposes a single read-only agent.usage property. It returns an AggregatedUsage view derived from the centralized usage registry on each access, scoped to this agent’s agent_usage_id.
Sub-pipeline model calls — memory summarization, reliability validator/editor, culture, policy, and sub-agents invoked as tools — automatically inherit the agent’s scope and roll into agent.usage without any manual propagation.
When printing is enabled (print_do / print_do_async), an Agent Metrics panel is displayed after each task so you can see the updated totals.
Accessing Agent Metrics
Read agent.usage on any Agent instance. It always returns an AggregatedUsage — zero-valued before the first run, populated thereafter.
Token Metrics
| Property | Type | Description |
|---|
input_tokens | int | Total prompt/input tokens across all runs |
output_tokens | int | Total completion/output tokens across all runs |
total_tokens | int | Sum of input_tokens + output_tokens |
cache_read_tokens | int | Tokens read from prompt cache |
cache_write_tokens | int | Tokens written to prompt cache |
reasoning_tokens | int | Reasoning (chain-of-thought) tokens |
| Property | Type | Description |
|---|
requests | int | Total number of LLM API requests made |
tool_calls | int | Total number of tool calls executed |
Timing Metrics
| Property | Type | Description |
|---|
duration | float | Sum of per-call durations across contributing entries (seconds) |
model_execution_time | float | Total time spent inside LLM API calls (seconds) |
tool_execution_time | float | Total time spent executing tools (seconds) |
upsonic_execution_time | float | Framework overhead = duration − model − tool (seconds) |
time_to_first_token | float | None | Earliest TTFT across contributing entries |
Cost Metrics
| Property | Type | Description |
|---|
cost | float | None | Sum of cost_usd across contributing entries. None if no entry was priced; 0.0 means priced and free. |
| Property | Type | Description |
|---|
entry_count | int | Number of underlying UsageEntry rows contributing to this view |
models | list[str] | Distinct model identifiers that contributed (first-seen order) |
Example
from upsonic import Agent, Task
agent = Agent("anthropic/claude-sonnet-4-5", print=True)
agent.print_do(Task("What is 2 + 2? Reply with one number."))
agent.print_do(Task("What is 3 + 3? Reply with one number."))
u = agent.usage
print(f"Requests: {u.requests}")
print(f"Input tokens: {u.input_tokens}")
print(f"Output tokens: {u.output_tokens}")
print(f"Tool calls: {u.tool_calls}")
if u.cost is not None:
print(f"Cost: ${u.cost:.4f}")
print(f"Model time: {u.model_execution_time:.2f}s")
print(f"Tool time: {u.tool_execution_time:.2f}s")
print(f"Framework time: {u.upsonic_execution_time:.2f}s")
print(f"Models used: {u.models}")
Printed Panel
When you use print_do or print_do_async, the Agent Metrics panel displays after each task:
╭──────────────────── Agent Metrics ────────────────────╮
│ Agent: MyAgent │
│ │
│ Total Requests: 4 │
│ Total Input Tokens: 1,552 │
│ Total Output Tokens: 915 │
│ Total Tool Calls: 2 │
│ Total Estimated Cost: $0.0008 │
│ Total Duration: 21.55 seconds │
│ Model Execution Time: 18.17 seconds │
│ Tool Execution Time: 1.00 seconds │
│ Framework Overhead: 2.38 seconds │
╰───────────────────────────────────────────────────────╯
Scope & Propagation
- Across tasks — Every call to
do / print_do / do_async / print_do_async records entries against the agent’s scope. Reading agent.usage re-aggregates them, so the figures always reflect the latest state.
- Sub-pipeline rollup — Memory summarization, reliability validator/editor, culture, policy, and sub-agent calls inherit the parent’s scope via context variables and roll into
agent.usage automatically.
- Retry idempotency — The registry is keyed by
entry_id. Retried requests replace their prior entry instead of double-counting.
- Independent agents — Each
Agent instance has its own agent_usage_id. Two different agents never share usage.
- JSON snapshot — Call
agent.usage.to_dict() for a flat dict suitable for logs and dashboards.
Legacy Migration
Legacy surfaces have been removed in favour of agent.usage:| Legacy | Replacement |
|---|
agent.cost (dict) | agent.usage.to_dict() |
AgentUsage.incr() / accumulator fields | (registry-derived; no mutation needed) |
agent._finalize_agent_usage, retry baseline machinery | (registry is idempotent) |