Media-generation observability SDK — capture the assets your app generates as events
Project description
keeps — media-generation observability SDK (v0.3.0)
User-facing docs live in docs/ (Mintlify site: quickstart, core concepts, providers, reliability, privacy, API + HTTP reference); their design rationale is in ../spec/DOCS-RATIONALE.md. This README is the engineering-facing summary.
Standalone and provider-agnostic — the SDK never wraps or patches
fal_client / replicate / openai. You call capture() around your own
provider code; the only thing carried across processes is the client-owned
asset_id. The wire contract it emits is MVP-SPEC §3
(../spec/MVP-SPEC.md) — envelope changes go there
first (invariant 8).
import keeps
keeps.init(api_key="kp_live_…") # or KEEPS_API_KEY / KEEPS_INGEST_URL env vars
# First call mints and returns a uuid7 asset_id; reuse it to append events.
asset_id = keeps.capture(
model="fal-ai/flux-pro/v1.1", # bare provider-native id
provider="fal", # dimension for pricing — never a join key
status="submitted",
inputs={"prompt": "an elephant"},
)
# … your real provider call runs, untouched …
keeps.capture(
asset_id,
status="completed",
outputs=[{"url": url}], # references, never bytes
usage={"n": 1, "duration_s": 6.2}, # provider billing meters, verbatim
properties={"generation_id": request_id, "tier": "pro"},
)
Full surface: init, capture, context (ambient tags), session
(tags + flush-on-exit), flush, shutdown, stats.
Design guarantees
- Fail-open, always. The SDK cannot raise into your code, cannot block beyond an in-memory append, and drops its own events under overflow or outage. Killing the ingest endpoint does not touch your pipeline — there are tests proving this.
- Stateless. No files, no local DB. One bounded in-memory buffer and a daemon flusher thread (fork-aware for prefork servers).
- References, not bytes. Events carry output URLs + metadata. Media
never leaves your infrastructure through this SDK;
bytesvalues are reduced to a length stub. - Verbatim capture.
inputsare recorded as-is for maximum fidelity — the SDK does not redact. Redact any sensitive field yourself beforecapture(). - Truncation is byte-based and flagged out of band (envelope
truncatedarray). Over-budgetinputscollapse to a hashed stub;propertiestrim values (never a stub key);outputskeep the first refs plus a{"__dropped__": n}marker. - Stdlib-only runtime. Zero dependencies.
Transport
Batches (≤200 events) POST to /v1/events with a top-level sent_at (lets
ingest cancel client clock skew), gzipped ≥1 KiB. Retries: 3× jittered
backoff; 429 Retry-After honored; 413 bisects the batch so one oversized
event costs only itself; other 4xx drop with a one-time warning. The 202 body
({"accepted": n, "rejected": [...]}) is parsed into stats().
Configuration
init() arg |
env var | default |
|---|---|---|
api_key |
KEEPS_API_KEY |
— (unset ⇒ SDK disabled, warns) |
endpoint |
KEEPS_INGEST_URL |
unreachable .invalid placeholder |
disabled |
KEEPS_DISABLED |
False (1/true/yes disables — CI) |
user_id |
None (process default; override per call or via keeps.context()) |
|
flush_interval |
1.0s |
|
max_buffer |
10_000 events |
Observability of the observer
keeps.stats() → initialized, disabled, emitted, sent, batches,
retries, dropped_overflow, dropped_send, plus the server's own ledger
from each 202 body: accepted (stored) and rejected_by_server (per-event
rejects — terminal, logged once with reason codes).
Development
uv venv && uv pip install -e ".[dev]"
pytest # full suite, incl. fail-open + concurrency tests
ruff check . && ruff format --check .
The wire contract lives in ../spec/MVP-SPEC.md §3 — schema changes go there first. Judgment calls are logged in ../spec/DECISIONS.md.
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 keeps_sdk-0.3.0.tar.gz.
File metadata
- Download URL: keeps_sdk-0.3.0.tar.gz
- Upload date:
- Size: 57.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8623502b44c05371bd85bc769274046d9add47061b2c1c325c825e7c3ac14b3e
|
|
| MD5 |
9b97a88d713e450322cb4b83b11b2ca9
|
|
| BLAKE2b-256 |
0bc8b626c187383797c5e232fb80fa4b3447651a99d9c08c3fe53cd11bfde77c
|
File details
Details for the file keeps_sdk-0.3.0-py3-none-any.whl.
File metadata
- Download URL: keeps_sdk-0.3.0-py3-none-any.whl
- Upload date:
- Size: 16.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.0
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
55bfb0f014ceb75688566e57525ef1362e4c64e5ff7c956786ac3e2d04234d07
|
|
| MD5 |
8279d88dce0ac80db4d8358d364d2590
|
|
| BLAKE2b-256 |
9d810722287f89d7760f4040428e741432e417ab3c79d713dbce30bafcdec1a0
|