Minibridge is a proof-and-metering service for LLM API calls.
It sits between a caller and an upstream LLM provider, keeps the API key inside a trusted boundary, executes the call, returns the response to the caller, and emits a tamper-evident receipt that proves the request, the response, and the billable usage.
The cost bearer is the provider / key owner, not the caller. The caller submits work; Minibridge proves what was spent.
The service boundary is narrow:
- it receives a request for an LLM call,
- keeps the API key inside a trusted boundary,
- forwards the call to the model provider,
- records the exact request/response metadata and token usage,
- computes a cost from a pinned pricing table,
- signs a tamper-evident receipt.
The current code is TEE-ready, but it is not tied to a specific hardware enclave yet. The design is meant to be moved behind a TEE or HSM later.
The service is split into two layers:
- the untrusted outer service: HTTP, orchestration, storage, admin flow
- the trusted inner boundary: API key handling, LLM provider calls, receipt signing, attestation evidence
The HTTP surface supports both generic and provider-specific calls:
POST /callPOST /provePOST /providers/{provider_id}/callPOST /providers/{provider_id}/proveGET /providersGET /proofsGET /proofs/{proof_id}POST /register-provider
- the request hash
- the response hash
- the model name and parameters
- token usage returned by the provider
- the computed cost under a pinned pricing table
- that the receipt was signed by the service
- one-time request IDs, expiry times, and caller allowlists
- a typed key policy rather than ad hoc enrollment fields
- that the provider independently signed the same bill
- that the agent was correct outside the service boundary
- that the host machine was trustworthy unless the service runs inside a real TEE
src/minibridge/core/— shared domain objects: requests, receipts, proofs, pricing, signing, attestation, verificationsrc/minibridge/providers/— provider registry and OpenAI-compatible provider adapterssrc/minibridge/proof/— the proof service and call/prove orchestrationsrc/minibridge/transport/— HTTP server and request handlerssrc/minibridge/app/— CLI and local state persistencesrc/llm_api_proof/— compatibility package that re-exports the Minibridge modulesexamples/mock_run.py— end-to-end demo using the mock providerexamples/http_demo.py— end-to-end demo using the HTTP servicedocs/provider-registration.md— provider registration payloads for OpenAI, OpenRouter, Chutes, and mockconfigs/minibridge.demo.json— demo bootstrap config for local or container useDockerfileanddocker-compose.yml— containerized demo runtimeweb/— separate frontend app boundary for the Minibridge dashboard
python3 examples/mock_run.pyThe demo prints a signed receipt and verifies it locally.
To run the HTTP service demo:
python3 examples/http_demo.pyInstall the project in editable mode and use the minibridge command:
pip install -e .
minibridge --helpRun a local service with a generated signing key:
minibridge serveThat writes a private signing key file and a matching public key file, then starts the HTTP service.
By default it also writes .minibridge-state.json, which persists providers, keys, and receipts across restarts. Use --state-file "" to disable persistence.
Register a provider and a key against a running service:
minibridge providers add --payload - --server http://127.0.0.1:8080
minibridge keys add --payload - --server http://127.0.0.1:8080The provider payload examples are in docs/provider-registration.md.
Submit a request through the service:
minibridge call --payload docs/request.json --server http://127.0.0.1:8080Capture a public proof bundle:
minibridge prove --payload docs/request.json --server http://127.0.0.1:8080Create a SparkProof-style offline bundle from a running service:
minibridge bundle create --server http://127.0.0.1:8080 --bundle bundles/run-001Verify that bundle on any CPU host:
minibridge bundle verify --bundle bundles/run-001The HTTP API also exposes:
GET /bundleGET /bundle/exportGET /bundle/manifest
Verify a receipt offline:
minibridge verify --receipt docs/receipt.json --public-key-file .minibridge-signing.key.pubYou can also verify a proof bundle directly:
minibridge verify --proof docs/proof.json --public-key-file .minibridge-signing.key.pubFor unattended startup, use minibridge serve --config <file>.json with a bootstrap file that includes pricing_table, optional providers, and optional keys.
For a containerized demo, run:
docker compose up --buildThat starts Minibridge on http://127.0.0.1:8080 using configs/minibridge.demo.json and persists state under ./data.
The web UI lives under web/ and talks only to the HTTP API. It can be run independently of the Python package.
With the included compose stack, the API is published on http://127.0.0.1:18080 and the UI on http://127.0.0.1:5173.
The receipt proves metered usage observed by the trusted service. It does not prove the upstream provider’s internal invoice unless the provider participates in the protocol.
The attestation layer is intentionally abstracted so you can start with MockAttestationProvider and later swap in a real TEE attestation backend without changing the service API or receipt format.
The attestation record is structured, not just a free-form blob. In the current MVP it carries:
- attestation mode
- backend identifier
- service instance ID
- context hash
- optional measurement / quote / report-data fields
- extra claims
The service also enforces a basic anti-replay boundary:
request_idis accepted once per(owner_id, key_id)- optional
expires_atrejects stale calls - optional
allowed_callerslimits which agent or validator may spend a key KeyPolicyis the enrollment object used by the service and HTTP API
OpenRouter and Chutes are documented as OpenAI-compatible surfaces, and OpenAI itself publishes the official API reference. In this repo, the provider registry treats them as OpenAI-compatible backends with configurable endpoint URLs and payload styles rather than hard-coding one transport shape for every vendor.
See docs/provider-registration.md for copy-pastable POST /register-provider payloads and a provider-specific call example.
-
Lock the public API.
Freeze the request, receipt, provider, and policy schemas so downstream users can rely on them.
-
Harden the trusted boundary.
Move the key store, provider call path, and receipt signer into a real TEE-backed runtime and wire attestation verification into enrollment.
-
Add provider-specific adapters.
Keep OpenAI, OpenRouter, and Chutes as explicit backend profiles with clear request shaping and response normalization.
-
Add settlement primitives.
Track per-key spend, per-caller policy, expiry, and revocation so receipts can be used for reimbursement or audit.
-
Add operator tooling.
Provide a CLI and small admin surface for provider registration, key enrollment, and receipt inspection.
-
Make the caller-facing path explicit.
The caller should receive the LLM response through Minibridge, not by talking to the upstream provider directly.
-
Add failure-mode tests.
Cover replay, bypass, stale requests, bad provider config, provider outages, and attestation mismatch.
That is still useful for:
- reimbursement
- validator settlement
- audit trails
- metered API usage proof
The caller-facing path is explicit now: the caller submits a request to Minibridge and receives the response back from Minibridge, along with the receipt that proves the billable call.