Documentation
Everything you need
Integrate Pradvion into your stack in minutes.
Quick start
Get your first request tracked in under 5 minutes.
Installation
Tracking never blocks your app. The SDK writes events to a local queue instantly, then flushes in the background. Data is never lost — even if Pradvion goes down, events are persisted locally and retried automatically.
Python quick start
import openai
import pradvion
# Initialize once at startup
pradvion.init(api_key="nx_live_...")
# Wrap your OpenAI client — drop-in replacement
client = pradvion.wrap(openai.OpenAI())
# Tag with business context
with pradvion.context(
feature="resume-summarizer",
customer_id="customer-001", # hashed automatically
team="hr-team",
environment="production"
):
response = client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": "Hello"}]
)
# Cost, tokens, and latency tracked automaticallyNode.js / TypeScript quick start
import OpenAI from "openai"
import * as pradvion from "pradvion-node"
// Initialize once at startup
pradvion.init({ apiKey: "nx_live_..." })
// Wrap your OpenAI client
const client = pradvion.monitor(new OpenAI())
// Tag with business context
await pradvion.context(
{ feature: "resume-summarizer", customerId: "customer-001", environment: "production" },
async () => {
const response = await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
})
}
)Middleware pattern (FastAPI)
Set context once per request so every AI call in that request is automatically tagged.
@app.middleware("http")
async def pradvion_middleware(request, call_next):
user = get_current_user(request)
pradvion.set_context(
customer_id=user.company_id,
environment="production"
)
response = await call_next(request)
pradvion.clear_context()
return responseAgent / multi-step usage
Use conversation_id to group all LLM calls within a single agent run. Filter by it in the Requests page to see total cost per run.
import pradvion
run_id = pradvion.new_conversation() # generates a unique ID
with pradvion.context(
feature="research-agent",
customer_id="my-company",
conversation_id=run_id # groups all calls in this run
):
plan = client.chat.completions.create(...) # step 1
search = client.chat.completions.create(...) # step 2
report = client.chat.completions.create(...) # step 3
# All 3 calls appear in dashboard linked by conversation_idAPI Keys
Authenticate the SDK with your project API key.
Generating a key
- Step 1: Go to Projects → select your project
- Step 2: Click the API Keys tab
- Step 3: Click Generate key
- Step 4: Copy the key immediately — it is shown only once
# Key format
nx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxUsing your key
# Python
pradvion.init(api_key="nx_live_...")
# Node.js
pradvion.init({ apiKey: "nx_live_..." })
# Environment variable (recommended)
# Set PRADVION_API_KEY in your environment
pradvion.init(api_key=os.environ["PRADVION_API_KEY"])Security best practices
- • Store in environment variables, never in source code
- • Never commit to git or share publicly
- • Create one key per project per environment (production / staging)
- • Revoke immediately if compromised: Dashboard → API Keys → Revoke
SDK Reference
Complete reference for the Python and Node.js SDKs.
init()
Initialize the SDK. Call once at application startup before any AI calls.
# Python
pradvion.init(
api_key="nx_live_...", # required
base_url="https://...", # optional — default: Pradvion cloud
timeout=5, # HTTP timeout in seconds (default: 5)
async_tracking=True, # non-blocking background queue (default: True)
auto_flush=True # flush on process exit (default: True)
)// Node.js
pradvion.init({
apiKey: "nx_live_...", // required
baseUrl: "https://...", // optional
timeout: 5000, // milliseconds (default: 5000)
autoFlush: true, // flush on process exit (default: true)
})wrap() / monitor()
Wrap an AI client. Returns a drop-in replacement — no code changes needed.
# Python — pradvion.wrap() or pradvion.monitor() (aliases)
import openai, anthropic, pradvion
openai_client = pradvion.wrap(openai.OpenAI())
async_client = pradvion.wrap(openai.AsyncOpenAI())
anthropic_client = pradvion.wrap(anthropic.Anthropic())// Node.js — pradvion.monitor()
import OpenAI from "openai"
import Anthropic from "@anthropic-ai/sdk"
import * as pradvion from "pradvion-node"
const openai = pradvion.monitor(new OpenAI())
const anthropic = pradvion.monitor(new Anthropic())Streaming is fully supported — tokens accumulate correctly across chunks. Errors (status 500+) are tracked automatically including partial streaming failures.
context()
Tag all AI calls within a block. All parameters are optional.
# Python — context manager
with pradvion.context(
feature="resume-summarizer", # what the AI is doing
team="hr-team", # which team owns this
department="engineering", # which department
customer_id="customer-001", # auto-hashed with SHA-256
environment="production", # separates prod from test traffic
conversation_id="run-abc-123",# groups multi-step agent calls
project="my-project" # optional project name/slug
):
response = client.chat.completions.create(...)// Node.js — async function wrapper
await pradvion.context(
{
feature: "resume-summarizer",
customerId: "customer-001",
environment: "production",
conversationId: "run-abc-123",
project: "my-project", // optional project name/slug
},
async () => {
const response = await client.chat.completions.create(...)
}
)trace()
Shorthand for context() — pass a customer ID string directly without a config object.
// Node.js — wrap a handler with a single customer ID
const result = await pradvion.trace("customer-001", async () => {
return await client.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
})
})
// Equivalent to:
await pradvion.context({ customerId: "customer-001" }, async () => { ... })set_context() / clear_context()
For middleware — set once per request instead of wrapping each call.
# Python — middleware pattern
pradvion.set_context(
customer_id=user.company_id,
environment="production",
feature="api-handler"
)
# ... handle request ...
pradvion.clear_context()
# Node.js
pradvion.setContext({ customerId: user.companyId, environment: "production" })
// ... handle request ...
pradvion.clearContext()track()
Manually track an AI call without using the client wrapper.
# Python
pradvion.get_client().track(
provider="openai",
model="gpt-4o",
input_tokens=1200,
output_tokens=400,
latency_ms=850,
status_code=200,
feature="chatbot",
customer_id="my-company",
environment="production",
cached_tokens=200, # optional — reduces cost (50% rate)
reasoning_tokens=100, # optional — o1/o3 models
)// Node.js
pradvion.getClient().track({
provider: "openai",
model: "gpt-4o",
inputTokens: 1200,
outputTokens: 400,
latencyMs: 850,
statusCode: 200,
feature: "chatbot",
customerId: "my-company",
cachedTokens: 200,
reasoningTokens: 100,
})track_error() / trackError()
Track a failed AI call for cost attribution and error monitoring.
# Python
try:
response = client.chat.completions.create(...)
except Exception as e:
pradvion.track_error(
provider="openai",
model="gpt-4o",
error=str(e),
status_code=500,
latency_ms=elapsed_ms,
feature="chatbot"
)// Node.js
try {
const response = await client.chat.completions.create(...)
} catch (e) {
pradvion.getClient().trackError({
provider: "openai",
model: "gpt-4o",
error: String(e),
statusCode: 500,
latencyMs: elapsedMs,
})
}track_batch() / trackBatch()
Track multiple AI calls in one operation.
# Python
pradvion.track_batch([
{ "provider": "openai", "model": "gpt-4o", "input_tokens": 500, "output_tokens": 200, "latency_ms": 800 },
{ "provider": "anthropic", "model": "claude-sonnet-4-6", "input_tokens": 300, "output_tokens": 150, "latency_ms": 600 },
])new_conversation()
Generate a unique conversation ID to group related agent calls.
# Python
run_id = pradvion.new_conversation() # returns a UUID string
with pradvion.context(conversation_id=run_id, feature="research-agent"):
step1 = client.chat.completions.create(...)
step2 = client.chat.completions.create(...)// Node.js
const runId = pradvion.newConversation()
await pradvion.context({ conversationId: runId, feature: "research-agent" }, async () => {
const step1 = await client.chat.completions.create(...)
const step2 = await client.chat.completions.create(...)
})flush() / shutdown()
Force-flush the local queue before process exit. Use in scripts, Lambda functions, or tests.
# Python
import pradvion
# ... track some events ...
pradvion.flush(timeout=10.0) # wait up to 10s for all events to send
pradvion.shutdown() # flush + stop background worker gracefully// Node.js
await pradvion.flush() // wait for all pending events
await pradvion.shutdown() // flush + stop workerAlways call flush() in short-lived processes (scripts, serverless functions) to ensure events are sent before the process exits.
Business Signals
Track business outcomes alongside AI costs to compute cost-per-outcome and margin.
What are signals?
Signals are business events — a meeting booked, an email sent, a lead qualified, a report generated. Pradvion joins signals with AI costs on customer_id to compute cost-per-outcome: how much AI spend produced each business result.
signal() — track a business event
# Python
pradvion.signal(
customer_id="customer-001", # links back to AI costs for this customer
event="meeting_booked", # lowercase, snake_case
quantity=1, # number of outcomes (default: 1)
value=150.00, # dollar value of the outcome (optional)
feature="outreach-agent", # optional tags
team="sales",
environment="production"
)// Node.js
pradvion.signal({
customerId: "customer-001",
event: "meeting_booked",
quantity: 1,
value: 150.00,
feature: "outreach-agent",
environment: "production",
})signal_batch() / signalBatch()
Send multiple signals in one call.
# Python
pradvion.signal_batch([
{ "customer_id": "my-company", "event": "email_sent", "quantity": 50 },
{ "customer_id": "my-company", "event": "meeting_booked", "quantity": 3, "value": 450.0 },
{ "customer_id": "my-company", "event": "deal_closed", "quantity": 1, "value": 12000.0 },
])Tracking signals alongside AI calls
import pradvion
# 1. Run your AI agent
with pradvion.context(customer_id="my-company", feature="outreach-agent"):
draft = client.chat.completions.create(model="gpt-4o", ...)
scored = client.chat.completions.create(model="gpt-4o-mini", ...)
# 2. After the downstream outcome happens, record the signal
if email_was_sent:
pradvion.signal(
customer_id="my-company",
event="email_sent",
quantity=1
)
if meeting_was_booked:
pradvion.signal(
customer_id="my-company",
event="meeting_booked",
quantity=1,
value=150.0 # expected revenue value
)Pradvion automatically computes cost per meeting booked, margin per customer, and ROI per feature in the Unit Economics dashboard.
Provider Setup
Supported AI providers and models.
OpenAI
import openai, pradvion
pradvion.init(api_key="nx_live_...")
client = pradvion.wrap(openai.OpenAI())
# Supported models (pricing tracked automatically):
# gpt-4o gpt-4o-mini gpt-4.1 gpt-4.1-mini
# gpt-4-turbo gpt-3.5-turbo o1 o1-mini
# o3-mini text-embedding-3-large text-embedding-3-small
# Reasoning tokens (o1/o3) tracked separately — billed at output rate
client = pradvion.wrap(openai.AsyncOpenAI()) # async also supportedAnthropic
import anthropic, pradvion
pradvion.init(api_key="nx_live_...")
client = pradvion.wrap(anthropic.Anthropic())
# Supported models:
# claude-opus-4-6 claude-opus-4-7
# claude-sonnet-4-6 claude-haiku-4-5
# claude-3-5-sonnet-20241022 claude-3-5-haiku-20241022
# claude-3-opus-20240229 claude-3-haiku-20240307Other providers (coming soon)
Native SDK support for Google (Gemini), Mistral, and Cohere is coming soon. Follow hello@pradvion.com for updates.
LangChain & Agents
Native integrations for LangChain, LangGraph, LlamaIndex, and agent frameworks.
LangChain callback (Python)
from langchain_openai import ChatOpenAI
from pradvion.integrations.langchain import PradvionCallback
import pradvion
pradvion.init(api_key="nx_live_...")
# Add Pradvion callback — all LLM calls are tracked automatically
callback = PradvionCallback(
feature="research-chain",
customer_id="my-company",
environment="production"
)
llm = ChatOpenAI(model="gpt-4o", callbacks=[callback])
# Works with chains, agents, and runnables
response = llm.invoke("Summarize this document")LangChain callback (Node.js / TypeScript)
import { ChatOpenAI } from "@langchain/openai"
import { PradvionCallbackHandler } from "pradvion-node/integrations/langchain"
import * as pradvion from "pradvion-node"
pradvion.init({ apiKey: "nx_live_..." })
const callback = new PradvionCallbackHandler({
feature: "research-chain",
customerId: "my-company",
environment: "production",
})
const llm = new ChatOpenAI({
model: "gpt-4o",
callbacks: [callback],
})LangGraph (Python)
LangGraph uses LangChain under the hood — the same callback works.
from langgraph.graph import StateGraph
from langchain_openai import ChatOpenAI
from pradvion.integrations.langchain import PradvionCallback
import pradvion
pradvion.init(api_key="nx_live_...")
run_id = pradvion.new_conversation()
callback = PradvionCallback(
feature="research-agent",
customer_id="my-company",
conversation_id=run_id # groups all steps in this run
)
llm = ChatOpenAI(model="gpt-4o", callbacks=[callback])
# Build your graph normally — every LLM node is tracked
graph = StateGraph(...)
...
graph.invoke(inputs)Manual agent tracking
For CrewAI, AutoGen, or any framework — wrap individual calls manually.
import pradvion
run_id = pradvion.new_conversation()
# Set context for the entire agent run
with pradvion.context(
feature="research-agent",
customer_id="my-company",
conversation_id=run_id,
environment="production"
):
# Each sub-call tracked automatically if client is wrapped
plan_response = wrapped_client.chat.completions.create(...)
search_response = wrapped_client.chat.completions.create(...)
report_response = wrapped_client.chat.completions.create(...)
# Track the business outcome once agent completes
if task_completed:
pradvion.signal(
customer_id="my-company",
event="report_generated",
quantity=1,
value=50.0
)LlamaIndex (Python)
Track every LLM call made by a LlamaIndex pipeline with one callback.
from llama_index.core import Settings
from llama_index.core.callbacks import CallbackManager
from pradvion.integrations.llamaindex import PradvionLlamaCallback
import pradvion
pradvion.init(api_key="nx_live_...")
callback = PradvionLlamaCallback(
feature="rag-pipeline",
customer_id="my-company",
environment="production"
)
# Set globally — all LlamaIndex pipelines are tracked
Settings.callback_manager = CallbackManager([callback])
# Use LlamaIndex as normal — all LLM calls appear in Pradvion
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
response = query_engine.query("What are the main findings?")OpenTelemetry integration
Use the OTEL exporter to ingest traces from any instrumented LLM framework.
from pradvion.integrations.otel import PradvionSpanExporter
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
exporter = PradvionSpanExporter(api_key="nx_live_...")
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(exporter))
# Pradvion reads GenAI semantic conventions from your OTEL spans
# Compatible with: OpenLLMetry, Langfuse OTEL, traceloop, etc.Core Concepts
Key terms and how Pradvion works under the hood.
SDK wrapper approach — not a proxy
Pradvion uses an SDK wrapper — not a proxy. Your requests go directly from your application to OpenAI or Anthropic. The SDK captures metadata non-blocking after each call and sends it to Pradvion in the background. Zero latency impact. Zero infrastructure dependency. If Pradvion goes down, your app keeps running — only tracking pauses, and no data is lost (events are persisted locally and retried).
Your Pradvion account. All projects, API keys, and usage data belong to your organization.
Groups AI usage for one client, product, or service. Each project has its own API key, budget, and analytics. Example: Support Bot, Email Assistant, Report Generator.
nx_live_...Authenticates the SDK for a specific project. Format: nx_live_... Generate one per project per environment. Shown only once — store securely.
One AI API call tracked by Pradvion. Contains provider, model, token counts, cost, latency, and optional context tags.
feature=Labels what the AI is doing within your product. Examples: "resume-summarizer", "chatbot", "code-review". Used for cost breakdown by feature.
customer_id=Your end-user or client identifier (e.g. company slug or user ID). The SDK hashes it with SHA-256 before sending — Pradvion never sees the raw value. Used to compute per-customer cost and unit economics.
conversation_id=Groups multiple LLM calls that belong to the same agent run or multi-turn conversation. Generate with pradvion.new_conversation(). Filter by it in the Requests page to see total cost for one run.
A downstream business outcome — meeting booked, email sent, deal closed. Pradvion joins signals with AI costs on customer_id to compute cost-per-outcome and margin per customer.
Total AI spend ÷ total signal quantity for a given customer + feature + event combination. The Unit Economics dashboard shows this automatically once you send both events and signals.
team= / department=Optional organizational labels. Team = squad-level (hr-team, infra). Department = org-level (engineering, marketing). Both appear as filter dimensions in Analytics.
environment=Separates production from test traffic. Use "production", "staging", or "development". Filter to production-only in analytics to exclude test noise.
A percentage you can set per project or organization. Applied in reconciliation reports — if you charge clients more than raw AI cost, Pradvion computes the invoice amount automatically.