Start with one demo
You need Python 3.11 or later, Git, and Bash on macOS, Linux, or Windows with WSL. No cloud account and no special hardware. The demos stand in software for the chip's signed report (attestation), so they show the checks working but not the hardware protection itself.
git clone https://github.com/agentrust-io/integrations && cd integrations/demos
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txt
python demo.py 1 # start with tool-call policy enforcement
The requirements install cMCP for demos 1 to 5, Weight Custody Manifest for demos 6 to 9, and a model API client for demo 10. demo.py sets dev mode and the bearer token for you, so there is nothing to export. Source: github.com/agentrust-io/integrations/tree/main/demos.
What to look for: demo 1 sends an agent's actions through a local checkpoint (the cMCP gateway) and ends with a signed record of what was allowed and refused. Because there is no real hardware, that record does not pass a hardware check. To explore weight custody, run python demo.py 6; to run the full set without pauses, use python demo.py --no-pause.
Individual commands below: run them from the demos folder with the environment activated. For demos that start cMCP, set export CMCP_BEARER_TOKEN=demo-token first. The demo.py launcher handles this setup for you.
Real WCM code with a software (mock) attestation provider, no hardware.
downloaded hash : sha256:b3a36b547da3babd1dc9f2b900…
owns the silicon (see TEE.fail), not silicon-proof
custody. It IS the provenance the download never gave you.
Securing model weights
A model's weights are the trained file that is the model. A version you trained further on your own data (a fine-tune) is valuable work that exists nowhere else. These four demos protect that file: record exactly which file it is, hand the key that decrypts it only to a server that proves what it is running, and keep a checkable family tree from every derived model back to its original.
The honest limit, stated up front. If an attacker physically owns the machine, no confidential-computing chip on sale today can keep the weights safe. Published attacks such as TEE.fail and BadRAM show why. What these demos give you is a clear, signed record of who could release the key and when, which holds as long as you trust the operator not to attack their own hardware. Demo 9 adds a scheme where several parties must agree before a key is released, for when one operator's word is not enough. Anyone selling you weight protection "without operator trust assumptions" is overstating what the hardware does.
What you will see: a model file with one changed byte is refused before it loads, while the genuine file gets its key.
A Weight Custody Manifest binds the checkpoint's exact weights_hash, gates the decryption key behind attestation, and carries the fine-tune's lineage.
- a manifest jointly signed by builder and custodian binds the exact
weights_hash, and the signature verifies - the attestation gate releases the key only for the certified serving stack: genuine nonce, approved platform, signed image measurement
- a tampered checkpoint's hash does not match, so it is refused before it ever loads
- a fine-tune verifies as a derivative back to the signed base
python demo-06-weight-custody/run.py
What you will see: a server that could leak the secret model file asks for the key and is turned away.
The mirror of demo 6. Here the base model is closed, a frontier lab shipping weights into a customer's or a sovereign's own enclave, so the weights themselves are the secret and the job is keeping the key off the operator.
- a manifest with
base_confidentiality: confidential, jointly signed by lab and customer - the key releases only into the attested, lab-signed serving stack
- an unapproved stack, one that could export plaintext weights, is refused the key
- same protocol as demo 6, different job
python demo-07-closed-weight/run.py
What you will see: a model trained from a protected base is traced back to it, and an unauthorised copy of the new model is rejected.
Fine-tune inside the enclave on private data and the result is novel IP. It gets its own signed manifest with a derived_from pointer and a rights_holder split.
- a base permitting
fine-tune-only, and a derivative permittingnone verify_lineageresolves the derivative back to the base: chain, depth, root- the
rights_holderrecords the base and derivative IP split - rights are monotone, so a fork of the no-derivatives derivative is rejected
python demo-08-derivative-lineage/run.py
What you will see: one party alone cannot decrypt the model; it takes two of the three key holders.
This is the answer to the limit in the callout above. If a hardware owner who forges one attestation could release a key, then never let one release be enough.
- the model key is split 2-of-3 across the lab, the sovereign authority, and the customer
- a single share reconstructs nothing, so one forged attestation sits below threshold
- two independent shareholders each attest and release their share
- forging now means forging attestation to a quorum of independent roots, not one
python demo-09-sovereign-threshold/run.py
Checking what an agent does
These six put written rules at the point an agent has to pass through: five where it uses a tool, and demo 10 where it sends a request to an AI model. The rules decide what the agent may do, in which job, and with what kind of data. They are written in Cedar, an open policy language, checked on every call, and each session ends with a signed TRACE receipt of what happened.
What you will see: an agent writes and reads a file, is refused when it tries to list a folder, and gets a signed record of all three.
An agent calls three tools through the cMCP gateway. Cedar is enforced on every call, and the session closes with a signed TRACE claim carrying the policy bundle hash.
write_fileandread_fileallowed, real files written toworkspace/list_dirdenied by policy: HTTP 403,POLICY_DENY- the claim carries
runtime.platform,runtime.measurement,policy.bundle_hash - on real Intel TDX the bundle hash flows into RTMR[2] at startup
python demo-01-cmcp-in-action/run.py
What you will see: someone quietly swaps the rule set, and the receipt check catches it.
The operator quietly loads a different policy bundle. The claim's hash changes, and a verifier pinned to the old hash rejects it.
- v1 and v2 bundle hashes printed, visibly different
write_filenow denied under v2- verifying a v2 claim against the pinned v1 hash fails with
POLICY_HASH_MISMATCH - on real TDX the measurement itself changes, not just a field
python demo-02-policy-swap/run.py
What you will see: a receipt checked on your machine with no network, with a plain list of what could and could not be confirmed.
Verify the signed claim with no gateway, no server, and no network call at all.
- schema, signature, policy hash, catalog hash and audit chain all check out
hardware_attestationstays inunverified_fieldsin software mode, so the status readspartially_verified- on real TDX that field verifies too and the status becomes
verified - no connection is made to anything
python demo-03-offline-trace/run.py
What you will see: the same action allowed in one job and refused in another.
The same tool, the same arguments, allowed in one workflow and denied in another. The decision depends on the job the call says it belongs to. The tool's name and the model's stated reason do not change it.
write_fileunderworkflow_id="invoice-run": allowed- the identical call under
workflow_id="chat-freeform": denied, default-deny holds read_filestill allowed in both, so only the write capability is scoped- both the allow and the deny land in the signed audit chain
python demo-04-context-enforcement/run.py
What you will see: a tool that is not cleared for patient data is refused, whatever its name.
Refuse a tool based on its labels instead of its name. A tool not covered by a business associate agreement (BAA, the US contract required to handle patient data) is refused by one rule, whatever it is called.
- tools tagged
compliance_domain=clinical,baa_covered=true: allowed - a tool tagged
baa_covered=false: denied - the deny comes from
forbid ... when { context.baa_covered == false }, overriding the baseline permit - one rule covers every non-covered tool in the catalog, present and future
python demo-05-compliance-domain/run.py
What you will see: each prompt sent to a different model route, or cleaned first, depending on how sensitive its data is.
Put rules in front of a model endpoint that uses the common chat-completions API, and send each request where its kind of data is allowed to go.
- public prompts can use the shared model route
- personal data (PII) leaves only after names and other identifiers are stripped
- confidential prompts and patient health data (PHI) stay on approved servers in the right region
- the same governance boundary applies to model calls, not only MCP tools
python demo-10-model-gateway/run.py
Where to go next
- Demo source on GitHub, including a web console and a plain JSON-RPC test server
- weight-custody-manifest on PyPI, the reference SDK behind demos 6 to 9
- Worked WCM examples
- cMCP and TRACE specifications
- The cMCP quickstart if you would rather write the policy yourself