Decision Records for production AI.
Project description
Lumyn
Decision Records for production AI.
Lumyn is a deterministic decide() gateway for AI agents. It enforces strict policies, returns explicit verdicts (ALLOW, DENY, ESCALATE, ABSTAIN), and writes durable Decision Records for instant incident replay.
[!NOTE] v1.0.0 Stable: This documentation covers the v1 engine. For legacy v0 documentation, see Legacy Specs.
When an AI incident happens
Support shares a screenshot. Engineering tries to reconstruct what the model saw and what policy/risk rules fired. Nobody can answer, precisely and repeatably: what happened, what changed, and why did we allow it?
Lumyn's unit of evidence is a decision_id. Paste it into the ticket, then:
lumyn show <decision_id>lumyn explain <decision_id> --markdownlumyn export <decision_id> --pack --out decision_pack.ziplumyn replay decision_pack.zip --markdown
Why teams adopt Lumyn
- Write-path safety: gates consequential actions with explicit policy and outcomes.
- Replayable decisions: stable digests (
policy.policy_hash,request.context.digest,determinism.inputs_digest). - No bluffing: uncertainty becomes
ABSTAINorESCALATEwith reason codes. - Compounding reliability: labeled failures/successes feed Experience Memory similarity.
- Drop-in: works as a Python library and as an optional HTTP service.
Operations & Safety
📺 The War Room (lumyn monitor)
"Less drama. Fewer incidents." A live, scrolling Matrix-style TUI showing decisions as they happen.
lumyn monitor --limit 50
🛡️ Regression Testing (lumyn diff)
"Did my change block valid users?" Run a candidate policy against a history of past records to catch regressions before deployment.
lumyn diff past_traffic.json --policy new_policy.v1.yml
The primitive
You wrap a risky action with decide():
- you provide a
DecisionRequest(subject, action, evidence,schema_version: decision_request.v1) - Lumyn evaluates deterministic
policy.v1(strict stages + conditions) - Lumyn returns a
DecisionRecordand persists it (append-only)
The Decision Record is the unit you export into incidents, tickets, and postmortems.
How it works (one screen)
- You provide a
DecisionRequest(no external fetches in v1; your app suppliesevidence). - Lumyn evaluations occur in 5 strict stages:
REQUIREMENTS->HARD_BLOCKS->ESCALATIONS->ALLOW_PATHS->DEFAULT. - Lumyn computes Experience Memory similarity from prior labeled outcomes.
- Lumyn persists the Decision Record to SQLite before returning (or returns ABSTAIN on storage failure).
What a Decision Record looks like
{
"schema_version": "decision_record.v1",
"decision_id": "01JZ1S7Y1NQ2A0D5JQK2Q2P3X4",
"created_at": "2025-12-15T10:00:00Z",
"request": {
"schema_version": "decision_request.v1",
"subject": { "type": "service", "id": "support-agent", "tenant_id": "acme" },
"action": {
"type": "support.refund",
"intent": "Refund duplicate charge for order 82731",
"amount": { "value": 201.0, "currency": "USD" }
},
"evidence": { "ticket_id": "ZD-1001", "order_id": "82731", "payment_instrument_risk": "low" },
"context": { "mode": "digest_only", "digest": "sha256:aaaaaaaa..." }
},
"policy": {
"policy_id": "lumyn-support",
"policy_version": "1.0.0",
"policy_hash": "sha256:bbbbbb...",
"mode": "enforce"
},
"verdict": "ESCALATE",
"reason_codes": ["REFUND_OVER_ESCALATION_LIMIT"],
"matched_rules": [
{ "rule_id": "R008", "stage": "ESCALATIONS", "effect": "ESCALATE", "reason_codes": ["REFUND_OVER_ESCALATION_LIMIT"] }
],
"risk_signals": {
"uncertainty_score": 0.12,
"failure_similarity": { "score": 0.07, "top_k": [] }
},
"determinism": {
"engine_version": "1.0.0",
"inputs_digest": "sha256:cccc..."
}
}
Quickstart (no keys, no Docker)
Install:
pip install lumyn- Service mode:
pip install lumyn[service]
Fastest "aha" (compounding in seconds):
lumyn doctor --fixlumyn demo --story
Common CLI workflows:
lumyn init(creates local SQLite + starterpolicy.v1)lumyn demo(emits a few real-looking Decision Records as JSON)lumyn demo --story(auto-label a failure and show compounding)lumyn decide req.json(prints a Decision Record)lumyn show <decision_id>,lumyn explain <decision_id>lumyn export <decision_id> --pack --out decision_pack.ziplumyn replay decision_pack.zip(validate pack + digests)lumyn policy validate(strict v1 validation)lumyn migrate old_policy.v0.yml(upgrade to v1)
SDK (drop-in)
Lumyn does not call your model. You call Lumyn before (or around) a real write-path action.
from lumyn import LumynConfig, decide_v1
cfg = LumynConfig(store_path=".lumyn/lumyn.db") # loads policies/starter.v1.yml
record = decide_v1(
{
"schema_version": "decision_request.v1",
"request_id": "req_123", # recommended for retries
"subject": {"type": "service", "id": "support-agent", "tenant_id": "acme"},
"action": {
"type": "support.refund",
"intent": "Refund duplicate charge",
"amount": {"value": 20.0, "currency": "USD"},
},
"evidence": {
"ticket_id": "ZD-1001",
"payment_instrument_risk": "low",
},
"context": {"mode": "digest_only", "digest": "sha256:..."}
},
config=cfg,
)
if record["verdict"] == "ALLOW":
pass # perform the write-path action
elif record["verdict"] == "ESCALATE":
pass # route to human queue
else:
pass # block (ABSTAIN/DENY)
Service mode (FastAPI)
Run:
lumyn serve
Call:
curl -sS -X POST http://127.0.0.1:8000/v1/decide -H 'content-type: application/json' --data-binary @request.json
Endpoints:
POST /v1/decide-> DecisionRecord (v1)GET /v1/decisions/{decision_id}GET /v1/policy
Documentation
- Feature Overview & Quickstart
- v1 Semantics Reference
- Architecture
- Specs & Schemas
- Integration Checklist
- Migration Guide
Design principles
- Decision as an artifact: every gate yields a record.
- Policy + outcomes, not prompts: rules tie to action classes and objective outcomes.
- Telemetry ≠ truth: OpenTelemetry is for visibility; the Decision Record is the system of record.
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 lumyn-1.0.0.tar.gz.
File metadata
- Download URL: lumyn-1.0.0.tar.gz
- Upload date:
- Size: 154.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2c849e6aeb4c80ea7abfd8aeb4c8a297e1a530742663da11c058133cf734d2f7
|
|
| MD5 |
d3457bd9d9b6e984fb5c9363a2a778d5
|
|
| BLAKE2b-256 |
52d1aef3829cf58672974766787a9e4ab1ca6354f3f11b08a41d39bf41e62708
|
Provenance
The following attestation bundles were made for lumyn-1.0.0.tar.gz:
Publisher:
release.yml on davidahmann/lumyn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lumyn-1.0.0.tar.gz -
Subject digest:
2c849e6aeb4c80ea7abfd8aeb4c8a297e1a530742663da11c058133cf734d2f7 - Sigstore transparency entry: 766087165
- Sigstore integration time:
-
Permalink:
davidahmann/lumyn@3df5568becc49b46811181bf7e55d795e489ae67 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/davidahmann
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3df5568becc49b46811181bf7e55d795e489ae67 -
Trigger Event:
push
-
Statement type:
File details
Details for the file lumyn-1.0.0-py3-none-any.whl.
File metadata
- Download URL: lumyn-1.0.0-py3-none-any.whl
- Upload date:
- Size: 79.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
53b3abe2a1aa77271919f70fd716d4a497a24ecf47b705539888968c6a329233
|
|
| MD5 |
0c8fb2c88da94650c389ccf3822d18e2
|
|
| BLAKE2b-256 |
5d6b3a3439ae12e5f92c4956e927748aee8f4edc2d847f27f0aa06c090e012d7
|
Provenance
The following attestation bundles were made for lumyn-1.0.0-py3-none-any.whl:
Publisher:
release.yml on davidahmann/lumyn
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
lumyn-1.0.0-py3-none-any.whl -
Subject digest:
53b3abe2a1aa77271919f70fd716d4a497a24ecf47b705539888968c6a329233 - Sigstore transparency entry: 766087171
- Sigstore integration time:
-
Permalink:
davidahmann/lumyn@3df5568becc49b46811181bf7e55d795e489ae67 -
Branch / Tag:
refs/tags/v1.0.0 - Owner: https://github.com/davidahmann
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@3df5568becc49b46811181bf7e55d795e489ae67 -
Trigger Event:
push
-
Statement type: