Skip to main content

saive

Zero-friction LLM footprint reporting. Patches the OpenAI, Anthropic and Google GenAI Python clients to report token usage to saive asynchronously, in the background, without ever seeing your prompts or completions.

pip install saive-client
import saive
saive.init()  # reads SAIVE_API_KEY from the environment

from openai import OpenAI
client = OpenAI()  # unchanged from here on — sync, async, and streaming all work

That's the entire integration. If SAIVE_API_KEY isn't set, saive.init() is a complete no-op — safe to call unconditionally, including from library code that doesn't know whether its caller uses saive.

What this does and does not do

  • Not a proxy. Your calls to OpenAI/Anthropic/Google go straight to them, exactly as before. saive never sits in the request path, never sees your API keys for those providers, and a saive outage is invisible to your application — every failure path here degrades to a silent no-op plus one warning-level log line, never an exception.
  • Never sends prompt or completion content. Only the model string, input/output/ reasoning token counts, a timestamp, and latency are extracted from each response's usage object. Nothing else is read from your requests or responses.
  • Never blocks. Usage is buffered in memory and flushed from a background thread on a size/time trigger, plus once more at interpreter exit. Buffered events are dropped (not retried indefinitely, never written to disk) if saive can't be reached — an acceptable loss for a component whose numbers are estimates with wide uncertainty bands already.

Configuration

All via environment variables — there is no config object to construct.

Variable Default
SAIVE_API_KEY (none) Required. Without it, init() patches nothing.
SAIVE_DISABLED (unset) Set to 1 to force saive off regardless of SAIVE_API_KEY.
SAIVE_BASE_URL production saive endpoint Override for self-hosted saive deployments.
SAIVE_FLUSH_INTERVAL_SECONDS 5 How often the background thread flushes.
SAIVE_MAX_BUFFER_SIZE 500 Max events buffered before new ones are dropped.
SAIVE_MAX_RETRIES 2 Retries (with backoff) per flush before discarding the batch.

Tagging

with saive.tags(feature="summarise", customer_id="acme"):
    client.chat.completions.create(...)

Tags apply to every tracked call made inside the with block, on whichever thread or asyncio task is inside it (tags use contextvars, so they follow async control flow correctly — a plain thread-local would not). Nested tags() blocks merge, innermost wins on key collision. These merge server-side with whatever default_tags your saive API key carries; the event's own tags win on collision there too.

Serverless

Call saive.flush() at the end of your handler, before the process might be frozen or killed:

def handler(event, context):
    ...
    saive.flush()

Streaming

Streaming is supported for all three providers. Usage typically only arrives in (or after) the final chunk, so if you stop consuming a stream early, saive will not have data to report for that call.

OpenAI specifically: the API only includes usage in a streamed response if you pass stream_options={"include_usage": True} to create(). saive does not add this for you (saive does not modify your outgoing requests, ever) — without it, saive has no token counts to report for that streamed call and will silently skip it.

Supported call surfaces (v1)

  • OpenAI: client.chat.completions.create() (sync, async, streaming). The newer client.responses.create() API is not yet instrumented.
  • Anthropic: client.messages.create() (sync, async, streaming). The client.messages.stream() context-manager helper is a separate code path and is not yet instrumented — use create(stream=True) if you want saive to see it.
  • Google GenAI: client.models.generate_content() and generate_content_stream(), sync and async (client.aio.models...).

What gets sent

For every tracked call, exactly this shape is POSTed (batched) to saive:

{
  "request_id": "generated-uuid4",
  "provider": "openai",
  "model": "gpt-4o-mini",
  "input_tokens": 123,
  "output_tokens": 45,
  "reasoning_tokens": 12,
  "max_tokens": 500,
  "timestamp": "2026-01-01T00:00:00+00:00",
  "latency_ms": 842.3,
  "tags": {"env": "prod"}
}

max_tokens is the ceiling your code passed to the SDK call (max_tokens for OpenAI/Anthropic, max_completion_tokens taking priority over max_tokens for OpenAI, config.max_output_tokens for Google GenAI) — not a usage figure. It powers one of the reduction insights (calls that request far more headroom than they use).

reasoning_tokens, max_tokens, latency_ms and tags are omitted entirely when not applicable rather than sent as null/{}.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

saive_client-0.1.0.tar.gz (13.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

saive_client-0.1.0-py3-none-any.whl (15.4 kB view details)

Uploaded Python 3

File details

Details for the file saive_client-0.1.0.tar.gz.

File metadata

  • Download URL: saive_client-0.1.0.tar.gz
  • Upload date:
  • Size: 13.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for saive_client-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9ff7bfe92f5af8ce3d8068e44a7c8cbdd4aebe05091971556f1f60db1bfbbbbd
MD5 56e63195612d288e9b68f982e97b3b51
BLAKE2b-256 d828713e6aab0d2a374baa4c6a9876843e4177ef8203d2a701f545fcd4e698e9

See more details on using hashes here.

File details

Details for the file saive_client-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: saive_client-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 15.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.3

File hashes

Hashes for saive_client-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b4e972fcccd4f8a3251634c6d5a67fe11de287357b6bb63449801c39bf272a5f
MD5 e56d83088b830b37eefc44743e593b6b
BLAKE2b-256 9955a865e822c6bafc1ee61ecd9f8d651cdcea00d6823541ef93288cbed21012

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page