wrap()
wrap() is the one entry point you need. It identifies the provider from the client you hand it and returns the matching wrapper.
from anthropic import Anthropic
from tokeven import wrap
tracked = wrap(
Anthropic(), # Anthropic / OpenAI / xAI / Google GenAI client
ingest_token="tkv_ing_...", # or set TOKEVEN_INGEST_TOKEN
base_url="https://api.tokeven.com",
project="checkout-api", # optional label attached to every event
session_id="onboarding-run", # optional: group calls into one session
)Pass an object it cannot identify and it raises TypeError rather than guessing - an unrecognised client used to be treated as Anthropic and failed much later with a confusing AttributeError.
Explicit wrappers
Each provider also has a class, and they take exactly the same keyword arguments as wrap():
from tokeven import TokevenAnthropic, TokevenOpenAI, TokevenGemini, TokevenXAI
tracked = TokevenOpenAI(OpenAI(), ingest_token="tkv_ing_...", base_url="https://api.tokeven.com")Every wrapper proxies unknown attributes straight through to the client it wraps, so your call sites do not change.
Configuration options
Each keyword argument sets a field on TokevenConfig. Explicit kwargs win over the environment variable.
| Option | Env var | Default | Description |
|---|---|---|---|
ingest_token | TOKEVEN_INGEST_TOKEN | none | Your write-only ingest token |
base_url | TOKEVEN_BASE_URL | http://localhost:8000 | Set this to https://api.tokeven.com in production |
project | TOKEVEN_PROJECT | none | Logical project label attached to events |
mode | TOKEVEN_MODE | per-prompt | per-prompt or per-session |
session_id | - | none | Groups related calls together; events carry no session unless you set one |
enabled | TOKEVEN_ENABLED | true | Toggle tracking off without removing the wrapper |
flush_interval_s | - | 5.0 | Seconds between background flushes |
flush_threshold | - | 50 | Events buffered before a flush is triggered |
queue_max_events | - | 10000 | Bound on the durable local queue |
compact_after_tokens | TOKEVEN_COMPACT_AFTER_TOKENS | none | Compact the conversation past N estimated tokens |
nudges_enabled | TOKEVEN_NUDGES | true | Local efficiency nudges |
A misspelled option is not silently accepted: unknown kwargs are logged as a warning (with a "did you mean" suggestion) and ignored, because token= instead of ingest_token= once produced a wrapper that looked configured and never sent an event.
Methods
- •
tracked.estimate(model=..., messages=[...])- pre-send advisor; returns cross-provider options with cost and confidence, entirely client-side - •
tracked.flush()- force a blocking flush of buffered events - •
tracked.close()- flush, stop the emitter, and dispatch end-of-session nudges
Event schema
Each tracked call generates an event with:
- •
event_id- client-generated UUID for idempotency - •
occurred_at- ISO 8601 timestamp - •
provider-anthropic|openai|google|xai - •
model- model ID used - •
modality-text|vision|audio, detected from message structure, never by reading content - •
input_tokens- prompt token count - •
output_tokens- completion token count - •
cache_read_tokens- tokens served from cache - •
cache_creation_tokens- tokens written to cache - •
prompt_length- a local character count, never the text itself - •
latency_ms- request duration - •
session_id/project- your optional labels - •
advisor_used/original_model- set when you accept an advisor suggestion, so the saving can be verified
No prompt or completion content appears anywhere in an event; the emitter enforces this with a field allowlist before the batch leaves your machine.