Skip to main content

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

PropertyTypeDescription
input_tokensintTotal prompt/input tokens across all runs
output_tokensintTotal completion/output tokens across all runs
total_tokensintSum of input_tokens + output_tokens
cache_read_tokensintTokens read from prompt cache
cache_write_tokensintTokens written to prompt cache
reasoning_tokensintReasoning (chain-of-thought) tokens

Request & Tool Metrics

PropertyTypeDescription
requestsintTotal number of LLM API requests made
tool_callsintTotal number of tool calls executed

Timing Metrics

PropertyTypeDescription
durationfloatSum of per-call durations across contributing entries (seconds)
model_execution_timefloatTotal time spent inside LLM API calls (seconds)
tool_execution_timefloatTotal time spent executing tools (seconds)
upsonic_execution_timefloatFramework overhead = duration − model − tool (seconds)
time_to_first_tokenfloat | NoneEarliest TTFT across contributing entries

Cost Metrics

PropertyTypeDescription
costfloat | NoneSum of cost_usd across contributing entries. None if no entry was priced; 0.0 means priced and free.

Aggregation Metadata

PropertyTypeDescription
entry_countintNumber of underlying UsageEntry rows contributing to this view
modelslist[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:
LegacyReplacement
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)