Lightweight AI incident detection. Catch cost spikes, latency anomalies, and prompt bloat before they hit your users.
Project description
Agentracer Python SDK
Lightweight AI observability. Catch cost spikes, latency anomalies, and prompt bloat before they hit your users.
Installation
pip install agentracer
With provider-specific extras:
# OpenAI support
pip install agentracer[openai]
# Anthropic support
pip install agentracer[anthropic]
# Google Gemini support
pip install agentracer[gemini]
# All providers
pip install agentracer[all]
Quick Start
import agentracer
# Initialize once at app startup
agentracer.init(
tracker_api_key="at_your_api_key",
project_id="your_project_id",
environment="production"
)
Usage
OpenAI
from agentracer.openai import openai
# Use exactly like the normal OpenAI client
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}],
feature_tag="chatbot" # optional: tag this call
)
Anthropic
from agentracer.anthropic import anthropic
response = anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}],
feature_tag="summarizer" # optional: tag this call
)
Google Gemini
import google.generativeai as genai
from agentracer.gemini import gemini
# Configure your API key as usual
genai.configure(api_key="your-gemini-api-key")
model = gemini.GenerativeModel("gemini-1.5-pro")
response = model.generate_content(
"Hello!",
feature_tag="content-gen" # optional: tag this call
)
Custom Client Configuration
The default imports (openai, anthropic) create clients using environment variables. To pass custom configuration like api_key or base_url, use the class constructors:
OpenAI
from agentracer.openai import TrackedOpenAI
openai = TrackedOpenAI(api_key="sk-...", base_url="https://custom.api/v1")
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello!"}]
)
Anthropic
from agentracer.anthropic import TrackedAnthropic
anthropic = TrackedAnthropic(api_key="sk-ant-...")
response = anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello!"}]
)
Async Support
For async applications, use the async client wrappers:
Async OpenAI
from agentracer.openai import TrackedAsyncOpenAI
client = TrackedAsyncOpenAI()
async def chat(message: str):
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": message}],
feature_tag="async-chatbot"
)
return response.choices[0].message.content
Async Anthropic
from agentracer.anthropic import TrackedAsyncAnthropic
client = TrackedAsyncAnthropic()
async def chat(message: str):
response = await client.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": message}],
feature_tag="async-summarizer"
)
return response.content[0].text
Streaming
All providers support streaming. Token usage is automatically tracked after the stream completes.
OpenAI Streaming
from agentracer.openai import openai
stream = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Write a poem"}],
stream=True,
feature_tag="poet"
)
for chunk in stream:
content = chunk.choices[0].delta.content
if content:
print(content, end="")
# Telemetry is sent automatically after the stream ends
Anthropic Streaming
from agentracer.anthropic import anthropic
stream = anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a poem"}],
stream=True,
feature_tag="poet"
)
for event in stream:
if event.type == "content_block_delta":
print(event.delta.text, end="")
Gemini Streaming
from agentracer.gemini import gemini
model = gemini.GenerativeModel("gemini-1.5-pro")
stream = model.generate_content(
"Write a poem",
stream=True,
feature_tag="poet"
)
for chunk in stream:
print(chunk.text, end="")
Streaming works transparently -- usage is captured from the final chunk (OpenAI), SSE events (Anthropic), or chunk metadata (Gemini), then sent as a single telemetry event after the stream finishes.
Feature Tags
Feature tags let you group and track costs by feature across your application. There are three ways to apply them:
1. Inline (per-call)
Pass feature_tag directly on any tracked call:
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Summarize this"}],
feature_tag="summarizer"
)
2. Decorator
Use the @observe decorator to tag all LLM calls inside a function:
import agentracer
@agentracer.observe(feature_tag="chatbot")
def handle_chat(message: str):
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": message}]
)
return response
# Async functions work too
@agentracer.observe(feature_tag="async-chatbot")
async def handle_chat_async(message: str):
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": message}]
)
return response
3. Context Manager
Use feature_context for block-level tagging:
from agentracer import feature_context
with feature_context("report-generator"):
# All LLM calls in this block get tagged "report-generator"
summary = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Summarize the data"}]
)
analysis = anthropic.messages.create(
model="claude-sonnet-4-20250514",
max_tokens=2048,
messages=[{"role": "user", "content": "Analyze trends"}]
)
Agent Runs
Track multi-step agent workflows as a single run with AgentRun. Each LLM call inside the run is automatically recorded as a step.
from agentracer import AgentRun
from agentracer.openai import openai
with AgentRun(run_name="research-agent", feature_tag="research") as run:
# Step 1: Plan
plan = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Plan a research outline"}]
)
# Step 2: Execute
result = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": f"Research: {plan.choices[0].message.content}"}]
)
# Step 3: Summarize
summary = openai.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": f"Summarize: {result.choices[0].message.content}"}]
)
# All 3 steps are tracked under a single run with timing, tokens, and status
Async Agent Runs
AgentRun also works as an async context manager:
from agentracer import AgentRun
from agentracer.openai import TrackedAsyncOpenAI
client = TrackedAsyncOpenAI()
async def run_agent(query: str):
async with AgentRun(run_name="async-agent", feature_tag="agent") as run:
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}]
)
return response.choices[0].message.content
AgentRun Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
run_name |
str |
None |
Name for this run (shown in dashboard) |
feature_tag |
str |
"unknown" |
Feature tag applied to all steps |
end_user_id |
str |
None |
ID of the end user triggering this run |
run_id |
str |
auto-generated | Custom run ID (UUID v4 generated if omitted) |
What gets tracked per run
- Start/end timestamps and total duration
- Status:
completedorfailed(auto-detected from exceptions) - Each step: model, provider, tokens, latency, success/failure
- Aggregates: total steps, total tokens, total cost, total latency
Manual Tracking
For custom integrations or providers not yet supported, use track() directly:
import agentracer
agentracer.track(
model="gpt-4o",
input_tokens=150,
output_tokens=300,
latency_ms=420.5,
feature_tag="custom-pipeline",
provider="openai",
end_user_id="user-123", # optional: track per-user costs
cached_tokens=50, # optional: cached/prompt-cache tokens
)
FastAPI Example
from fastapi import FastAPI
import agentracer
from agentracer.openai import TrackedAsyncOpenAI
app = FastAPI()
client = TrackedAsyncOpenAI()
agentracer.init(
tracker_api_key="at_your_api_key",
project_id="your_project_id",
environment="production"
)
@app.post("/chat")
@agentracer.observe(feature_tag="chatbot")
async def chat(message: str):
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": message}]
)
return {"reply": response.choices[0].message.content}
@app.post("/summarize")
async def summarize(text: str):
with agentracer.feature_context("summarizer"):
response = await client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": f"Summarize: {text}"}]
)
return {"summary": response.choices[0].message.content}
@app.post("/agent")
async def agent(query: str):
async with agentracer.AgentRun(run_name="qa-agent", feature_tag="agent") as run:
response = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}]
)
return {"answer": response.choices[0].message.content}
Django Example
# settings.py
import agentracer
agentracer.init(
tracker_api_key="at_your_api_key",
project_id="your_project_id",
environment="production"
)
# views.py
from agentracer.openai import openai
from agentracer import feature_context, AgentRun
def chat_view(request):
message = request.POST.get("message")
with feature_context("django-chatbot"):
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": message}]
)
return JsonResponse({"reply": response.choices[0].message.content})
def agent_view(request):
query = request.POST.get("query")
with AgentRun(run_name="django-agent", feature_tag="agent"):
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": query}]
)
return JsonResponse({"answer": response.choices[0].message.content})
Configuration
agentracer.init(
tracker_api_key="at_your_api_key", # Required: your API key from the dashboard
project_id="your_project_id", # Required: your project ID
environment="production", # Optional: environment name (default: "production")
host="https://api.agentracer.dev", # Optional: API host (default: production)
debug=False, # Optional: enable debug logging (default: False)
enabled=True # Optional: enable/disable tracking (default: True)
)
| Parameter | Type | Default | Description |
|---|---|---|---|
tracker_api_key |
str |
required | Your API key from the Agentracer dashboard |
project_id |
str |
required | Your project ID |
environment |
str |
"production" |
Environment name (e.g., "staging", "development") |
host |
str |
"https://api.agentracer.dev" |
API endpoint |
debug |
bool |
False |
Print telemetry payloads to console |
enabled |
bool |
True |
Set to False to disable all tracking |
What We Track
Every LLM call automatically captures:
| Field | Description |
|---|---|
project_id |
Your project identifier |
provider |
LLM provider (openai, anthropic, gemini, custom) |
model |
Model name (e.g., gpt-4o, claude-sonnet-4-20250514) |
feature_tag |
Feature label for cost grouping |
input_tokens |
Number of input/prompt tokens |
output_tokens |
Number of output/completion tokens |
cached_tokens |
Prompt-cached tokens (OpenAI, Anthropic, Gemini) |
latency_ms |
Request latency in milliseconds |
success |
Whether the call succeeded |
error_type |
Exception class name on failure |
environment |
Deployment environment |
end_user_id |
End user identifier (when provided) |
We never capture prompts, responses, or any PII. Only metadata and usage metrics.
Troubleshooting
Telemetry not appearing in the dashboard
- Check your API key and project ID -- ensure they match what's in your dashboard.
- Enable debug mode to see what's being sent:
agentracer.init( tracker_api_key="at_your_api_key", project_id="your_project_id", debug=True )
- Check that tracking is enabled -- make sure you haven't set
enabled=False. - Verify network connectivity -- the SDK sends data to
https://api.agentracer.dev/api/ingest.
Import errors for provider modules
If you see ImportError: openai package not installed, install the provider extra:
pip install agentracer[openai]
# or
pip install agentracer[anthropic]
# or
pip install agentracer[gemini]
Feature tags showing as "unknown"
Make sure you're setting feature tags using one of the three methods:
- Inline:
feature_tag="my-feature"on the call - Decorator:
@agentracer.observe(feature_tag="my-feature") - Context manager:
with agentracer.feature_context("my-feature"):
SDK not throwing errors
This is by design. The SDK uses a fire-and-forget pattern and silently catches all exceptions to ensure it never impacts your application's performance or reliability.
License
MIT
Project details
Release history Release notifications | RSS feed
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 agentracer-0.1.0.tar.gz.
File metadata
- Download URL: agentracer-0.1.0.tar.gz
- Upload date:
- Size: 12.4 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
993544c8c9fb628853b2008c626c6dbdb7acae71069e6ae531a3ff1ebb6c3202
|
|
| MD5 |
f745286bae3e78c9aecb4d3e406f3ab0
|
|
| BLAKE2b-256 |
89eb6974fe15605a426494fea74336c3d9c7b83baf8cfdf1cbb5cc24706305c4
|
File details
Details for the file agentracer-0.1.0-py3-none-any.whl.
File metadata
- Download URL: agentracer-0.1.0-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e344853fca4f1a576737ae90a1e5c4ff12ff347a4b449e257d1b543e78ef22d7
|
|
| MD5 |
1d2a1588934e36c6343260ad396eded1
|
|
| BLAKE2b-256 |
850092ac59e0a37a0f594ac26d9af86789629a1d67784a4e003e98cc426a2418
|