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.3.tar.gz (15.0 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.3-py3-none-any.whl (16.3 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: saive_client-0.1.3.tar.gz
  • Upload date:
  • Size: 15.0 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.3.tar.gz
Algorithm Hash digest
SHA256 630f514ca9cac96bf8620c61f980fe5a4ecc56c89f31c59af961d26ebfc48c79
MD5 bea0a8f550fa4b3d5f2470c3c99d00d0
BLAKE2b-256 9981c17c4f4d5c163770c21b0991835e44947ad02a07ec6f817336192c7efc3f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: saive_client-0.1.3-py3-none-any.whl
  • Upload date:
  • Size: 16.3 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.3-py3-none-any.whl
Algorithm Hash digest
SHA256 46398cb0f525cf63ad2c6cfa5756fddcf433348deb40b6c1eb6bbfaf45145c43
MD5 9a6133387fe4949c036dbfd23b17de39
BLAKE2b-256 e54dc3a9b40312e463b62dd697493fde6760121216d23f44fac4167fa02741d7

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 Sentry Error logging StatusPage Status page