Skip to main content

Overview

Every task execution tracks detailed metrics including token counts, timing breakdowns, estimated cost, and tool calls. All timing and token data lives in task.usage (TaskUsage) — the single source of truth for task-level metrics. When printing is enabled (print_do / print_do_async), a Task Metrics panel is displayed after each task execution.

Accessing Task Metrics

After executing a task, metrics are available directly on the Task instance.

Token & Cost Properties

PropertyTypeDescription
total_input_tokenint | NoneNumber of input/prompt tokens used
total_output_tokenint | NoneNumber of output/completion tokens generated
total_costfloat | NoneEstimated cost in USD
price_idstrUnique identifier for tracking this task’s pricing

Timing Properties

PropertyTypeDescription
durationfloat | NoneTotal wall-clock execution time (seconds)
model_execution_timefloat | NoneTime spent inside LLM API calls (seconds)
tool_execution_timefloat | NoneTime spent executing tools (seconds)
upsonic_execution_timefloat | NoneFramework overhead = duration - model_execution_time - tool_execution_time (seconds)
start_timefloat | NoneUnix timestamp when the task started
end_timefloat | NoneUnix timestamp when the task finished

Response & Tool Properties

PropertyTypeDescription
responsestr | BaseModel | NoneThe task’s output after execution
tool_callslist[dict]List of tool calls made during execution

The usage Property (TaskUsage)

task.usage returns the underlying TaskUsage object — the single source of truth for all task-level metrics. The timing properties above (duration, model_execution_time, upsonic_execution_time) delegate directly to this object.
PropertyTypeDescription
requestsintNumber of LLM API requests made for this task
tool_callsintNumber of tool calls executed during this task
input_tokensintInput tokens (accumulated from model responses)
output_tokensintOutput tokens (accumulated from model responses)
total_tokensintSum of input_tokens + output_tokens
cache_write_tokensintTokens written to cache
cache_read_tokensintTokens read from cache
reasoning_tokensintTokens used for reasoning
durationfloat | NoneTotal task execution time (seconds)
model_execution_timefloat | NoneTime in LLM API calls (seconds)
tool_execution_timefloat | NoneTime spent executing tools (seconds)
upsonic_execution_timefloat | NoneFramework overhead time (seconds)
costfloat | NoneEstimated cost of this task

Basic Usage

from upsonic import Agent, Task

agent = Agent("anthropic/claude-sonnet-4-5")
task = Task("Summarize the key benefits of AI agents in production systems")

agent.print_do(task)

print(f"Cost:             ${task.total_cost:.6f}")
print(f"Input tokens:     {task.total_input_token}")
print(f"Output tokens:    {task.total_output_token}")
print(f"Duration:         {task.duration:.2f}s")
print(f"Model time:       {task.model_execution_time:.2f}s")
print(f"Tool time:        {(task.tool_execution_time or 0):.2f}s")
print(f"Framework time:   {task.upsonic_execution_time:.2f}s")

Printed Panel

When you use print_do or print_do_async, the Task Metrics panel is displayed:
╭──────────────────── Task Metrics ─────────────────────╮
│  Price ID:              a1b2c3d4-e5f6-...             │
│                                                       │
│  Input Tokens:          762                           │
│  Output Tokens:         408                           │
│  Total Estimated Cost:  $0.0004                       │
│  Time Taken:            10.55 seconds                 │
│  Model Execution Time:  7.99 seconds                  │
│  Tool Execution Time:   1.00 seconds                  │
│  Framework Overhead:    1.56 seconds                  │
╰───────────────────────────────────────────────────────╯

Accessing Usage Directly

For programmatic access to the full usage data, use task.usage:
from upsonic import Agent, Task

agent = Agent("anthropic/claude-sonnet-4-5")
task = Task("What is 2 + 2?")
agent.do(task)

u = task.usage
print(f"Input tokens:     {u.input_tokens}")
print(f"Output tokens:    {u.output_tokens}")
print(f"Duration:         {u.duration:.2f}s")
print(f"Model time:       {u.model_execution_time:.2f}s")
print(f"Tool time:        {u.tool_execution_time or 0:.2f}s")
print(f"Framework time:   {u.upsonic_execution_time:.2f}s")

Monitoring Multiple Tasks

from upsonic import Agent, Task

agent = Agent("anthropic/claude-sonnet-4-5")

tasks = [
    Task("Analyze sentiment of customer feedback"),
    Task("Extract key entities from the document"),
    Task("Generate a summary report"),
]

for task in tasks:
    agent.print_do(task)

    print(f"Task: {task.description[:40]}...")
    print(f"  Cost:      ${task.total_cost:.6f}")
    print(f"  Tokens:    {task.total_input_token + task.total_output_token}")
    print(f"  Duration:  {task.duration:.2f}s")
    print(f"  Model:     {task.model_execution_time:.2f}s")
    print(f"  Tool:      {(task.tool_execution_time or 0):.2f}s")
    print(f"  Overhead:  {task.upsonic_execution_time:.2f}s\n")

Independence Across Tasks

Each task has its own independent TaskUsage instance. Running multiple tasks on the same agent does not mix their metrics:
from upsonic import Agent, Task

agent = Agent("anthropic/claude-sonnet-4-5")

task_a = Task("Say hello.")
task_b = Task("Say goodbye.")

agent.do(task_a)
agent.do(task_b)

# Each task has its own usage
assert task_a.usage is not task_b.usage
print(f"Task A duration: {task_a.duration:.2f}s")
print(f"Task B duration: {task_b.duration:.2f}s")

Cost Optimization Tips

  1. Choose the right model — Use smaller models (gpt-4o-mini) for simple tasks
  2. Optimize prompts — Shorter, clearer prompts reduce input tokens
  3. Use caching — Enable task caching for repeated queries
  4. Monitor timing — Use model_execution_time vs upsonic_execution_time to identify bottlenecks