Skip to main content
Pricing AI features requires per-token billing. Historically that meant building middleware to extract usage from every provider, normalize it across response shapes, batch events to a billing system, and survive outages. That work isn’t your product. The Lago Agent SDK removes that layer. You wrap your existing LLM client and keep calling it the same way: same arguments, same return shape, same exceptions. The SDK extracts normalized token usage from each response and streams events to Lago in the background. It can also price calls for you. The SDK fetches live per-token prices, turns the priced token types on each call into a dollar cost, and lets you add a margin on top. Your LLM costs land in one place, and you decide what to resell them for. Available in two flavors, both open source and versioned together:
  • Python: lago-agent-sdk on PyPI. Python 3.10+.
  • JavaScript / TypeScript: lago-agent-sdk on npm. Authored in TypeScript, ships compiled JS with .d.ts.

Pick your provider

Each integration page carries the install command, the wrap call, streaming and async coverage, the per-call override syntax, and the exact fields captured for that provider.

OpenAI

Chat Completions and the Responses API. Reasoning tokens on o-series models.

Anthropic

messages.create and the streaming helper. Full prompt-caching breakdown.

AWS Bedrock

Converse and InvokeModel, streaming included. Seven InvokeModel shape families.

Google Gemini

google-genai unified SDK. Reasoning tokens on Gemini 2.5, plus audio and image.

Mistral

chat.complete and chat.stream, with cache-read tokens when the cache hits.

Cloudflare AI Gateway

Any provider behind your gateway. Cache hits skipped, Workers AI priced, logs backfilled.

Databricks AI Gateway

Hosted models and BYOK traffic. Live instrumentation, or backfill from Databricks’ own system tables.
Something missing? The wrapper layer is one file per provider in both repos. Open an issue or a PR on Python or JavaScript.

How it works

  • Wraps your existing LLM client in place. Your application code does not change.
  • Extracts usage from each response into a normalized shape (CanonicalUsage, 11 numeric fields).
  • Buffers events in memory and flushes them in batches to Lago’s /events/batch endpoint.
  • Survives provider and Lago outages with exponential backoff and a bounded buffer.
  • Never blocks your LLM call on Lago. Recording usage costs microseconds against a call that takes hundreds of milliseconds, and the request to Lago goes out on a background thread.
  • Never breaks your LLM call. Instrumentation errors are caught, logged, and optionally forwarded to your observability stack.

Quickstart

1

Install the SDK

Install the core package plus the provider SDK you already use. Python ships provider support as optional extras; in JavaScript you install the provider package yourself.
2

Initialize and wrap your LLM client

Pass your Lago API key and a default external_subscription_id, then wrap your provider client. The returned object is a drop-in replacement, and wrap() is idempotent: calling it twice on the same client is a no-op.
On the EU region or a self-hosted instance, set api_url / apiUrl. The default is https://api.getlago.com/api/v1.
3

Make LLM calls normally

The wrapped client preserves the original signature, return shape, and exceptions. No call-site changes required.
Streaming works the same way. The SDK wraps the iterator, reads usage from the terminal chunk, and emits one set of events per completed response. See your provider’s page for the exact streaming surface.
4

Flush events on shutdown

Events flush automatically: every second, or as soon as 100 events are buffered. Call flush() explicitly at process exit (FastAPI shutdown hook, Express server close, AWS Lambda extension) so in-flight events are not lost.
A clean interpreter exit already triggers a 2-second flush. Python registers an atexit hook, JavaScript a beforeExit handler. An explicit flush() is still the right call in a request-scoped or serverless runtime.
5

Wire up on_error

Instrumentation failures are silent by design — the SDK will never break your LLM call to tell you about one. That makes the error hook the only way to find out something is wrong, so set it on day one rather than later.
6

Register billable metrics in Lago

Before events count toward charges, register matching billable metrics in your Lago tenant. The SDK ships with default metric codes — Billing lists all eleven and shows the plan setup that prices them correctly.Follow Create a billable metric to create them, then attach charges in your plan. For a full worked example, see the per-token pricing template.

What the SDK does not cover

wrap() instruments the chat and completion surfaces, not everything a provider client can do. Embeddings, image and video generation, audio endpoints, batch APIs, and — on OpenAI and Anthropic — the parse() structured-output helpers all pass through unmetered. Each provider page has a “what is and isn’t instrumented” section with the exact list. For anything the wrappers miss, including providers with no wrapper at all, build a CanonicalUsage yourself and pass it to sdk.emit().

Where to go next

Billing

Token mode versus price mode, the metric codes to register, and the plan setup that prices each token type correctly.

Reference

Every configuration option, subscription routing, the error types, and how the SDK behaves under failure.

Verify the integration

Make one call through the wrapped client and call flush(). In the Lago dashboard, open Developers → Events and confirm an event arrives with the expected metric code and properties, then check that the customer’s usage counter moved. If nothing arrives, look at on_error first — instrumentation failures are silent by design. The usual causes are an unregistered metric code, no resolvable external_subscription_id, and an API key without write access.

Resources