Skip to main content

OpenToken Python SDK

Project description

Open Token Python SDK

Using UsageReporter directly

If you want to report usage from any provider, use UsageReporter directly:

from opentoken import UsageReporter

reporter = UsageReporter(
    open_token_api_key=os.environ["OPENTOKEN_API_KEY"],
    tags={"service": "checkout-api", "env": "prod"},
    batch=True,   # default; set False to POST one event at a time
)

response = your_provider_client.chat.completions.create(...)
reporter.report_usage(response=response, latency_ms=..., tags={"workflow_id": "..."})

report_usage(...) enqueues the report on a bounded in-memory queue and returns immediately (~microseconds on the caller's thread). A background daemon thread drains the queue and POSTs to /v1/usage:batch. You don't manage the thread — it's started lazily on your first call and dies with the process.

OpenAI Agents SDK integration

If you're using the OpenAI Agents SDK, register the tracing bridge once at startup and every Runner.run(...) will forward its LLM spans to OpenToken. You never call report_usage yourself.

from opentoken import UsageReporter, with_tags
from opentoken.integrations.agents import register_trace
from agents import Agent, Runner

# One-time setup — static tags apply to every event this reporter sends.
reporter = UsageReporter(open_token_api_key=..., tags={"env": "prod"})
register_trace(reporter)

sales_agent = Agent(name="sales_agent", model="gpt-5.5", instructions="...")

# Per-request handler — dynamic tags scoped to this one call.
async def handle(customer_id, question):
    with with_tags(customer_id=customer_id, agent_name="sales"):
        return await Runner.run(sales_agent, question)

Every event that flows out of that Runner.run lands with the merged tag set — reporter defaults + whatever's active in the surrounding with_tags block.

with_tags(**tags) — dynamic per-request tags

with_tags is the customer-facing knob for tags that vary per request: customer_id, session_id, workflow, whatever you want. It's a context manager backed by contextvars, so:

  • Async-safe. Concurrent tasks each maintain their own tag scope — no cross-request bleed.
  • Nested. Inner blocks inherit outer tags and override on collisions.
  • Works with both flows. Whether the event is emitted by the Agents integration or by a manual reporter.report_usage(...) call, the same ambient stack is read.

Tag precedence (highest wins)

For any event, tags merge in this order:

  1. UsageReporter(tags=...) — reporter defaults, static, process-wide
  2. with_tags(...) — ambient, request-scoped
  3. report_usage(tags=...) — per-call, most specific

Later layers override earlier ones on key collisions.

What lands in transactions.tags

Given the example above, one event would look like:

{
  "env":         "prod",           // reporter default
  "customer_id": "cus_123",        // from with_tags
  "agent_name":  "sales"           // from with_tags
}

No auto-injected tags. What you write is what lands.

Failure modes

  • HTTP failure (5xx, timeout, network blip). The batch is retried up to 3 times with exponential backoff + jitter, then dropped and logged. The worker keeps running.
  • Unexpected exception in the worker. The worker's main loop catches any exception, logs it, and continues. If the thread does die despite that, the next report_usage() call starts a fresh one; only the event in-flight at the time of the crash is lost — queued events are preserved.
  • Process death (SIGKILL, crash, sudden exit). The in-memory queue is lost. Long-lived servers are fine; short scripts should call reporter.flush() before exit, or rely on the built-in atexit flush (bounded to 5 seconds so slow OpenToken never hangs your process).

Enable logging.getLogger("opentoken") to see retries, drops, and worker restarts. Call reporter.stats() any time to inspect sent, dropped, retried, batches_flushed, worker_restarts, queue_depth.

Response shape

Both /v1/usage and /v1/usage:batch return the same positional bool array — one element per input event:

{"results": [true, false, true]}

Each true means the event was accepted; each false means it failed (unknown model, missing usage block, etc.). The SDK counts true events toward sent and retries false events up to max_retries times, then counts still-failing events toward dropped.

HTTP status is 200 for any well-formed request — individual event failures are surfaced inside results, not at the HTTP layer. The endpoints return 4xx only for whole-request problems (auth, malformed JSON, oversized batch).

Project details


Download files

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

Source Distribution

opentoken_sdk-0.1.0.tar.gz (14.3 kB view details)

Uploaded Source

Built Distribution

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

opentoken_sdk-0.1.0-py3-none-any.whl (13.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: opentoken_sdk-0.1.0.tar.gz
  • Upload date:
  • Size: 14.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for opentoken_sdk-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7b1c3edb370a400f13d57e0a1223c593d201c4084ed0f7e9d8bee035429442ae
MD5 42922a9298dfd1913f660d7f4d44d233
BLAKE2b-256 a124d27c0bbb112cc3955243ca666c16c855ad7eb62b79e0c9ad63a8db70364f

See more details on using hashes here.

File details

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

File metadata

  • Download URL: opentoken_sdk-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.2

File hashes

Hashes for opentoken_sdk-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 058f5b1b12cf9ffbe5ea56e9682b24a1310acee0678009b3d034ace089839c71
MD5 374dbc6ca7521043f7f1bb6f38b2ba33
BLAKE2b-256 c00ab128df6b6a836c95c40138d786b3a20274a09af2c39ea65a5413d0459d57

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