Python SDK for MetricAI — AI billing and metering proxy
Project description
MetricAI Python SDK
AI billing and metering proxy for India — route LLM calls, track costs, attribute spend, and manage budgets in INR/UPI.
Modes
MetricAI SDK supports two modes of operation:
| Mode | Description |
|---|---|
| Cloud Mode | Route traffic through MetricAI proxy with SaaS dashboard |
| Local Mode | Zero-egress tracking with local SQLite and dashboard |
Local Mode is ideal for:
- Enterprise deployments
- Air-gapped environments
- Compliance requirements
- Cost-sensitive projects
Get started with Local Mode: Quick Start Guide
Features
| Capability | Description |
|---|---|
| Local Mode (NEW) | Zero-egress tracking with SQLite — no data leaves your environment |
| Multi-Provider Proxy | Route OpenAI, Anthropic, Gemini, Grok, Groq, Perplexity, and more through a single endpoint |
| Native SDK Compatibility | Use official provider SDKs with zero code changes via instrument() |
| Per-Agent & Per-User Attribution | Group costs by agent_id and user_id in the dashboard |
| Budget Caps | Hard INR caps per agent or conversation to prevent runaway spend |
| Outcome Billing | Charge on success/failure outcomes, not just token usage |
| Streaming Telemetry | Track token counts and tool usage in real-time for streaming responses |
| Agentic Workflows | Built-in MetricAIAgent and MetricAIPipeline with tool calling and governance |
| Framework Integrations | LangChain, LangGraph, CrewAI, LlamaIndex, AutoGen, FastAPI, Django |
| Voice AI Tracking | Deepgram, ElevenLabs, Sarvam with voice-specific metrics |
| LiveKit Integration | Track LiveKit voice agents with billing and attribution |
| BYOK Support | Bring your own API keys — MetricAI never stores them |
| Fail-Open | Requests forward directly to providers if the proxy is unreachable |
Installation
pip install metricai
With Optional Providers
# Just OpenAI
pip install "metricai[openai]"
# Just Anthropic
pip install "metricai[anthropic]"
# All providers at once
pip install "metricai[all]"
Available extras: openai, anthropic, gemini, groq, grok, perplexity, bedrock, tavily, langchain, langgraph, crewai, llamaindex, fastapi, django, deepgram, elevenlabs, sarvam
Quickstart
1. Set your API key
export METRICAI_API_KEY="your_metricai_api_key"
For BYOK mode (bring your own provider keys):
export METRICAI_API_KEY="your_metricai_api_key"
export OPENAI_API_KEY="sk-proj-..." # Optional — for OpenAI routes
export ANTHROPIC_API_KEY="sk-ant-..." # Optional — for Anthropic routes
export GEMINI_API_KEY="AI..." # Optional — for Gemini routes
2. Use native SDKs via proxy
from metricai import MetricAI
client = MetricAI(api_key="your_metricai_api_key")
# OpenAI via proxy
openai_client = client.openai_sdk(agent_id="support-agent", user_id="user_42")
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "What's the weather in Mumbai?"}]
)
print(response.choices[0].message.content)
3. Track usage and costs
from metricai import MetricAI, MetricAISession, timed_call
client = MetricAI(api_key="your_metricai_api_key")
# Session-based tracking with budget cap
with MetricAISession(client, agent_id="booking-agent", user_id="user_123", max_budget_inr=50.0) as session:
response = client.openai_sdk().chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Book a flight to Delhi"}]
)
session.track(provider="openai", model="gpt-4o-mini", input_tokens=1500, output_tokens=300)
4. Outcome billing
# Simulate first to estimate cost
client.track(
provider="openai",
model="gpt-4o-mini",
outcome={"success": True, "outcome_type": "booking_confirmed", "charge_on_success_inr": 2.5},
simulate=True,
)
# Live outcome billing
client.track(
provider="openai",
model="gpt-4o-mini",
outcome={"success": True, "charge_on_success_inr": 2.5},
latency_ms=850,
)
5. Standalone agent with tools
from metricai import MetricAI
from metricai.workflow import MetricAIAgent
client = MetricAI(api_key="your_metricai_api_key", llm_keys={"gemini": "your_gemini_key"})
agent = MetricAIAgent(
client,
agent_id="research-agent",
user_id="user_456",
model="gemini-2.0-flash",
system_prompt="You are a helpful research assistant.",
budget_cap_inr=25.0,
)
response = agent.run("What are the top 5 AI news stories today?")
print(response.content)
Core Concepts
Client Initialization
from metricai import MetricAI, MetricAIConfig
# Simple initialization
client = MetricAI(api_key="your_metricai_api_key")
# With configuration object
config = MetricAIConfig(
api_key="your_metricai_api_key",
mode="byok", # "byok" or "managed"
llm_keys={"openai": "sk-..."}, # Provider keys for BYOK mode
proxy_base_url="https://proxy.metricai.co.in",
default_billing_mode="hybrid", # "usage", "outcome", or "hybrid"
default_budget_cap_inr=100.0, # Daily INR cap
fail_open=True, # Forward to provider if proxy unreachable
)
client = MetricAI(config=config)
Headers and Attribution
# Get headers for any SDK call
headers = client.headers(
agent_id="my-agent",
user_id="user_123",
session_id="session_abc",
billing_mode="hybrid",
budget_cap_inr=50.0,
)
# Pass headers to any HTTP client
response = openai_client.chat.completions.create(
model="gpt-4o",
messages=[...],
extra_headers=headers,
)
Routing
from metricai import MetricAI, RoutingConfig, RoutingManager
client = MetricAI(api_key="your_metricai_api_key")
# Configure routing policy server-side
router = RoutingManager(client)
router.configure(
agent_id="routing-agent",
strategy="cost-optimized",
config={"max_model": "gpt-4o-mini", "fallback_model": "gpt-3.5-turbo"}
)
# Or via config
client = MetricAI(
api_key="your_metricai_api_key",
routing=RoutingConfig(strategy="latency-optimized")
)
Global Instrumentation
Instrument all provider SDK clients globally — no need to change existing code:
from metricai import init, instrument
# Initialize once at app startup
init(api_key="your_metricai_api_key", auto_instrument=True)
# All subsequent OpenAI/Anthropic calls are automatically routed through MetricAI
from openai import OpenAI
client = OpenAI() # Already patched — routes through MetricAI proxy
Framework Integrations
LangChain
from langchain_openai import ChatOpenAI
from metricai.integrations.langchain import MetricAIChatCallbackHandler
handler = MetricAIChatCallbackHandler(agent_id="lc-agent", user_id="user_1")
llm = ChatOpenAI(callbacks=[handler])
response = llm.invoke("Hello!")
LangGraph
from langgraph.prebuilt import create_react_agent
from metricai.integrations.langgraph import MetricAIGraphTracer
tracer = MetricAIGraphTracer(agent_id="graph-agent", user_id="user_2")
agent = create_react_agent(model, tools, tracer=tracer)
CrewAI
from crewai import Agent
from metricai.integrations.crewai import MetricAICrewAIWrapper
wrapper = MetricAICrewAIWrapper(api_key="your_key")
agent = wrapper.wrap_agent(
Agent(role="Researcher", goal="Find AI news", backstory="You are a researcher"),
agent_id="crewai-researcher",
)
FastAPI Middleware
from fastapi import FastAPI
from metricai.integrations.web import MetricAIFastAPIMiddleware
app = FastAPI()
app.add_middleware(
MetricAIFastAPIMiddleware,
api_key="your_metricai_api_key",
default_agent_id="fastapi-agent",
)
Environment Variables
| Variable | Description | Default |
|---|---|---|
METRICAI_API_KEY |
Your MetricAI API key | Required |
METRICAI_PROXY_URL |
Proxy base URL | https://proxy.metricai.co.in |
METRICAI_API_URL |
Telemetry API URL | Same as proxy URL |
METRICAI_ENVIRONMENT |
production or sandbox |
production |
OPENAI_API_KEY |
BYOK key for OpenAI | — |
ANTHROPIC_API_KEY |
BYOK key for Anthropic | — |
GEMINI_API_KEY |
BYOK key for Gemini | — |
Supported Providers
| Provider | Proxy Path | Native SDK |
|---|---|---|
| OpenAI | /v1/proxy/openai |
✅ openai |
| Anthropic | /v1/proxy/claude |
✅ anthropic |
| Gemini | /v1/proxy/gemini |
✅ google-genai |
| Grok | /v1/proxy/grok |
✅ xai-sdk |
| Groq | /v1/proxy/groq |
✅ groq |
| Perplexity | /v1/proxy/perplexity |
✅ perplexityai |
| AWS Bedrock | /v1/proxy/bedrock |
✅ boto3 |
| Tavily | /v1/proxy/tavily |
✅ tavily-python |
| Deepgram | /v1/proxy/deepgram |
✅ deepgram-sdk |
| ElevenLabs | /v1/proxy/elevenlabs |
✅ elevenlabs |
| Sarvam | /v1/proxy/sarvam |
✅ sarvamai |
Error Handling
from metricai import (
MetricAI,
MetricAIError,
MetricAIAuthError,
MetricAIQuotaExhaustedError,
MetricAIRateLimitError,
MetricAIProxyError,
)
client = MetricAI(api_key="your_metricai_api_key")
try:
response = client.openai_sdk().chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}]
)
except MetricAIAuthError:
print("Invalid API key")
except MetricAIQuotaExhaustedError:
print("Budget cap reached — upgrade your plan")
except MetricAIRateLimitError:
print("Rate limited — retry after a moment")
except MetricAIProxyError as e:
print(f"Proxy error: {e}")
except MetricAIError as e:
print(f"Unexpected error: {e}")
API Reference
MetricAI
Main client class for all operations.
MetricAI(
api_key: str, # Required: your MetricAI API key
base_url: str | None = None, # Override proxy URL
timeout: int = 60, # Request timeout in seconds
agent_id: str | None = None, # Default agent ID
user_id: str | None = None, # Default user ID
billing_mode: str | None = None, # "usage", "outcome", or "hybrid"
budget_cap_inr: float | None = None, # Daily budget cap in INR
mode: str = "byok", # "byok" or "managed"
llm_keys: dict | None = None, # Provider API keys
config: MetricAIConfig | None = None, # Configuration object
)
Methods:
openai_sdk(...)→ Returns OpenAI-compatible client routed through proxyanthropic_sdk(...)→ Returns Anthropic client routed through proxygemini_sdk(...)→ Returns Gemini client routed through proxygrok_sdk(...)→ Returns Grok client routed through proxyheaders(...)→ Returns headers dict for any SDK calltrack(...)→ Track a billing eventtrack_stream(...)→ Track streaming responsessession(...)→ Context manager for session trackingget_quota_status()→ Get current billing usage
MetricAISession
Session context manager for grouped tracking:
with MetricAISession(
client,
agent_id="my-agent",
user_id="my-user",
max_budget_inr=50.0,
) as session:
# Your LLM calls here
session.track(provider="openai", model="gpt-4o", input_tokens=100, output_tokens=50)
MetricAIAgent
Tool-capable agent with built-in governance:
agent = MetricAIAgent(
client,
agent_id="my-agent",
user_id="my-user",
provider="openai", # or "anthropic", "gemini", "grok"
model="gpt-4o",
system_prompt="You are a helpful assistant.",
tools=[...], # Optional: list of tool definitions
max_iterations=10,
budget_cap_inr=25.0,
billing_mode="hybrid",
)
response = agent.run("User's request here")
print(response.content)
print(f"Tokens: {response.input_tokens} + {response.output_tokens}")
Examples
More examples are available in the examples/ directory:
byok_openai_sdk.py— Using official SDKs via proxystandalone_workflow.py— Standalone agent with toolslangchain_metricai_sample.py— LangChain integrationlanggraph_tracer.py— LangGraph tracingcrewai_crew.py— CrewAI integration
License
MIT License — see LICENSE for details.
Support
- Documentation: https://docs.metricai.co.in
- Issues: GitHub Issues
- Email: support@metricai.co.in
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 metricai-0.7.3.tar.gz.
File metadata
- Download URL: metricai-0.7.3.tar.gz
- Upload date:
- Size: 15.7 MB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f5f3717d0e40d9bc59c636f451437d5ae6e1fbb5dc0448e1ef760503bc087494
|
|
| MD5 |
5fd51388efd1f8ffec51d1064c5dadfd
|
|
| BLAKE2b-256 |
e5697f3d435b611cf34ec39a625649a9154e7655a5f74f3a3fdc4e702dac3fc5
|
File details
Details for the file metricai-0.7.3-py3-none-any.whl.
File metadata
- Download URL: metricai-0.7.3-py3-none-any.whl
- Upload date:
- Size: 193.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.11.15
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
03933cd0b0ef6fc16e7eab7a41b87769ae38409a9b331a807849d77467c4b784
|
|
| MD5 |
269e9f57f2b12f74c26c14f9add177f1
|
|
| BLAKE2b-256 |
40bdcce41ecde16346fd11c2ab2a320b9c6a260a41af2d08f523e3addd2141ac
|