Documentation

Everything you need

Integrate Pradvion into your stack in minutes.

Quick start

Get your first request tracked in under 5 minutes.

Installation

Python

pip install pradvion

v1.0.1 · pypi.org/project/pradvion

Node.js / TypeScript

npm install pradvion-node

v1.0.1 · npmjs.com/package/pradvion-node

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 automatically

Node.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 response

Agent / 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_id

API Keys

Authenticate the SDK with your project API key.

Generating a key

  1. Step 1: Go to Projects → select your project
  2. Step 2: Click the API Keys tab
  3. Step 3: Click Generate key
  4. Step 4: Copy the key immediately — it is shown only once
# Key format
nx_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Using 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 worker

Always 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 supported

Anthropic

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-20240307

Other 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).

Organization

Your Pradvion account. All projects, API keys, and usage data belong to your organization.

Project

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.

API Keynx_live_...

Authenticates the SDK for a specific project. Format: nx_live_... Generate one per project per environment. Shown only once — store securely.

Event / Request

One AI API call tracked by Pradvion. Contains provider, model, token counts, cost, latency, and optional context tags.

Feature tagfeature=

Labels what the AI is doing within your product. Examples: "resume-summarizer", "chatbot", "code-review". Used for cost breakdown by feature.

Customer IDcustomer_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 IDconversation_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.

Business signal

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.

Cost per outcome

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 tagsteam= / department=

Optional organizational labels. Team = squad-level (hr-team, infra). Department = org-level (engineering, marketing). Both appear as filter dimensions in Analytics.

Environmentenvironment=

Separates production from test traffic. Use "production", "staging", or "development". Filter to production-only in analytics to exclude test noise.

Markup

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.