Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ End-to-end integration examples showing cMCP, Agent Manifest, and TRACE working
|---|---|---|---|
| `financial-services/` | Payment agent with Cedar policy: blocks PII in tool call parameters | SEV-SNP / TDX | EU AI Act Art. 9/12, DORA Art. 9 |
| `healthcare/` | Clinical decision agent with HITL approvals and EU AI Act Art. 14 compliance records | SEV-SNP / TDX | EU AI Act Art. 14, HIPAA |
| `industrial-embodied-ai/` | Material-movement agent with cMCP authorization and an independent safety-controller boundary | TEE / software-only development mode | OT security and industrial robot safety references |
| `multi-tenant-saas/` | SaaS platform with per-tenant policy isolation | TDX | Customer contract SLA |
| `startup-tpm/` | 15-minute quickstart on any cloud VM with Trusted Launch | TPM 2.0 | Development / staging |

Expand Down
6 changes: 6 additions & 0 deletions industrial-embodied-ai/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Hash-bound artifacts must check out byte-identical on every platform.
# core.autocrlf=true otherwise rewrites LF to CRLF on Windows and breaks
# the system_prompt_hash check in validate_artifacts.py.
artifacts/** -text
artifact-hashes.json -text
trace-output/*.json -text
4 changes: 4 additions & 0 deletions industrial-embodied-ai/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
__pycache__/
*.pyc
audit.db
trace-output/latest-*.json
262 changes: 262 additions & 0 deletions industrial-embodied-ai/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,262 @@
# industrial-embodied-ai: Governed Material Movement

End-to-end example of an AI agent requesting motion from an industrial robot
cell through cMCP, with Agent Manifest declarations and a runtime-issued TRACE
Trust Record.

The scenario is synthetic. It uses no robot hardware, vendor SDK, production
endpoint, or proprietary industrial data.

## What the example demonstrates

The agent runs three paths through a live cMCP Runtime:

1. **Allowed and completed:** cMCP authorizes the declared workflow, then the
independent controller accepts and completes the simulated motion.
2. **Policy denied:** cMCP denies an undeclared workflow before the controller
receives the request.
3. **Safety rejected:** cMCP authorizes the declared workflow, but the
controller rejects motion after its current state reports a person in the
safeguarded area.

The third path is the central boundary:

> A cMCP `allow` decision means the software request is authorized. It does
> not mean that a physical action is safe, accepted by the controller, or
> completed by a machine.

## Architecture

```text
Material-movement agent
|
| MCP tools/call
v
+--------------------------+ Agent Manifest declares:
| cMCP Runtime | <--- agent, prompt, policy and tool hashes
| - attested tool catalog |
| - Cedar authorization |
| - hash-chained audit |
+------------+-------------+
|
| authorized request
v
+-------------------------------+
| Independent mock controller |
| - validates fresh state token |
| - rechecks current cell state |
| - enforces speed and zone |
+---------------+---------------+
|
| accepted command
v
Simulated robot execution

Session close -> signed TRACE Trust Record + signed audit bundle
```

## Run it

Prerequisites:

- Python 3.11 or newer
- Git

The project is a developer preview. `requirements.txt` pins the cMCP and TRACE
commits used for this reproducible example until the summit release stack is
available from PyPI.

```bash
cd industrial-embodied-ai
python -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
```

Start the mock controller:

```bash
python server/mock_robot_controller.py
```

In a second terminal, start cMCP in explicitly non-hardware development mode:

```bash
cd industrial-embodied-ai
source .venv/bin/activate
CMCP_DEV_MODE=1 cmcp start --config cmcp-config.yaml
```

In a third terminal, run the agent:

```bash
cd industrial-embodied-ai
source .venv/bin/activate
python agent/material_movement_agent.py
```

Expected summary:

```text
SUCCESS
cMCP policy: authorized
controller: accepted
execution: completed

POLICY DENY
cMCP policy: denied
controller: not invoked

SAFETY REJECT
cMCP policy: authorized
controller: rejected
reason: human_detected
execution: not_started

TRACE VERIFICATION
schema/signature/hashes/freshness: verified
audit bundle: verified
runtime platform: software-only
hardware attestation: not verified (development mode)
```

The agent writes fresh evidence to:

- `trace-output/latest-trust-record.json`
- `trace-output/latest-audit-bundle.json`

These files are ignored by Git. The committed `example-*` files were captured
from a real run and remain available for offline inspection.

## Hardware-attested run

On a supported host, do not set `CMCP_DEV_MODE`. Pin the expected artifacts
and configure the same bearer token for the runtime and agent:

```bash
export CMCP_BEARER_TOKEN="$(python -c 'import secrets; print(secrets.token_urlsafe(32))')"
export CMCP_POLICY_HASH="sha256:c8358148d201749ebd05651ea03cf92fb3ff8cc9cf05816483c394ebc3e1cac9"
export CMCP_CATALOG_HASH="sha256:792c86ff8152fa9713d52584c084611eb4929fa5ebf3ec8271dd21f0e0aa7eeb"

cmcp start --config cmcp-config.yaml
```

Then require hardware verification in the agent:

```bash
python agent/material_movement_agent.py --require-hardware
```

The runtime must detect and successfully verify one of its supported
attestation providers. Development mode intentionally cannot satisfy
`--require-hardware`.

## Verify committed artifacts

```bash
python validate_artifacts.py
python -m unittest discover -s tests -v
```

The validator checks:

- cMCP configuration and catalog definition hashes
- policy bundle and catalog hashes
- Agent Manifest artifact bindings and Ed25519 signature
- runtime-issued TRACE schema and signature
- signed audit-bundle integrity and binding to the TRACE record

To verify fresh output using the cMCP CLI:

```bash
cmcp verify trace-output/latest-trust-record.json \
--policy-hash sha256:c8358148d201749ebd05651ea03cf92fb3ff8cc9cf05816483c394ebc3e1cac9 \
--catalog-hash sha256:792c86ff8152fa9713d52584c084611eb4929fa5ebf3ec8271dd21f0e0aa7eeb \
--audit-bundle trace-output/latest-audit-bundle.json
```

## Evidence boundaries

| Evidence | What it establishes | What it does not establish |
|---|---|---|
| Agent Manifest | The signed declaration and hashes of the approved prompt, policy and tools | That the deployed runtime loaded those artifacts |
| cMCP decision | The active policy authorized or denied a cataloged tool request | That an authorized physical request was safe |
| TRACE Trust Record | Runtime, policy hash, catalog hash and tool-call transcript integrity | Controller acceptance, physical completion or functional-safety compliance |
| Controller response | The mock controller's decision returned during this run | A hardware-backed or independently retained execution record |

The current cMCP audit bundle records request hashes and authorization
decisions, but does not populate a response hash for the controller outcome.
The example therefore does not claim that TRACE proves controller acceptance
or physical completion. Binding independent controller evidence is a
follow-up design question, not something this example silently invents.

## AgentTrust artifacts

| File | Purpose |
|---|---|
| `agent-manifest.json` | Signed development declaration binding the prompt, policy bundle and tool catalog |
| `manifest-public-key.json` | Public verification key for the Agent Manifest |
| `artifact-hashes.json` | Approved cMCP and Agent Manifest artifact hashes |
| `catalog.json` | Attested definitions for safety-state and motion-request tools |
| `cmcp-config.yaml` | cMCP configuration shared by development and hardware runs |
| `policy/allow.cedar` | Explicit workflow-scoped permits with default deny |
| `trace-output/example-trust-record.json` | TRACE Trust Record captured from the live development run |
| `trace-output/example-audit-bundle.json` | Signed cMCP audit bundle captured from the same session |

The Agent Manifest is a signed declaration artifact in this example. The
current cMCP preview loads the policy and catalog directly; the validator
checks that their hashes agree with the manifest instead of claiming cMCP
consumes the manifest natively.

## Threats illustrated

- **Compromised planner:** only cataloged tools in the declared workflow are
authorized.
- **Policy bypass:** the undeclared workflow is denied before forwarding.
- **Untrusted request arguments:** the controller never accepts agent-supplied
safety booleans.
- **Stale or modified state:** short-lived authenticated state tokens fail
closed.
- **Replay:** a state token is single-use.
- **Time-of-check/time-of-use change:** the controller rechecks current state
and rejects motion even after cMCP authorization.

The HMAC state token is a teaching mechanism, not an industrial security
protocol. A real deployment requires authenticated device identity, protected
keys, replay protection, secure time and a validated industrial communication
architecture.

## Safety boundary

This example does not provide or certify:

- emergency-stop functions
- protective stops or safe torque off
- collision avoidance
- safe speed or separation monitoring
- safety-rated control logic
- machinery conformity assessment

Those functions remain in independently engineered and validated
safety-related control systems.

## External references

- [NIST SP 800-82 Rev. 3](https://csrc.nist.gov/pubs/sp/800/82/r3/final)
- [ISO 10218-1:2025](https://www.iso.org/standard/73933.html)
- [ISO 10218-2:2025](https://www.iso.org/standard/73934.html)
- [ISO 13849-1:2023](https://www.iso.org/standard/73481.html)
- [IEC 62443-4-2:2019](https://webstore.iec.ch/en/publication/34421)
- [IETF RFC 9334](https://datatracker.ietf.org/doc/rfc9334/)
- [IETF RFC 9711](https://datatracker.ietf.org/doc/rfc9711/)
- [ROS 2 Security Enclaves](https://design.ros2.org/articles/ros2_security_enclaves.html)
- [ROS 2 Access Control Policies](https://design.ros2.org/articles/ros2_access_control_policies.html)
- [Regulation (EU) 2023/1230](https://eur-lex.europa.eu/eli/reg/2023/1230/oj/eng)
- [Regulation (EU) 2024/1689](https://eur-lex.europa.eu/eli/reg/2024/1689/oj/eng)

These references inform the separation of responsibilities. The example is
not a claim of compliance with any standard or regulation.

## License

Apache 2.0. See [LICENSE](../LICENSE) in the repository root.
88 changes: 88 additions & 0 deletions industrial-embodied-ai/agent-manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
{
"@context": "https://agentmanifest.agentrust.io/v0.1/context.json",
"@type": "AgentManifest",
"manifest_id": "0197739a-8c00-7000-8000-000000000001",
"agent_id": "spiffe://factory.example/agent/material-movement/dev",
"version": "0.1",
"issued_at": "2026-06-12T00:00:00Z",
"expires_at": "2026-09-10T00:00:00Z",
"issuer": "spiffe://factory.example/signing-authority/development",
"crypto_profile": "standard",
"artifacts": {
"system_prompt": {
"hash": "sha256:9b364864a1d6682f56f572052dd7a0701b35d9726046bcb06d5fa5d87b49a70f",
"hash_algorithm": "SHA-256",
"version": "0.1.0",
"classification": "internal",
"bound_at": "2026-06-12T00:00:00Z"
},
"policy_bundle": {
"hash": "sha256:c8358148d201749ebd05651ea03cf92fb3ff8cc9cf05816483c394ebc3e1cac9",
"policy_language": "cedar",
"version": "0.1.0",
"enforcement_mode": "enforce",
"scope": [
"cell.read_safety_state",
"robot.request_motion"
],
"bound_at": "2026-06-12T00:00:00Z"
},
"tool_manifest": {
"catalog_hash": "sha256:3c7460301bbf38612b492de4a2095ccf40b7d921bdc9ce96e8ea0f50068d66e0",
"tools": [
{
"tool_id": "spiffe://factory.example/tool/cell.read_safety_state",
"name": "cell.read_safety_state",
"server_id": "spiffe://factory.example/controller/robot-cell-7",
"schema_hash": "sha256:99334726611ccf58a148b0814696bfa6fe08c1b2d027e946beccf5a74331c9aa",
"description_hash": "sha256:1a4030f710f75b6d7cabddbde5a774ca541450f7a8dcb5f46fcbf9a119dd6de7",
"version": "0.1.0",
"permission_scope": "safety-state:read",
"egress_destinations": []
},
{
"tool_id": "spiffe://factory.example/tool/robot.request_motion",
"name": "robot.request_motion",
"server_id": "spiffe://factory.example/controller/robot-cell-7",
"schema_hash": "sha256:d74b377cfce397a9074d2b6b377615f32f370e218a59594346cbaadd8ca88d00",
"description_hash": "sha256:6b67d52c678da09fc6bce54367ba3bf0a44ff92f3930db8a66e3d43af7ab6975",
"version": "0.1.0",
"permission_scope": "motion:request",
"egress_destinations": []
}
],
"allow_dynamic_registration": false,
"rug_pull_policy": "deny-and-alert",
"bound_at": "2026-06-12T00:00:00Z"
},
"model_identity": {
"provider": "example",
"model_id": "industrial-material-movement-planner",
"version": "development-simulation-v1",
"deployment_type": "api",
"bound_at": "2026-06-12T00:00:00Z"
}
},
"delegation_chain": [],
"signature": {
"algorithm": "Ed25519",
"key_id": "cd3708166771d7bd74a49e8d307842c318aded09c0348688d7ac6e40952a5522",
"key_type": "software",
"signed_at": "2026-06-12T00:00:00Z",
"signed_fields": [
"@context",
"@type",
"manifest_id",
"agent_id",
"version",
"issued_at",
"expires_at",
"issuer",
"crypto_profile",
"artifacts",
"delegation_chain",
"hitl_record"
],
"signature_value": "zYvzfGDshwKcAApc_JWmCXigNytQDhokavCQCTUwOtsQeDLYEoPETxgii3Acz2hl7RNIH-O4FKTdtYlNXt6MBA"
}
}
Loading
Loading