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 chat session exposes a single read-only chat.usage property. It returns an AggregatedUsage view derived from the centralized usage registry on each access, scoped to this chat’s chat_usage_id. The session’s own agent calls, sub-agents, memory summarization, reliability passes, culture, and policy checks all inherit the chat scope and roll into chat.usage automatically. For wall-clock session length, use chat.duration (or chat.end_time - chat.start_time for an explicit window).

Accessing Chat Metrics

Read chat.usage on any Chat instance. It always returns an AggregatedUsage — zero-valued before the first message, populated thereafter.

Token Metrics

PropertyTypeDescription
input_tokensintPrompt tokens across all model calls in the session
output_tokensintCompletion tokens across all model calls
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
requestsintNumber of LLM API requests across the session
tool_callsintNumber of tool calls across the session

Timing Metrics

PropertyTypeDescription
durationfloatSum of per-call durations recorded on 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)

Session Wall-Clock & Messages

PropertyTypeDescription
chat.durationfloatWall-clock session length in seconds
chat.start_timefloatUnix timestamp when the session opened
chat.end_timefloat | NoneUnix timestamp when the session closed (None if active)
len(chat.all_messages)intTotal messages in the session

Example

import asyncio
from upsonic import Agent, Chat


async def main():
    agent = Agent("anthropic/claude-sonnet-4-5")
    chat = Chat(session_id="session1", user_id="user1", agent=agent)

    await chat.invoke("Hello")
    await chat.invoke("How are you?")

    u = chat.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}")

    # Wall-clock session length
    print(f"Wall-clock:      {chat.duration:.1f}s")
    print(f"Messages:        {len(chat.all_messages)}")


if __name__ == "__main__":
    asyncio.run(main())

JSON-Friendly Output

import json

snapshot = {
    **chat.usage.to_dict(),
    "duration_wallclock": chat.duration,
    "messages": len(chat.all_messages),
}
print(json.dumps(snapshot, indent=2))

Scope & Propagation

  • Across invocations — Every chat.invoke / chat.stream adds entries under the chat’s scope. Reading chat.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 chat scope via context variables and roll into chat.usage automatically.
  • Retry idempotency — The registry is keyed by entry_id. Retried requests replace their prior entry instead of double-counting.
  • Persistence — When you configure storage on Chat, recorded entries persist alongside the conversation. Re-opening the same session_id re-hydrates the registry, so chat.usage continues from where it left off across processes and restarts.

Legacy Migration

Legacy chat-level properties and helpers have been removed in favour of chat.usage:
LegacyReplacement
chat.input_tokenschat.usage.input_tokens
chat.output_tokenschat.usage.output_tokens
chat.total_tokenschat.usage.total_tokens
chat.total_costchat.usage.cost
chat.total_requestschat.usage.requests
chat.total_tool_callschat.usage.tool_calls
chat.run_duration, chat.time_to_first_tokenchat.usage.duration, chat.usage.time_to_first_token
chat.get_usage()chat.usage
chat.get_session_metrics(), chat.get_session_summary(), SessionMetricschat.usage + chat.duration + len(chat.all_messages)
chat.get_cost_history()(registry query — filter UsageEntry rows by chat_usage_id)