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
Metadata
Release files for margined 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| margined-0.2.0.tar.gz | 15.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| margined-0.2.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.8 kB
Release files / margined-0.2.0.tar.gz
| Download URL | margined-0.2.0.tar.gz |
|---|---|
| Size | 15.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
24fef4653a3b04e7a1d11fd61bd3da84be04daa374362a1cbd5890578de3b9ac
|
|
BLAKE2b-256 checksum How to use checksums |
880db7aaf7c129b8e16167202735a43d3a1c0535a7c2f35cc0ac2c3ffa6e4fd2
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|
Release files / margined-0.2.0-py3-none-any.whl
| Download URL | margined-0.2.0-py3-none-any.whl |
|---|---|
| Size | 15.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
87776a21f5e00a2a2b4b88e1400ee256ed7731c82bdbb081c25f859024c6b39e
|
|
BLAKE2b-256 checksum How to use checksums |
14c07df1e1ca5b269c0ba0d0ab86d65e800193e46b1799d67e1483850ec75b1a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.6
|