Clue Backend SDK (Python) — OTel-based observation-source event capture for Django, FastAPI, Celery, SQLAlchemy, LangChain, LlamaIndex, CrewAI, MCP, and AI providers.
Project description
clue-backend-sdk
Shared Python backend core for Clue SDK wrappers (Django, FastAPI,
Celery). Events flow through an OTel TracerProvider + BatchSpanProcessor +
ObservationSourceEventExporter to
/api/v1/ingest/backend.
Minimal integration
The SDK exposes a single clue namespace with eight methods (init /
identify / group / reset / track / set_consent /
flush / close). This mirrors the cross-SDK contract documented in
docs/contracts/sdk/public-api.md §1.6.
import asyncio
from clue_backend_sdk import clue
clue.init({
"endpoint": "https://ingest.example.com/api/v1/ingest/backend",
"project_key": "...",
"api_key": "...",
"service_key": "backend-api",
})
clue.identify("user_42", {"name": "Alice", "email": "alice@example.com"})
clue.group("organization", "org_7", {"name": "Acme Inc"})
clue.track("order_placed", {"product_name": "shirt", "amount": 100})
clue.set_consent("granted")
# Shutdown idiom — both are coroutines for cross-SDK parity.
asyncio.run(clue.flush())
asyncio.run(clue.close())
Do not pass environment or service_name in the MVP setup path.
Clue derives dev/prod from the project key prefix, and service_key is the
single literal customer-facing backend service label.
clue.track custom event names must match
^[A-Za-z0-9_.:-]{1,128}$. Invalid names are ignored and do not emit
a source-signal custom track intent. clue.set_consent only records local
SDK state in the MVP backend SDK; it does not emit consent transition events.
Framework wrappers and runtime helpers are imported from their owning modules. The package root is intentionally small: customer-facing lifecycle methods plus stable setup helpers. Direct event builders are not public extension points.
Architecture boundary
The Python SDK is a thin language wrapper around OpenTelemetry and the Clue
transport. Framework integrations create spans or annotate the current span,
the exporter serializes those spans as sdk_source_signal_observed events,
and the Clue backend ingest core performs classification, normalization,
privacy projection, and raw-ingest shaping.
Python framework / library hook
-> OTel span or Clue source-signal attributes
-> ObservationSourceEventExporter
-> /api/v1/ingest/backend
-> apps/api/src/modules/ingest core
Rules:
- Keep framework code limited to raw facts, correlation context, and standard OTel attributes.
- Do not add Python-only classification, direct event builders, or custom fallback behavior.
- Add classifier behavior in the backend ingest core so Node.js, Python, and future SDK wrappers receive the same behavior.
- Preserve
interaction_id,request_span_id,request_id, andtrace_idwhenever they are available. User-action linkage is an ingest contract, not a display-only field.
Privacy and PII handling
1. Hard-deny: PII / secrets are stripped before transport
The SDK strips a built-in set of property keys before the event
leaves the customer process. Caller-supplied denied_keys are added
on top of DEFAULT_DENIED_KEYS — they cannot remove a default-denied
key.
Hard-deny categories (case- and separator-insensitive — userEmail,
user-email, USER_EMAIL, email_address all match):
- Auth credentials:
authorization,cookie,set-cookie,password,passwd,secret,token,access_token,refresh_token,session,session_token,api_key,apikey,private_key - PII categories:
email,phone,credit_card,ssn
This list is a strict superset of the server-side ingest hard-deny
(@clue/shared INGEST_HARD_DENY_KEYS), enforced by the
tests/test_privacy_parity.py cross-SDK parity test.
2. HTTP body capture (Django / FastAPI wrappers)
For framework wrappers that capture HTTP request bodies via
parameter_snapshot.py, the same hard-deny applies: body.email
cannot be unmasked via allowed_value_paths because email is in
DEFAULT_DENIED_KEYS. Use a non-PII path (e.g. body.product_name)
for explicit plaintext capture.
3. Default-masked: configure server allowlist for analysis projection
Properties that pass the hard-deny gate are still masked by default
on the server side. To make a property appear in Clue's analysis UI,
the property key must be listed on the resolved project service's
observationAnalysisPropertyAllowlist. Without this, the property
lands in raw_only_keys (visible in raw observation storage only) and not in
analysisProperties.projected.
4. Identity traits stay privacy-safe
clue.identify(user_id, traits={...}) accepts profile traits such as
name, email, avatarUrl, role, and plan. Use a stable opaque
user_id; the SDK converts email into privacy-safe contact-derived
fields before canonical identity events leave the process.
Build / test
python3 -m venv .venv
source .venv/bin/activate
pip install -e '.[test]'
python -m pytest
Live-verify (opt-in, requires apps/api + apps/worker running):
CLUE_LIVE_VERIFY=1 \
CLUE_LIVE_PROJECT_KEY=pk_dev_xxx \
CLUE_LIVE_API_KEY=cluesk_dev_xxx \
python -m pytest tests/test_canonical_endpoint_live.py -v
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
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 clue_backend_sdk-1.0.0.tar.gz.
File metadata
- Download URL: clue_backend_sdk-1.0.0.tar.gz
- Upload date:
- Size: 175.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
80ab1b6ddada1ff279b73be99280ff31cd7b57552cb21d6331f767903e513ccc
|
|
| MD5 |
dbada03812b29cee5d4e10b130a2b9f7
|
|
| BLAKE2b-256 |
81b71cfcfa185df8556080e9f3489818f32b82e323b55dadfb88f0bf2b6c94d2
|
File details
Details for the file clue_backend_sdk-1.0.0-py3-none-any.whl.
File metadata
- Download URL: clue_backend_sdk-1.0.0-py3-none-any.whl
- Upload date:
- Size: 163.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.9.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
747c847b9970feaf1a1e590ea0995094a100db5166f75aa48f26fe0eace93aca
|
|
| MD5 |
40876166ec6ff1823311719d7ff9694d
|
|
| BLAKE2b-256 |
43d89ea71e2ac8d86e4bd8d4fef1baca64c729ce106dd559daec5873617d7c04
|