Quickstart¶
Zero infrastructure. Zero credentials. From pip install to a working dependency
graph in under a minute.
from model_ledger import Ledger, DataNode
ledger = Ledger() # in-memory; swap for Ledger.from_sqlite("inv.db") to persist
ledger.add([
DataNode("raw_txns", platform="warehouse", outputs=["transactions"]),
DataNode("feature_build", platform="etl", inputs=["transactions"], outputs=["features"]),
DataNode("fraud_model", platform="ml", inputs=["features"], outputs=["risk_scores"]),
DataNode("review_queue", platform="alerting", inputs=["risk_scores"]),
])
ledger.connect() # ports match → edges appear
print(ledger.trace("review_queue"))
# ['raw_txns', 'feature_build', 'fraud_model', 'review_queue']
print(ledger.upstream("fraud_model"))
# ['raw_txns', 'feature_build']
That's the whole idea: declare nodes, the graph connects itself. Next, give a node an identity and a history → Register a model.
pip install "model-ledger[mcp]"
# Register the server with Claude Code (one time)
claude mcp add model-ledger -- model-ledger mcp --demo
Then just ask:
You: what models are in my inventory?
Claude: 7 models across 5 platforms.
fraud_scoringwas retrained and deployed this week. Want me to dig into anything?You: if we deprecate
customer_features, what breaks?Claude: 3 models consume it directly, 2 more transitively.
The --demo flag loads a sample inventory so you can explore before connecting
your own data. See the Agent guide for the full tool surface.
Register a model¶
A DataNode gives you the graph. register() gives a model an
identity and starts its history — the two things a regulator asks for.
from model_ledger import Ledger
ledger = Ledger.from_sqlite("./inventory.db")
ledger.register(
name="fraud_scoring",
owner="risk-team",
model_type="ml_model",
tier="high",
purpose="Real-time card fraud detection",
)
# Record an event — any payload you like, no schema to maintain
ledger.record("fraud_scoring", event="retrained", actor="ml-pipeline",
payload={"accuracy": 0.94, "features_added": ["velocity_24h"]})
for snap in ledger.history("fraud_scoring"):
print(snap.timestamp, snap.event_type)
# ... registered
# ... retrained
Every call appends an immutable Snapshot. Nothing is overwritten — that's what makes the inventory auditable.
Choose where it lives¶
Storage is a one-line decision and never changes your code:
from model_ledger import Ledger
from model_ledger.backends.json_files import JsonFileLedgerBackend
Ledger() # in-memory — tests & demos
Ledger.from_sqlite("./inventory.db") # zero-infra, single file
Ledger(JsonFileLedgerBackend("./inventory")) # git-friendly JSON files
Ledger.from_snowflake(conn, schema="DB.MODEL_LEDGER") # production
Where to next¶
- Concepts — DataNode, Snapshot, Composite. The whole model in three ideas.
- Agent guide — the 8 MCP tools and a worked multi-tool transcript.
- Recipes — copy-paste solutions to real tasks.
- API reference — generated from source, never out of date.