LLM unit economics: cost, margin, and profitability per customer and feature.
Project description
Margined Python SDK
LLM unit economics: cost, margin, and profitability per customer and feature.
Add one argument to your existing LLM calls. Get gross margin per customer, cost per feature, and the price you need to charge — without changing how your app works.
pip install margined
Quickstart
import margined
margined.init() # reads MARGINED_API_KEY
response = margined.track(
client.messages.create(
model="claude-sonnet-4-6",
max_tokens=1024,
messages=[{"role": "user", "content": prompt}],
),
user_id=current_user.id,
feature="summarize_document",
)
track() returns the exact same response object, unchanged. Zero risk to existing code.
Auto-patch (zero call-site changes)
import margined
margined.init()
margined.patch_anthropic() # sync + async clients
margined.patch_openai() # sync + async clients
# Tell Margined who the current user is (e.g. Flask):
margined.set_context(
user_id=lambda: g.current_user.id,
feature=lambda: request.endpoint,
)
Every LLM call in your app — including calls made by third-party libraries — is now tracked.
Decorator + scoped identity
@margined.feature("research_agent")
async def run_research(user, query):
async with margined.identify(user.id):
return await client.messages.create(...)
Streaming
Streams report usage only at the end; wrap them and Margined records one event when the stream completes:
stream = margined.track_stream(
client.messages.create(..., stream=True),
user_id=user.id, feature="chat",
)
for event in stream:
...
For OpenAI, pass stream_options={"include_usage": True} so the final chunk carries usage. Auto-patched clients wrap streams automatically.
Agent runs
Group multi-step agent workflows under one run — the dashboard shows cost per run (p50/p90/p99), not just cost per call:
with margined.run(user_id=user.id, feature="research_agent") as r:
step1 = client.messages.create(...) # auto-tracked
step2 = client.messages.create(...)
r.tag({"steps": 2})
Guarantees
The SDK is built to the same standard as Sentry/PostHog-class telemetry SDKs:
- Fail-open. Tracking never raises into your application and never blocks a request thread. If Margined is down, your app is unaffected.
- Background delivery. Events batch in memory and flush every 5 seconds (or at 100 events) on a daemon thread, with retry + exponential backoff on transient failures.
- Bounded memory. The queue caps at 10,000 events and drops the oldest under sustained backpressure (drops are counted and reported).
- No double counting. Every event carries an idempotency key; a retried flush can never inflate your costs.
- Cache-aware pricing. Prompt-cache reads and writes are priced at each provider's actual discount rates, and OpenAI cached tokens are separated from the uncached input count.
- Local cost computation. Cost is computed from a bundled, versioned price table (
margined.PRICES_VERSION) — no network round-trip on the hot path. The ingest API independently recomputes cost server-side, so a stale client table can't skew your dashboard.
Providers
Anthropic, OpenAI, Google Gemini, Groq, Mistral, DeepSeek, Together AI — with prefix matching for dated model snapshots and provider-prefixed IDs (anthropic.claude-…, openai/gpt-…).
Configuration
margined.init(
api_key="mgd_...", # or MARGINED_API_KEY
endpoint="https://...", # or MARGINED_ENDPOINT (self-hosting)
sample_rate=1.0, # record a fraction of events
disabled=False, # or MARGINED_DISABLED=1 (tests/CI)
debug=False, # or MARGINED_DEBUG=1
)
Serverless / short-lived processes
Call margined.flush() before the function exits (or margined.shutdown() to also stop the worker). The SDK also registers an atexit hook that drains the queue with a single best-effort attempt.
Dashboard
Events appear in your Margined dashboard in real time:
- Gross margin per customer — connect Stripe to see revenue vs. cost
- Cost per feature — which product surface burns your bill
- Pricing calculator — break-even and recommended prices from your real p50/p90/p99 usage
- Margin-at-risk alerts — email/Slack before a customer goes underwater
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file margined-0.2.0.tar.gz.
File metadata
- Download URL: margined-0.2.0.tar.gz
- Upload date:
- Size: 15.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
24fef4653a3b04e7a1d11fd61bd3da84be04daa374362a1cbd5890578de3b9ac
|
|
| MD5 |
8c3d498bc1f39f6ffd06f27830d96ecf
|
|
| BLAKE2b-256 |
880db7aaf7c129b8e16167202735a43d3a1c0535a7c2f35cc0ac2c3ffa6e4fd2
|
File details
Details for the file margined-0.2.0-py3-none-any.whl.
File metadata
- Download URL: margined-0.2.0-py3-none-any.whl
- Upload date:
- Size: 15.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/7.0.0 CPython/3.14.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
87776a21f5e00a2a2b4b88e1400ee256ed7731c82bdbb081c25f859024c6b39e
|
|
| MD5 |
1b753ea3c8edd7229b99da270a15602f
|
|
| BLAKE2b-256 |
14c07df1e1ca5b269c0ba0d0ab86d65e800193e46b1799d67e1483850ec75b1a
|