Enforcement gateway for the OpenCastor stack — receives signed RCAN action envelopes, verifies manifest provenance, applies tier policy + tool allowlist, dispatches to drivers. Mandatory exclusive path between agent intent and any actuator.
Project description
robot-md-gateway
The mandatory enforcement gateway for the OpenCastor stack. Receives signed RCAN action envelopes, verifies manifest provenance, applies tier policy + tool allowlist, dispatches to drivers. Exclusive path between agent intent and any actuator. Open, neutral, becomes OpenCastor's safety kernel via open-core extraction.
Renamed in 2026-05. This package was previously published as
robot-md-dispatcher. The old name is now a tombstone on PyPI;pip install robot-md-dispatchercontinues to work and pulls this package as a dependency. Imports and therobot-md-dispatcherCLI keep working through v0.4.x via a backward-compat shim. See CHANGELOG.md for migration notes.
Where this fits in the stack
robot-md-gateway is Layer 3 of the OpenCastor stack — the
enforcement gateway. Every action that crosses from agent intent to
any actuator passes through this gateway. There is no second path.
| Layer | Piece | What it is |
|---|---|---|
| 1 — Declaration | robot-md | The ROBOT.md file + Python CLI. Declares identity, capabilities, safety gates. |
| 2 — Agent runtime | (any MCP host) | Claude Code, Codex, Gemini — plans actions, calls tools, never reaches actuators directly. |
| 3 — Gateway / Enforcement ← this | robot-md-gateway | Mandatory exclusive path. Verifies signatures, applies policy, signs audit bundles. |
| 4 — Robot-facing runtime | OpenCastor | Productized open-core runtime. Embeds the gateway as its safety kernel. |
| 5 — Protocol | rcan-spec | Wire format, envelopes, conformance suite. |
| 6 — Registry | Robot Registry Foundation | Identity (RRN/RCN/RMN/RHN), public keys, evidence. |
See the live compatibility matrix →
What it does
The gateway accepts incoming signed RCAN INVOKE envelopes — never plaintext goals, never SDK sessions. Every envelope is checked for:
- Manifest provenance — the ROBOT.md being actuated against has a verified signature from a key registered to this robot's RRN at RRF.
- Tier + RBAC — the caller's bearer token resolves to a tier authorized for this scope.
- Tool allowlist — the requested tool is in the operator's policy (default-deny on unknown).
- Confidence + HiTL gates (Phase 4 — Plan 6) — model-asserted confidence above threshold; human-in-the-loop approval if scope demands it.
- Replay protection (Plan 6) — envelope's nonce + timestamp not previously seen.
- ESTOP precedence (Plan 6) — physical or operator stop signal preempts any pending action.
If all checks pass, the gateway dispatches to a local actuation tool (typically a robot-md-mcp tool call or a direct driver invocation) and emits a signed audit bundle entry per action. If any check fails, the action is denied and the failure is logged + signed.
What it does not do
- ❌ Spawn LLM planners. That was the v0.2.x mode; it now ships as
--legacy-byok-launcherfor backward compat (deprecation-warned), removed in v0.4.0. Planners run in agent runtimes (Layer 2), separately, and produce signed envelopes that come to the gateway. - ❌ Be optional. If you can move the robot without going through the gateway, you don't have an enforcement gateway — you have a hint.
- ❌ Cover Layer 4. Drivers, fleet UI, cloud bridge belong to OpenCastor (or any future Layer-4 runtime); not here.
Where safety is actually enforced.
Physical safety is enforced at Layer 3 (
robot-md-gateway) or Layer 4 (a runtime that embeds it, e.g., OpenCastor). Declaration alone (Layer 1) does not enforce safety. Agent host alone (Layer 2) is not the safety boundary. If a deployment lacks Layer 3, no safety claim attaches to it.
Status (v0.3.0a1)
This release lands the rename + scope-shift skeleton. The receive-only
RCAN handler, manifest provenance verification (cert MF-001 / MF-002),
and direct-device-bypass denial (cert GW-001) ship in upcoming patch
releases under Plan 6. The legacy planner-launcher mode is preserved
behind --legacy-byok-launcher for one minor release.
Installation
pip install robot-md-gateway
Quick start (legacy mode, until receive-only ships)
python3 -m venv .venv
.venv/bin/pip install robot-md-gateway robot-md # robot-md-mcp ships with robot-md
.venv/bin/robot-md-gateway init --yes
.venv/bin/robot-md-gateway --legacy-byok-launcher serve \
--bearers ./bearers.yaml --robot-md ./ROBOT.md
init --yes writes bearers.yaml, .env, and dispatch-test.sh next to your
ROBOT.md and prints a generated actuate-tier token once. Save the token — it's
not stored anywhere else. Run robot-md-gateway init (no --yes) for a
guided walk that explains each knob.
Production install
systemd/install.sh handles the full setup: dedicated robot system user, /opt/robot-md-gateway/.venv with hardened unit, DeviceAllow=/dev/ttyACM0 rw, MemoryMax=1G, CPUQuota=80%, journal logging.
Run robot-md-gateway init --yes first (next to your ROBOT.md) to generate
bearers.yaml, .env, and dispatch-test.sh. Then:
sudo ./systemd/install.sh
sudo cp ./bearers.yaml ./.env /etc/robot-md-gateway/
sudo cp ./ROBOT.md /etc/robot-md-gateway/ROBOT.md
sudo systemctl daemon-reload && sudo systemctl enable --now robot-md-gateway
Ingress — do not port-forward
The gateway binds to 127.0.0.1 by design. Expose it via Tailscale Funnel (named, revocable, TLS-terminated):
tailscale serve --bg --https=443 http://127.0.0.1:8080
tailscale funnel 443 on
Configuration
Environment variables (also settable via CLI flags — flags win):
| Variable | Purpose | Default |
|---|---|---|
ROBOT_MD_PATH |
Path to the ROBOT.md loaded as the manifest under verification |
unset |
ROBOT_MD_BEARERS_FILE |
Path to bearers.yaml |
required |
ROBOT_MD_MCP_COMMAND |
Stdio MCP command the gateway dispatches to | robot-md-mcp |
ROBOT_MD_MCP_ARGS |
Space-separated args for the MCP command | (none) |
ROBOT_MD_LOG_LEVEL |
Python log level | INFO |
Development
python3 -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/pytest -q
.venv/bin/ruff check src tests
The test suite mocks external SDK boundaries via Protocol shims, so pytest runs offline. The tier gate, auth, and HTTP surface are exercised end-to-end with a TestClient. Real tool names from robot-md-mcp's server are pinned in tests/test_gating.py; if the upstream tool surface shifts in a way that inverts a read/actuate classification, the test fails loudly.
License
Apache-2.0. See LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file robot_md_gateway-0.4.0a1.tar.gz.
File metadata
- Download URL: robot_md_gateway-0.4.0a1.tar.gz
- Upload date:
- Size: 76.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6aae215bb534565663d9b702a8dce734c341b6ef73e7ec1fdb655221e16f5e17
|
|
| MD5 |
24d30f3730ef5052ea530374190b8dc2
|
|
| BLAKE2b-256 |
4d9515d009694b9d7bad6dabfbde353d97def41aea6ae66562c1a252adc7e5b5
|
Provenance
The following attestation bundles were made for robot_md_gateway-0.4.0a1.tar.gz:
Publisher:
release.yml on RobotRegistryFoundation/robot-md-gateway
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
robot_md_gateway-0.4.0a1.tar.gz -
Subject digest:
6aae215bb534565663d9b702a8dce734c341b6ef73e7ec1fdb655221e16f5e17 - Sigstore transparency entry: 1436534721
- Sigstore integration time:
-
Permalink:
RobotRegistryFoundation/robot-md-gateway@86b5806bb2dadf776c764e5f9ea2d243a9579f26 -
Branch / Tag:
refs/tags/v0.4.0a1 - Owner: https://github.com/RobotRegistryFoundation
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@86b5806bb2dadf776c764e5f9ea2d243a9579f26 -
Trigger Event:
push
-
Statement type:
File details
Details for the file robot_md_gateway-0.4.0a1-py3-none-any.whl.
File metadata
- Download URL: robot_md_gateway-0.4.0a1-py3-none-any.whl
- Upload date:
- Size: 37.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0262c3a0cf781adf2aba303ed492f02a8b00cd8ff6380d60c4e474252ecd39e3
|
|
| MD5 |
79bcf4557589dd0bf8d9c7d13a15bbd3
|
|
| BLAKE2b-256 |
93827db0aa613f3f5891f55f2a0624e385947fe897c253bf3d12b427be8782f8
|
Provenance
The following attestation bundles were made for robot_md_gateway-0.4.0a1-py3-none-any.whl:
Publisher:
release.yml on RobotRegistryFoundation/robot-md-gateway
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
robot_md_gateway-0.4.0a1-py3-none-any.whl -
Subject digest:
0262c3a0cf781adf2aba303ed492f02a8b00cd8ff6380d60c4e474252ecd39e3 - Sigstore transparency entry: 1436534828
- Sigstore integration time:
-
Permalink:
RobotRegistryFoundation/robot-md-gateway@86b5806bb2dadf776c764e5f9ea2d243a9579f26 -
Branch / Tag:
refs/tags/v0.4.0a1 - Owner: https://github.com/RobotRegistryFoundation
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@86b5806bb2dadf776c764e5f9ea2d243a9579f26 -
Trigger Event:
push
-
Statement type: