Skip to main content

tokenops

Attribute LLM spend to your customers with one line.

TokenOps records what each LLM call cost and which of your customers it was for, so you can see cost-vs-revenue per customer. This is the Python client.

Install

pip install lovie-tokenops

Requires Python 3.9+. No runtime dependencies (uses the standard library).

Quick start — auto-instrument Anthropic

import os
from tokenops import TokenOps, wrap_anthropic
from anthropic import Anthropic

tokenops = TokenOps(
    company_id="<your-company-uuid>",
    secret_key=os.environ["TOKENOPS_SECRET_KEY"],  # sk_live_...
    ingest_url="https://api.lovie.co",
)

# One line. Every non-streaming call is now attributed.
anthropic = wrap_anthropic(Anthropic(), tokenops)

anthropic.messages.create(
    model="claude-sonnet-4-5",
    max_tokens=1024,
    messages=[{"role": "user", "content": "hi"}],
    customer_id="acme-inc",  # <- attributes the spend; stripped before the real call
)

wrap_anthropic tracks on a background worker: it never blocks or fails your LLM call. Pass on_error to observe background tracking failures. Both sync (Anthropic) and async (AsyncAnthropic) messages.create calls are instrumented; streaming calls (stream=True) and messages.stream() are passed through untracked. Wrapping the same client twice is a no-op — it never double-tracks.

Quick start — auto-instrument OpenAI

import os
from tokenops import TokenOps, wrap_openai
from openai import OpenAI

tokenops = TokenOps(
    company_id="<your-company-uuid>",
    secret_key=os.environ["TOKENOPS_SECRET_KEY"],  # sk_live_...
    ingest_url="https://api.lovie.co",
)

# One line. Every non-streaming call is now attributed.
openai = wrap_openai(OpenAI(), tokenops)

openai.chat.completions.create(
    model="gpt-4o",
    messages=[{"role": "user", "content": "hi"}],
    customer_id="acme-inc",  # <- attributes the spend; stripped before the real call
)

wrap_openai instruments chat.completions.create and, when present, responses.create (a no-op on older SDKs without it). It tracks on a background worker: it never blocks or fails your LLM call. Pass on_error to observe background tracking failures. Both sync (OpenAI) and async (AsyncOpenAI) calls are instrumented; streaming calls (stream=True) are passed through untracked. Wrapping the same client twice is a no-op — it never double-tracks.

Flushing before exit

Tracking runs on a background worker, so a short-lived script or serverless invocation can exit before in-flight events are sent. Events are drained automatically on normal interpreter exit, but for serverless or before a hard exit, flush explicitly:

tokenops.flush()  # block until queued events are sent
tokenops.close()  # flush, then stop the background worker

Track events directly

from tokenops import TokenOpsEvent

tokenops.track(TokenOpsEvent(
    vendor="openai",
    model="gpt-4o",
    input_tokens=1200,
    output_tokens=350,
    customer_id="acme-inc",
    provider_observation_id="resp_123",  # idempotent de-dup on re-send
))

tokenops.track_batch([event1, event2])  # batches of >500 are split automatically

provider_observation_id is optional: set it to the provider's response id to get idempotent de-duplication on re-send. When omitted it is auto-generated so the event is always accepted.

Failed sends retry with exponential backoff on network errors, 429, and 5xx; a 4xx (e.g. a bad key) raises TokenOpsError immediately.

License

MIT

Download files

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

Source Distribution

lovie_tokenops-0.1.0.tar.gz (9.3 kB view details)

Uploaded Source

Built Distribution

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

lovie_tokenops-0.1.0-py3-none-any.whl (8.4 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for lovie_tokenops-0.1.0.tar.gz
Algorithm Hash digest
SHA256 046c035189777a76b3683d44b3adbac93fbf412df8ac475c6e2c83ae76bf29f9
MD5 2a126c326b6968c9aad2f8c32c772c7d
BLAKE2b-256 40ae066fc2abc282e8991577608348a9b2fa815aad378f0cb0e7888febe8a9fd

See more details on using hashes here.

File details

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

File metadata

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

File hashes

Hashes for lovie_tokenops-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ad040d068f33ee178b66ebd2d82a9b60f2cbede47e54605c7d7a34b6d1ccc15a
MD5 686842a21dee146dd8426fc352ab4b03
BLAKE2b-256 ed2a61a1aa1a4a960e9c69103054002fd1803d1f40405d6d0cb86837772afe31

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