The CostTracker hook monitors LLM API costs in real time. It accumulates token usage per session and globally, computes costs using a configurable price table, and optionally enforces budget limits.

Quick Setup

import "github.com/spawn08/chronos/engine/hooks"

tracker := hooks.NewCostTracker(nil) // uses default price table

a, _ := agent.New("assistant", "Assistant").
    WithModel(model.NewOpenAI(key)).
    AddHook(tracker).
    Build()

resp, _ := a.Chat(ctx, "Summarize this document...")

report := tracker.GetGlobalCost()
fmt.Printf("Tokens: %d prompt + %d completion\n",
    report.PromptTokens, report.CompletionTokens)
fmt.Printf("Cost: $%.6f\n", report.TotalCost)

CostReport

type CostReport struct {
    PromptTokens     int     `json:"prompt_tokens"`
    CompletionTokens int     `json:"completion_tokens"`
    TotalTokens      int     `json:"total_tokens"`
    TotalCost        float64 `json:"total_cost"`
    Currency         string  `json:"currency"`
}

Custom Price Table

Override the default prices by passing a custom price table:

prices := map[string]hooks.ModelPrice{
    "gpt-4o": {
        PromptPricePerToken:     0.0000025,
        CompletionPricePerToken: 0.00001,
    },
    "claude-sonnet-4-6": {
        PromptPricePerToken:     0.000003,
        CompletionPricePerToken: 0.000015,
    },
}

tracker := hooks.NewCostTracker(prices)

Default Price Table

The built-in table covers these models:

Model Prompt (per token) Completion (per token)
gpt-4o $0.0000025 $0.00001
gpt-4o-mini $0.00000015 $0.0000006
gpt-4-turbo $0.00001 $0.00003
o1 $0.000015 $0.00006
o3 $0.00001 $0.00004
o3-mini $0.0000011 $0.0000044
claude-sonnet-4-6 $0.000003 $0.000015
claude-3-opus $0.000015 $0.000075
claude-3-haiku $0.00000025 $0.00000125
gemini-2.0-flash $0.00000015 $0.0000006
gemini-1.5-pro $0.00000125 $0.000005
mistral-large-latest $0.000002 $0.000006

Budget Enforcement

Set a maximum spend. When the budget is exceeded, the hook returns an error on the next model call, preventing further API charges:

tracker := hooks.NewCostTracker(nil)
tracker.Budget = 5.00 // $5.00 maximum

a, _ := agent.New("budget-agent", "Budget Agent").
    WithModel(model.NewOpenAI(key)).
    AddHook(tracker).
    Build()

// After spending $5.00, subsequent calls return:
// "cost budget exceeded: spent $5.0012 of $5.0000 budget"

Per-Session Tracking

Track costs for individual sessions:

// After running several sessions
sessionReport := tracker.GetSessionCost("sess_abc123")
globalReport := tracker.GetGlobalCost()

fmt.Printf("Session cost: $%.4f\n", sessionReport.TotalCost)
fmt.Printf("Global cost:  $%.4f\n", globalReport.TotalCost)

To associate model calls with sessions, set session_id in event metadata. The ChatWithSession method does this automatically.

Combining with Other Hooks

Cost tracking works alongside other middleware. Order matters – place the cost tracker after retry hooks so retried calls are counted:

a, _ := agent.New("production", "Production Agent").
    WithModel(model.NewOpenAI(key)).
    AddHook(hooks.NewRetryHook(3)).       // retries first
    AddHook(hooks.NewRateLimitHook(60, 0)). // then rate limit
    AddHook(tracker).                      // then track costs
    AddHook(hooks.NewMetricsHook()).       // then record metrics
    Build()