rcan-py
Python SDK for the RCAN protocol. Build robots that communicate securely, audit every action, enforce safety gates locally, and register with the Robot Registry Foundation. Pinned protocol version: see the live compatibility matrix.
Where this fits in the stack
This repo is the Python SDK layer — the library any Python planner, gateway, or driver links against to speak RCAN. Everything below is independent; adopt one, or all seven.
| Layer | Piece | What it is |
|---|---|---|
| Declaration | ROBOT.md | The file a robot ships at its root. YAML frontmatter + markdown prose. Declares identity, capabilities, safety gates. Spec + Python CLI. |
| Agent bridge | robot-md-mcp | MCP server that exposes a ROBOT.md to Claude Code, Claude Desktop, Cursor, Zed, Gemini CLI — any MCP-aware agent. |
| Wire protocol | RCAN | How robots, gateways, and planners talk. Signed envelopes, LoA enforcement, PQC crypto. Think HTTP for robots. |
| Python SDK ← this | rcan-py | pip install rcan — RCANMessage, RobotURI, ConfidenceGate, HiTLGate, AuditChain, RegistryClient. |
| TypeScript SDK | rcan-ts | npm install rcan-ts — same API surface for Node + browser. |
| Registry | Robot Registry Foundation | Permanent RRN identities. Public resolver at /r/<rrn>. Like ICANN for robots. |
| Reference runtime | OpenCastor | Open-source robot runtime — connects LLM brains to hardware bodies. One implementation of RCAN. |
Install
pip install rcan
Optional extras:
pip install rcan[http] # httpx for registry client
pip install rcan[crypto] # cryptography for Ed25519 signing
pip install rcan[all] # everything
Quick Start
from rcan import RobotURI, RCANMessage, ConfidenceGate
from rcan.audit import AuditChain, CommitmentRecord
from rcan.replay import ReplayCache
from rcan.qos import QoSLevel
from rcan.consent import ConsentRequest
# 1. Address a robot
uri = RobotURI.build(manufacturer="acme", model="arm", version="v2", device_id="unit-001")
# rcan://registry.rcan.dev/acme/arm/v2/unit-001
# 2. Gate on AI confidence before acting
gate = ConfidenceGate(threshold=0.8)
confidence = 0.91
if gate.allows(confidence):
msg = RCANMessage(
cmd="move_forward",
target=uri,
params={"distance_m": 1.0},
confidence=confidence,
model_identity="gemini-2.5-flash",
)
# 3. Replay attack prevention — deduplicate incoming messages
cache = ReplayCache(window_seconds=300)
if cache.is_replay(msg.msg_id):
raise ValueError("Replay attack detected")
cache.record(msg.msg_id)
# 4. Tamper-evident audit chain — every action sealed and linked
chain = AuditChain(secret="your-hmac-secret")
chain.append(CommitmentRecord(
action="move_forward",
robot_uri=str(uri),
confidence=confidence,
model_identity="gemini-2.5-flash",
safety_approved=True,
))
chain.verify_all() # raises if chain is tampered
# 5. Request human consent before a sensitive action
req = ConsentRequest(
action="open_gripper",
robot_uri=str(uri),
requester="operator-alice",
scope="control",
)
print(req.to_json())
What's in v0.6.0
| Module | Description |
|---|---|
rcan.message |
Core RCANMessage envelope with all v1.6 fields |
rcan.address |
RobotURI — parse, build, and validate RCAN robot addresses |
rcan.audit |
AuditChain + CommitmentRecord — tamper-evident HMAC-chained logs |
rcan.gates |
ConfidenceGate, HiTLGate — safety gates for AI-driven actions |
rcan.replay |
ReplayCache — sliding-window replay attack prevention (GAP-03) |
rcan.clock |
ClockSyncStatus — NTP clock sync verification (GAP-04) |
rcan.qos |
QoSLevel — FIRE_AND_FORGET / ACKNOWLEDGED / EXACTLY_ONCE (GAP-11) |
rcan.consent |
Consent wire protocol — request/grant/deny (GAP-05) |
rcan.revocation |
Robot identity revocation with TTL cache (GAP-02) |
rcan.training_consent |
Training data consent, GDPR/EU AI Act Annex III §5 (GAP-10) |
rcan.delegation |
Command delegation chain, max 4 hops, Ed25519-signed (GAP-01) |
rcan.offline |
Offline operation mode — ESTOP always allowed (GAP-06) |
rcan.fault |
FaultCode structured fault taxonomy (GAP-20) |
rcan.federation |
Federated consent — cross-registry trust, DNS discovery (GAP-16) |
rcan.transport |
Constrained transports — compact CBOR, 32-byte ESTOP minimal, BLE (GAP-17) |
rcan.multimodal |
Multi-modal payloads — inline/ref media, streaming (GAP-18) |
rcan.identity |
Level of Assurance — LoA policies, JWT parsing (GAP-14) |
rcan.keys |
Key rotation with JWKS-compatible KeyStore (GAP-09) |
rcan.config_update |
CONFIG_UPDATE protocol with safety scope enforcement (GAP-07) |
rcan.node |
NodeClient — resolve RRNs across federated registry nodes (§17) |
rcan.validate |
L1/L2/L3 conformance validation for configs, messages, URIs |
Protocol 66 Compliance
Protocol 66 is RCAN's safety layer. Key invariants enforced by this SDK:
- ESTOP always delivered —
QoSLevel.EXACTLY_ONCE, never blocked by QoS downgrade - Local safety wins —
offlinemodule enforces local limits even without cloud connectivity - Confidence gates run locally —
ConfidenceGatenever makes a network call - Audit chain required —
AuditChain.verify_all()before executing any flagged command
from rcan.offline import OfflineMode
from rcan.safety import SafetyInvariant
mode = OfflineMode()
mode.assert_estop_reachable() # raises if ESTOP path is blocked
CLI
# Validate a robot config (L1/L2/L3 conformance)
rcan-validate config myrobot.rcan.yaml
# Validate a RCAN message
rcan-validate message command.json
# Verify an audit chain
rcan-validate audit audit.jsonl
# Validate a Robot URI
rcan-validate uri 'rcan://registry.rcan.dev/acme/arm/v2/unit-001'
# Run all checks
rcan-validate all myrobot.rcan.yaml
Spec Compliance
Implements the RCAN protocol — 587 tests, 0 skipped. See the live compatibility matrix for the pinned version this SDK targets.
Covered sections: §1 Robot URI · §2 RBAC · §3 Message Format · §5 Authentication · §5.3 QoS · §6 Safety Invariants · §8.3 Replay Prevention · §8.4 Clock Sync · §8.5 Sender Type · §8.6 Key Lifecycle · §8.7 Level of Assurance · §9 Capabilities · §11 Behavior Scripts · §12 Command Delegation · §13 Revocation · §14 Offline Mode · §16 AI Accountability · §17 Distributed Registry · §18 Federation · §19 Constrained Transport · §21 Registry Integration
Physical assurance (RCAN Appendix C, informative)
rcan.assurance ports the reference verifier from RCAN Appendix C, the
Physical Assurance Profile. The appendix is informative and these helpers are
optional: nothing in RCAN requires them, and using them changes no conformance
level. The appendix is proposed in
rcan-spec#221
and has not been merged.
import json
from rcan.assurance import verify_chain, audit_authority, replay_against_envelope
chain = json.load(open("gate-decisions.json")) # list of gate_decision records
envelope = json.load(open("envelope.json"))
findings = [
*verify_chain(chain, expected_head=None), # pass an anchored head if you hold one
*audit_authority(chain, envelope),
*replay_against_envelope(chain, envelope),
]
for f in findings:
print(f.seq, f.code, f.detail)
What these helpers do and do not tell you:
- They verify evidence, not robots. They check that a
gate_decisionlog is internally consistent, that executed authority-gated commands name a principal and an authority, and that applied commands sit inside the declared envelope. A passing chain says nothing about whether the machine behaved as logged. - Without an anchored head,
verify_chaincannot detect records removed from the end of a chain. Passexpected_headwhen you hold the last hash from somewhere the log writer cannot rewrite. replay_against_envelopejudges onlylinear_mps,angular_radpsand a 2Dtarget. Any other applied field is reported asUNCHECKED_FIELDS, never silently passed.- Physical assurance levels A1 to A3 are a separate axis from RCAN protocol conformance levels L1 to L4. An L3 robot can be A1, and neither level implies the other. An A-level is self-declared unless third-party evidence accompanies it.
Conformance is not certification.
Ecosystem
| Package | Version | Purpose |
|---|---|---|
| rcan-py (this) | v2.0.0 | Python SDK |
| rcan-ts | v2.0.0 | TypeScript SDK |
| rcan-spec | v3.0 | Protocol spec |
| ROBOT.md | v0.1.3 | Single-file robot manifest |
| OpenCastor | v2026.3.17.1 | Robot runtime (reference impl) |
| RRF | v1.6.0 | Robot identity registry |
| Fleet UI | live | Web fleet dashboard |
| Docs | live | Runtime reference, RCAN, API |
Contributing
Issues and PRs welcome at github.com/RobotRegistryFoundation/rcan-py.
Spec discussions: github.com/RobotRegistryFoundation/rcan-spec/issues
License
MIT
Stewarded by the Robot Registry Foundation. RCAN is an open standard; issues and PRs welcome. See CONTRIBUTING.md.
Metadata
Release files for rcan 3.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| rcan-3.6.0.tar.gz | 191.8 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| rcan-3.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 324.5 kB
Release files / rcan-3.6.0.tar.gz
| Download URL | rcan-3.6.0.tar.gz |
|---|---|
| Size | 191.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d199afa6c2f0a3899360858130e020b09ab245282e79f8f66006a9360c6abcae
|
|
BLAKE2b-256 checksum How to use checksums |
5a6b6975f2344393517219c64b7efa1bfb1de0cee13dc510453b35cba0a85310
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|
Release files / rcan-3.6.0-py3-none-any.whl
| Download URL | rcan-3.6.0-py3-none-any.whl |
|---|---|
| Size | 132.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bb0b11fbcd5929a33777009aa1ef8a487e8783dfbe51297cf29ab29b9575d3ed
|
|
BLAKE2b-256 checksum How to use checksums |
5bbd5c067606414401675e8654c527f2bf89f9856dee249da523514864a95f90
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.13.5
|