Skip to content
Open-source model governance

git for models.

Know what models you have deployed, where they run, what they depend on, and what changed — across every platform, as one immutable, queryable graph. Built for the regulator’s real question: show me everything that ever changed.

raw_txns features rules fraud_model review_queue

declare nodes · connect() · the graph builds itself

model-ledger is a model inventory for any organization with deployed models. It discovers models, heuristic rules, and ETL across your platforms, maps the dependency graph automatically, and records every change as an immutable event. Unlike registries tied to one platform (MLflow, SageMaker, W&B), it spans all of them — and it's built to be driven by AI agents through a native MCP server.

Get started in 60 seconds Why a ledger, not a registry?

Four ways in

  •  Python SDK


    Declare nodes; the graph connects itself. The whole API is tool-shaped.

    pip install model-ledger
    

    Quickstart

  •  MCP Server


    Talk to your inventory. The agent surface is the product — 8 tools, 3 resources.

    pip install "model-ledger[mcp]"
    claude mcp add model-ledger -- model-ledger mcp --demo
    

    Agent guide

  •  REST API


    Auto-generated OpenAPI for frontends and dashboards. Same tools over HTTP.

    pip install "model-ledger[rest-api]"
    model-ledger serve --demo
    

    Backends & serving

  •  CLI


    Launch the MCP server or REST API from anywhere — zero config to start.

    model-ledger mcp      # for agents
    model-ledger serve    # for HTTP
    

    Reference

The graph builds itself

Every model is a DataNode with typed input and output ports. When an output name matches an input name, connect() creates the dependency edge — no hand-wiring.

from model_ledger import Ledger, DataNode

ledger = Ledger.from_sqlite("./inventory.db")

ledger.add([
    DataNode("segmentation", platform="etl",      outputs=["customer_segments"]),
    DataNode("fraud_scorer", platform="ml",       inputs=["customer_segments"], outputs=["risk_scores"]),
    DataNode("fraud_alerts", platform="alerting", inputs=["risk_scores"]),
])
ledger.connect()

ledger.trace("fraud_alerts")
# ['segmentation', 'fraud_scorer', 'fraud_alerts']
graph LR
    A["segmentation<br/><small>ETL</small>"] -->|customer_segments| B["fraud_scorer<br/><small>ML model</small>"]
    B -->|risk_scores| C["fraud_alerts<br/><small>Alert queue</small>"]
    classDef etl fill:#607D8B,color:#fff,stroke:#455A64;
    classDef ml fill:#7a1a1a,color:#fff,stroke:#5a1010;
    classDef alert fill:#C8884E,color:#fff,stroke:#9c6a3a;
    class A etl; class B ml; class C alert;

One operation, every surface

The SDK, the REST API, and the MCP tools are the same six verbsdiscover, record, investigate, query, trace, changelog (plus tag/list_tags). Registering a model looks like this everywhere:

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 fraud detection",
)
{
  "tool": "record",
  "arguments": {
    "model_name": "fraud_scoring",
    "event": "registered",
    "owner": "risk-team",
    "model_type": "ml_model",
    "purpose": "Real-time fraud detection"
  }
}
curl -X POST localhost:8000/record \
  -H 'content-type: application/json' \
  -d '{"model_name":"fraud_scoring","event":"registered",
       "owner":"risk-team","model_type":"ml_model",
       "purpose":"Real-time fraud detection"}'

Why a ledger, not a registry

A registry answers "what is the current state?" A regulator asks "show me the complete history of every change, approval, and validation." Those are different data structures.

model-ledger treats the inventory as an append-only event log. A model is an identity (ModelRef); everything else — every retrain, every config change, every validation — is an immutable, content-addressed Snapshot. You get full history and point-in-time reconstruction for free, because nothing is ever overwritten.

That's exactly what a model-risk program needs — see how it maps to SR 26‑2, the EU AI Act, and NIST in Governance.

 Cross-platform — ML models, heuristic rules, ETL, and queues are all one DataNode. The graph spans MLflow, SageMaker, your warehouse, your scheduler.

 Change is the point — every mutation is an immutable Snapshot. Reconstruct your inventory as it stood on any date.

 Agent-native — the MCP server is a first-class surface, not an afterthought. Ask Claude "if we deprecate customer_features, what breaks?"

 Bring your own everything — storage backends, source connectors, and compliance profiles are all pluggable protocols.


Built in the open by Block · Apache-2.0 · Source · PyPI · /llms.txt for agents