Automatic LLM cost tracking for OpenAI, Anthropic, and more
Project description
Tokenr Python SDK
Automatic LLM cost tracking in one line of code.
Track costs from OpenAI, Anthropic, and other LLM providers with zero code changes. Get real-time visibility into spending by agent, feature, team, or any dimension you need.
Features
- One-line setup — Add
tokenr.init()and you're done - Zero code changes — Use OpenAI/Anthropic SDK as normal
- Automatic tracking — Token counts and costs tracked automatically
- Async by default — Never slows down your app
- Multi-provider — OpenAI, Anthropic (more coming)
- Rich attribution — Track by agent, feature, team, or custom tags
- Production-ready — Handles errors gracefully, never crashes your app
Installation
pip install tokenr
Quickstart
OpenAI
import tokenr
import openai
# One line to enable tracking
tokenr.init(token="your-tokenr-token")
# Use OpenAI exactly as you normally would
response = openai.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello!"}]
)
# That's it — costs are automatically tracked to Tokenr
Anthropic
import tokenr
from anthropic import Anthropic
tokenr.init(token="your-tokenr-token")
client = Anthropic(api_key="your-anthropic-key")
response = client.messages.create(
model="claude-opus-4-5",
messages=[{"role": "user", "content": "Hello!"}]
)
# Automatically tracked!
Configuration
Environment Variables
export TOKENR_TOKEN="your-token"
import tokenr
tokenr.init() # Reads from TOKENR_TOKEN
All Options
tokenr.init(
token="your-token", # API token (or TOKENR_TOKEN env var)
url="https://tokenr.co/...", # Override API URL (optional)
agent_id="my-app", # Default agent ID for all requests
tags={"environment": "prod"}, # Default tags applied to every request
enabled=True, # Set False to disable tracking entirely
debug=False, # Print tracking info to console
)
Disable in Development
import os
tokenr.init(
token=os.getenv("TOKENR_TOKEN"),
enabled=os.getenv("ENV") == "production"
)
Advanced Usage
Track by Agent
# Option 1: Set a default agent ID at init
tokenr.init(token="...", agent_id="customer-support-bot")
# Option 2: Override per request
response = openai.chat.completions.create(
model="gpt-4",
messages=[...],
tokenr_agent_id="sales-assistant"
)
Track by Feature
response = openai.chat.completions.create(
model="gpt-4",
messages=[...],
tokenr_feature="chat",
tokenr_agent_id="support-bot"
)
Multi-Tenant Tracking
response = openai.chat.completions.create(
model="gpt-4",
messages=[...],
tokenr_team_id="team-123",
tokenr_agent_id="shared-bot"
)
Custom Tags
response = openai.chat.completions.create(
model="gpt-4",
messages=[...],
tokenr_tags={
"customer_id": "cust_123",
"conversation_id": "conv_456",
"language": "en",
"priority": "high"
}
)
Manual Tracking
For providers not yet auto-patched, or when you need full control:
import tokenr
tokenr.track(
provider="custom-provider",
model="custom-model-v1",
input_tokens=1000,
output_tokens=500,
agent_id="my-agent",
feature_name="translation",
tags={"language": "es"}
)
Per-Request Parameters
Add any of these to OpenAI or Anthropic calls:
| Parameter | Type | Description |
|---|---|---|
tokenr_agent_id |
str |
Agent identifier |
tokenr_feature |
str |
Feature name |
tokenr_team_id |
str |
Team or customer ID |
tokenr_tags |
dict |
Arbitrary metadata |
tokenr.track() Reference
tokenr.track(
provider="openai", # required
model="gpt-4", # required
input_tokens=100, # required
output_tokens=50, # required
cache_read_tokens=0, # tokens served from prompt cache
cache_write_tokens=0, # tokens written to prompt cache
agent_id=None,
feature_name=None,
team_id=None,
status="success", # "success" or "error"
latency_ms=None,
tags=None,
requested_at=None, # ISO 8601 timestamp; defaults to now
)
Supported Providers
| Provider | Auto-Tracking | Manual Tracking |
|---|---|---|
| OpenAI | Yes | Yes |
| Anthropic | Yes | Yes |
| Google AI | Coming soon | Yes |
| Cohere | Coming soon | Yes |
| Custom | — | Yes |
Prompt Caching
Both OpenAI and Anthropic support prompt caching, and the SDK handles it automatically. You don't need to do anything special.
OpenAI includes cached tokens inside prompt_tokens. The SDK reads prompt_tokens_details.cached_tokens and separates them so Tokenr can price each category at the correct rate.
Anthropic reports cache tokens as separate fields (cache_creation_input_tokens and cache_read_input_tokens). The SDK passes these through directly.
In both cases, the Tokenr server applies the right per-token rate for input, output, cache reads, and cache writes.
For manual tracking, you can pass cache tokens explicitly:
tokenr.track(
provider="anthropic",
model="claude-sonnet-4-20250514",
input_tokens=500,
output_tokens=200,
cache_read_tokens=8000,
cache_write_tokens=2000,
)
How It Works
tokenr.init()wraps thecreatemethod on OpenAI and Anthropic clients- After each call, token counts are read from the response
usagefield - A background daemon thread sends the data to Tokenr asynchronously
- If tracking fails for any reason, your app is completely unaffected
Examples
See the examples/ directory:
basic_openai.py— Simple OpenAI setupmulti_agent.py— Multiple agents, multiple providerssaas_multitenant.py— Per-team cost attribution
Getting Your API Token
- Sign up at tokenr.co
- Go to API Tokens and create a token
- Copy it — it's shown only once
export TOKENR_TOKEN="your-token-here"
Troubleshooting
No data showing up?
tokenr.init(token="your-token", debug=True)
# Prints: [Tokenr] Tracked: gpt-4 - $0.0012
- Verify
echo $TOKENR_TOKENreturns your token - Confirm you're making actual LLM API calls
- Check network access to
tokenr.co
Errors? The SDK never raises — it always fails silently. Use debug=True to see what's happening.
Running Tests
# Unit and mock tests (no API keys needed)
python -m unittest discover tests -v
# Live integration tests (makes real API calls, costs fractions of a cent)
OPENAI_API_KEY=sk-... ANTHROPIC_API_KEY=sk-ant-... python -m unittest tests.test_live_integration -v
The live tests make a real call to each provider, then verify that the token counts in the Tokenr payload match what the provider actually returned. This includes a test that triggers Anthropic prompt caching and confirms cache tokens are extracted correctly.
Security
This SDK is open source so you can audit exactly what data is sent and when. The short version:
- Only token counts, model names, and your attribution metadata are transmitted
- No prompt content or response content ever leaves your application
- All requests use HTTPS
- The tracker runs in a daemon thread and cannot block your process
License
MIT — see LICENSE
Support
- Issues: github.com/tokenr-co/tokenr-python/issues
- Email: support@tokenr.co
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tokenr-0.1.3.tar.gz.
File metadata
- Download URL: tokenr-0.1.3.tar.gz
- Upload date:
- Size: 18.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9d0c7b62ddba8acd84f5348327b954350ec47f4d3405820795847bf2212aa334
|
|
| MD5 |
1a229ad40f5aeaf643d4bb7fa7714077
|
|
| BLAKE2b-256 |
4db05eeb68c6b02c9c1a568217957f4efdd096ba9de6fdfc198b9e16fa481182
|
File details
Details for the file tokenr-0.1.3-py3-none-any.whl.
File metadata
- Download URL: tokenr-0.1.3-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c12b309ace9cdb51e7671a3650846089a438f178ce978216925263b1d22a2e9
|
|
| MD5 |
cf23e26a993cfb384fd8b066125e0524
|
|
| BLAKE2b-256 |
768d042e889c1ad4c314dc65907e549db131dcff9611edb4b65aeb608f8a8b72
|