SDK Documentation

Complete guide to integrating AgentCost into your OpenAI, Anthropic, Gemini, and LangChain applications

Installation

Install the AgentCost SDK using pip:

bash
pip install agentcost

Or install from source:

bash
cd agentcost-sdk
pip install -e .

Quick Start

Add just two lines of code to start tracking LLM costs:

python
from agentcost import track_costs

# Initialize tracking
track_costs.init(
    api_key="sk_...",  # Settings → your project → API Key
    project_id="123e4567-e89b-42d3-a456-426614174000"  # Settings → your project → UUID
)

# OpenAI — automatically tracked
from openai import OpenAI
client = OpenAI()
response = client.chat.completions.create(model="gpt-4o", messages=[{"role": "user", "content": "Hello!"}])

# Anthropic — automatically tracked
from anthropic import Anthropic
client = Anthropic()
message = client.messages.create(model="claude-3-5-sonnet-20241022", max_tokens=100, messages=[{"role": "user", "content": "Hello!"}])

# Gemini — automatically tracked (Google Gen AI SDK)
from google import genai
client = genai.Client()
response = client.models.generate_content(model="gemini-2.5-flash", contents="Hello!")

# LangChain — automatically tracked
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4")
response = llm.invoke("Hello, world!")  # Automatically tracked

Note: The SDK uses monkey patching to intercept OpenAI, Anthropic, Gemini, and LangChain calls. Your existing code requires no modifications.

Security: API keys are shown once on creation. Store them securely and rotate keys from the dashboard if needed.

Verify it worked

Force-send any pending events, then check your dashboard — your first calls should appear within seconds:

python
# Push any batched events to the backend immediately
track_costs.flush()

# Now open your dashboard — the calls above should be there.

Nothing showing up? If your api_key and project_id don't match (e.g. the project name was used instead of its UUID), the backend returns 403 and the SDK emits a RuntimeWarning plus an error on the agentcost logger. Check your console output.

Configuration

The SDK supports extensive configuration options:

python
track_costs.init(
    # Required for cloud mode
    api_key="sk_...",
    project_id="123e4567-e89b-42d3-a456-426614174000",  # project UUID, not its name

    # Optional settings
    base_url="https://api.agentcost.tech",  # Your backend URL
    batch_size=10,                          # Events before auto-flush
    flush_interval=5.0,                     # Seconds between flushes
    debug=True,                             # Enable debug logging
    default_agent_name="my-agent",          # Default agent tag
    local_mode=False,                       # Store locally (no backend)
    enabled=True,                           # Enable/disable tracking

    # Custom pricing (overrides defaults)
    custom_pricing={
        "my-custom-model": {"input": 0.001, "output": 0.002}
    },

    # Global metadata (attached to all events)
    global_metadata={
        "environment": "production",
        "version": "1.0.0"
    }
)

Configuration Options

ParameterTypeDefaultDescription
api_keystrNoneYour project API key
project_idstrNoneYour project's UUID (Settings → your project), not its name
batch_sizeint10Events before auto-flush
flush_intervalfloat5.0Seconds between flushes
local_modeboolFalseStore events locally only
debugboolFalseEnable debug logging

Agent Tagging

Tag LLM calls by agent for granular analytics:

python
# Option 1: Set default agent
track_costs.set_agent_name("router-agent")

# Option 2: Context manager (recommended)
with track_costs.agent("technical-agent"):
    llm.invoke("How do I fix this bug?")  # Tagged as "technical-agent"

with track_costs.agent("billing-agent"):
    llm.invoke("What's my balance?")  # Tagged as "billing-agent"

Agent names appear in your dashboard, allowing you to track costs per agent and identify which parts of your system are most expensive.

Workflows & Steps

Agent tagging answers which agent spent the money. Wrapping a multi-step run answers what one run costs, which step inside it is expensive, and whether the agent is looping:

python
with track_costs.workflow("support-triage"):

    with track_costs.step("classify"):
        llm.invoke("Which queue does this belong in?")

    with track_costs.tool("search_docs"):
        llm.invoke("Summarise these results")

    with track_costs.step("draft_reply"):
        llm.invoke("Write the response")

Every call inside shares one trace id and records the step it belongs to, its parent, and how deeply it was nested. Steps nest freely, and a sub-agent that opens its own workflow() stays part of the caller's run rather than starting a second one.

This unlocks the Workflows page in your dashboard: cost per run rather than per call, cost per step and per tool, and detection of the same call being made twice inside a single run — which is usually a loop rather than something a cache would fix.

Mark how a run ended and you also get cost per completed outcome, which charges failed runs to the successes they were paid for:

python
with track_costs.workflow("support-triage"):
    ticket = handle(request)
    track_costs.outcome(ticket.resolved, label=ticket.status)

Entirely optional and entirely additive. Without a workflow() your events are exactly what they were before, and step() outside a workflow is a no-op — so instrumenting a shared helper never depends on how it gets called. Workflow, step and tool names are strings you write and they are transmitted as written; see the privacy architecture page.

Pre-deployment Analysis

Estimate what an agent will cost, and find its loops, before it has spent anything. The analyser runs entirely on your machine:

bash
# What do the prompt and skill files cost on every call?
agentcost analyze ./agent --model gpt-4o

# Record a test run with local mode, then project it to production
agentcost analyze ./agent --events run.json --runs-per-day 2000

Save a test run with local mode, where nothing leaves the process at all:

python
import json
from agentcost import track_costs

track_costs.init(local_mode=True)

with track_costs.workflow("support-triage"):
    ...   # run your agent once

track_costs.flush()
json.dump(track_costs.get_local_events(), open("run.json", "w"))

The report gives cost per run, the share each step contributes, a projected monthly bill at your expected volume, and findings: steps that loop, identical calls repeated inside one run, prompt files eating the context window, and duplicated content across files.

Every flag, every finding it can raise, and the CI exit codes are in the CLI reference.

This command reads your prompts and skill files, and it never transmits them. No network call is made, and no file content outlives the token count taken from it — see the privacy architecture page.

Metadata

Attach custom metadata for filtering and grouping:

python
# Persistent metadata (attached to all subsequent events)
track_costs.add_metadata("user_id", "user_123")
track_costs.add_metadata("tenant_id", "acme_corp")

# Temporary metadata (context manager)
with track_costs.metadata(conversation_id="conv_456", step="routing"):
    llm.invoke("Route this query")

Local Mode

Test without running a backend:

python
track_costs.init(local_mode=True, debug=True)

# Make LLM calls
llm.invoke("Hello!")
llm.invoke("World!")

# Retrieve captured events
events = track_costs.get_local_events()
for event in events:
    print(f"Model: {event['model']}")
    print(f"Tokens: {event['total_tokens']}")
    print(f"Cost: ${event['cost']:.6f}")

Streaming Support

Streaming calls are automatically tracked:

python
# Sync streaming
for chunk in llm.stream("Tell me a story"):
    print(chunk.content, end="")
# Event recorded after stream completes

# Async streaming
async for chunk in llm.astream("Tell me a story"):
    print(chunk.content, end="")
# Event recorded after stream completes

Supported Models

AgentCost supports over 3,500+ models from all major providers. Pricing is automatically synced from LiteLLM's comprehensive pricing database, ensuring you always have accurate, up-to-date cost information.

View all models: Browse the complete model catalog with search, filtering, and live pricing.

ProviderExamples
OpenAIgpt-4, gpt-4-turbo, gpt-4o, gpt-4o-mini, gpt-3.5-turbo, o1, o1-mini, o1-preview
Anthropicclaude-3-opus, claude-3-sonnet, claude-3-haiku, claude-3.5-sonnet, claude-3.5-haiku, claude-4-opus
Googlegemini-pro, gemini-1.5-pro, gemini-1.5-flash, gemini-2.0-flash
Groqllama-3.1-8b, llama-3.1-70b, llama-3.3-70b, mixtral-8x7b
DeepSeekdeepseek-chat, deepseek-coder, deepseek-reasoner
Coherecommand, command-r, command-r-plus
Mistralmistral-small, mistral-medium, mistral-large
Together AImeta-llama/Llama-3-70b, Qwen models, Phi models
AWS BedrockAll Bedrock-hosted models (Claude, Titan, Llama)
Azure OpenAIAll Azure-hosted OpenAI models
50+ MoreReplicate, Fireworks, Anyscale, Perplexity, etc.

For custom or private models, you can provide custom pricing via the custom_pricing parameter. The SDK also fetches the latest pricing from the backend automatically.

Event Structure

Each tracked event contains:

json
{
  "agent_name": "my-agent",
  "model": "gpt-4",
  "input_tokens": 150,
  "output_tokens": 80,
  "total_tokens": 230,
  "cost": 0.0093,
  "latency_ms": 1234,
  "timestamp": "2024-01-23T10:30:45.123Z",
  "success": true,
  "error": null,
  "streaming": false,
  "metadata": {"conversation_id": "conv_456"}
}

Graceful Shutdown

Ensure all events are sent before your application exits:

python
# Send pending events
track_costs.flush()

# Full shutdown
track_costs.shutdown()

Tip: Use Python's atexit module to automatically call shutdown() when your application exits.

Error Handling

The SDK is designed to never interfere with your application. All tracking operations are:

  • Non-blocking: Events are batched and sent asynchronously
  • Fault-tolerant: Network failures are silently handled
  • Retry-enabled: Failed batches are retried with exponential backoff
python
# The SDK never throws exceptions to your code
try:
    response = llm.invoke("Hello!")  # This works even if tracking fails
except Exception as e:
    # This will only catch LLM errors, not tracking errors
    print(f"LLM error: {e}")

# To see tracking errors, enable debug mode
track_costs.init(
    api_key="sk_...",
    project_id="123e4567-e89b-42d3-a456-426614174000",
    debug=True,  # Logs errors to console
)

Best Practices

1. Initialize Early

Call track_costs.init() before creating any LLM instances:

python
# Correct: Initialize before importing LLM
from agentcost import track_costs
track_costs.init(
    api_key="sk_...",
    project_id="123e4567-e89b-42d3-a456-426614174000",
)

from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4")

# Wrong: LLM created before initialization
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4")

from agentcost import track_costs
track_costs.init(
    api_key="sk_...",
    project_id="123e4567-e89b-42d3-a456-426614174000",
)  # Too late!

2. Use Agent Context Managers

Context managers ensure proper agent tagging even if exceptions occur:

python
# Recommended: Context manager
with track_costs.agent("router"):
    response = llm.invoke(query)

# Less safe: Manual setting
track_costs.set_agent_name("router")
response = llm.invoke(query)  # What if this throws?
track_costs.set_agent_name("default")  # Might not run

3. Environment Variables

Store sensitive configuration in environment variables:

python
import os
from agentcost import track_costs

track_costs.init(
    api_key=os.environ["AGENTCOST_API_KEY"],       # sk_...
    project_id=os.environ["AGENTCOST_PROJECT_ID"], # project UUID
    base_url=os.environ.get("AGENTCOST_URL", "https://api.agentcost.tech"),
    debug=os.environ.get("DEBUG", "false").lower() == "true"
)

4. Graceful Shutdown

Always flush events before your application exits:

python
import atexit
from agentcost import track_costs

track_costs.init(
    api_key="sk_...",
    project_id="123e4567-e89b-42d3-a456-426614174000",
)

# Register shutdown handler
atexit.register(track_costs.shutdown)

# Or in FastAPI/Flask
@app.on_event("shutdown")
async def shutdown_event():
    track_costs.shutdown()

Troubleshooting

Events not appearing in dashboard

  • #1 cause: project_id must be the project UUID from Settings, not its name — a mismatch returns 403 and the SDK logs an agentcost error
  • Ensure track_costs.init() is called before LLM usage
  • Check your API key is correct
  • Enable debug=True to see error messages
  • Call track_costs.flush() to force send events

Token counts seem wrong

  • The SDK uses tiktoken for accurate counting
  • Make sure tiktoken is installed: pip install tiktoken
  • Some models may use different tokenizers

Connection errors

  • Verify your base_url is correct
  • Check that the backend is running and accessible
  • Look for firewall or proxy issues

Getting support

If you're still having issues, check our GitHub Issues or start a discussion.