Context infrastructure for AI applications
Project description
Fabra
Context Records for LLM incidents.
Capture what the model saw as a durable artifact you can replay, verify, and diff.
record -> replay -> diff
When An LLM Incident Happens
- Support shares a screenshot.
- Engineering tries to reconstruct prompts, retrieval, features, and runtime state.
- Nobody can answer, precisely and repeatably: what did it see, what changed, why did it answer that way?
Fabra's unit of evidence is a context_id (UUID or ctx_<UUID>). Paste it into the ticket, then:
fabra context show <context_id>
fabra context verify <context_id>
fabra context diff <context_id_A> <context_id_B>
Quickstart (No Keys, No Docker)
pip install fabra-ai
fabra demo
fabra demo starts a local server, makes a test request, and prints a working context_id plus the next commands to run.
By default, Context Records are stored durably in DuckDB at ~/.fabra/fabra.duckdb (override with FABRA_DUCKDB_PATH).
How It Works (One Screen)
- You define features and
@contextfunctions in a Python file. fabra serve <file.py>loads that file, starts a FastAPI server, and serves:GET /v1/features/<name>for feature values (withfreshness_ms)POST /v1/context/<name>for assembled context + acontext_id
- Fabra persists a CRS-001 Context Record (receipt) and exposes it at
GET /v1/record/<context_id>. - Under incident pressure you run
fabra context show/verify/difffrom thecontext_id.
Details: docs/how-it-works.md
Requirements
- Python
>= 3.9 pip(oruv, optional)curl(used in quickstart verification commands)- Optional:
- Node.js (only for
fabra ui) - Docker (only for Docker-based examples / local production stack)
- Node.js (only for
Help and diagnostics:
fabra --help
fabra context --help
fabra doctor
Production defaults (no fake receipts)
In FABRA_ENV=production, Fabra defaults to FABRA_EVIDENCE_MODE=required: if CRS-001 record persistence fails, the request fails (no context_id returned).
Already using LangChain or calling OpenAI directly? Add receipts without changing your app architecture:
docs/exporters-and-adapters.md(LangChain-style callbacks, OpenAI wrapper, logs/OTEL)
Events/workers (optional): docs/events-and-workers.md
What A Context Record Is
A Context Record is a durable artifact for an AI request: assembled content plus lineage (features, retrieval, freshness decisions), and optional integrity metadata.
Create a context_id locally using the shipped example:
fabra serve examples/demo_context.py
In another terminal:
curl -fsS -X POST http://127.0.0.1:8000/v1/context/chat_context \
-H "Content-Type: application/json" \
-d '{"user_id":"u1","query":"test"}'
Core workflow (from a context_id):
fabra context show <context_id>
fabra context verify <context_id>
fabra context diff <context_id_A> <context_id_B>
fabra context export <context_id> --bundle -o incident_bundle.zip
incident_bundle.zip includes the exported record (<context_id>.json) plus manifest.json with stored vs computed hashes.
Drop-In Receipts (No Keys)
If you already build prompts but don’t use @context yet, emit a verifiable receipt:
from fabra.receipts import ReceiptRecorder
from fabra.exporters.logging import emit_context_id_json
prompt = "system: ...\nuser: ..."
recorder = ReceiptRecorder()
receipt = recorder.record_sync(
context_function="my_llm_call",
content=prompt,
inputs={"model": "gpt-4.1-mini"},
)
emit_context_id_json(receipt.context_id, source="my-service", ticket="INC-1234")
Two Entry Points
ML Engineers (Features)Define features in Python and serve them over HTTP. from fabra import FeatureStore, entity, feature
from datetime import timedelta
store = FeatureStore()
@entity(store)
class User:
user_id: str
@feature(entity=User, refresh=timedelta(hours=1))
def purchase_count(user_id: str) -> int:
# Replace with a real DB call
return 47
fabra serve features.py # or: fabra serve examples/demo_features.py
curl localhost:8000/v1/features/purchase_count?entity_id=u123
# {"value": 47, "freshness_ms": 0, "served_from": "online"}
|
AI Engineers (Context)Assemble prompts with features + retrieval, with lineage and budgets. from fabra import FeatureStore
from fabra.context import context, ContextItem
store = FeatureStore()
@context(store, max_tokens=4000, freshness_sla="5m")
async def build_prompt(user_id: str, query: str) -> list[ContextItem]:
# Replace with your feature calls and retriever / RAG call
tier = "premium"
docs = "..."
return [
ContextItem(content=f"User tier: {tier}", priority=1),
ContextItem(content=docs, priority=2),
]
ctx = await build_prompt("user_123", "question")
print(ctx.id)
print(ctx.lineage)
|
CLI (Most Used)
fabra demo # start demo + print a context_id
fabra context show <id> # inspect a record (or best-effort legacy view)
fabra context verify <id> # verify CRS-001 hashes (fails if unavailable)
fabra context diff <a> <b> # compare two contexts
fabra context diff <a> <b> --local # diff two CRS-001 receipts from DuckDB (no server required)
fabra context pack <id> -o incident.zip # zip: context.json + summary.md
fabra context pack <id> --baseline <id0> -o incident.zip # adds diff.patch (content unified diff)
fabra context export <id> # export json/yaml
fabra context export <id> --bundle # zip bundle for incident/audit
fabra doctor # local diagnostics
fabra serve <file.py> # run server for examples/your code
fabra deploy fly|cloudrun|ecs # generate deployment config
fabra ui <file.py> # local UI (requires Node.js)
Note: fabra ui requires Node.js. If you’re running from source, install UI deps with cd src/fabra/ui-next && npm install.
What Fabra Is / Isn’t
Fabra is Python-first infrastructure for inference-time evidence (Context Records) and for serving features and context over HTTP. Define features and context in code (not YAML), run locally with DuckDB, and scale to Postgres/Redis in production. No Kubernetes or Kafka is required to adopt Fabra.
Fabra is not:
- an agent framework
- a monitoring dashboard
- a no-code builder
See docs/quickstart.md, docs/context-record-spec.md, and docs/comparisons.md for details.
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 fabra_ai-2.2.8.tar.gz.
File metadata
- Download URL: fabra_ai-2.2.8.tar.gz
- Upload date:
- Size: 912.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1b35ed1dc3077ad208a36b5a44c8b7e0df31bc94be571c0d24d94e763599bc84
|
|
| MD5 |
d913182afcfd65597e3694a9532909d9
|
|
| BLAKE2b-256 |
5f7ea1b65ac23bd4537b94ced81355d133f7a908a8df80a5e7d9cdb1ac18b30e
|
Provenance
The following attestation bundles were made for fabra_ai-2.2.8.tar.gz:
Publisher:
release.yml on davidahmann/fabra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fabra_ai-2.2.8.tar.gz -
Subject digest:
1b35ed1dc3077ad208a36b5a44c8b7e0df31bc94be571c0d24d94e763599bc84 - Sigstore transparency entry: 774137587
- Sigstore integration time:
-
Permalink:
davidahmann/fabra@f4ce06549e3d10b261231afac6c8ce7910d708cf -
Branch / Tag:
refs/tags/v2.2.8 - Owner: https://github.com/davidahmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f4ce06549e3d10b261231afac6c8ce7910d708cf -
Trigger Event:
push
-
Statement type:
File details
Details for the file fabra_ai-2.2.8-py3-none-any.whl.
File metadata
- Download URL: fabra_ai-2.2.8-py3-none-any.whl
- Upload date:
- Size: 221.7 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 |
2785f48d31dac797b134de641917947a98a0d07af702e4b5a19324f7a5591e80
|
|
| MD5 |
29e974cbb1c9f643f08e2e83ecfcec68
|
|
| BLAKE2b-256 |
2a30d5a9fa5c043b3bdba6d14581c4439e5aaaad835954311edfacb49574ec52
|
Provenance
The following attestation bundles were made for fabra_ai-2.2.8-py3-none-any.whl:
Publisher:
release.yml on davidahmann/fabra
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
fabra_ai-2.2.8-py3-none-any.whl -
Subject digest:
2785f48d31dac797b134de641917947a98a0d07af702e4b5a19324f7a5591e80 - Sigstore transparency entry: 774137588
- Sigstore integration time:
-
Permalink:
davidahmann/fabra@f4ce06549e3d10b261231afac6c8ce7910d708cf -
Branch / Tag:
refs/tags/v2.2.8 - Owner: https://github.com/davidahmann
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@f4ce06549e3d10b261231afac6c8ce7910d708cf -
Trigger Event:
push
-
Statement type: