guides
Intended Documentation
Physical-AI Quickstart
From sign-up to your first verified Authority Token for a physical action — register an actor, classify a structured goal, snapshot state, and mint a short-lived RS256 token.
Physical-AI Quickstart#
No robot required. You will register an actor on your fleet roster, classify a structured agent goal, mint a short-lived Authority Token bound to that action, and inspect the wire format your edge / firmware team integrates against.
What you will have at the end#
- An Intended tenant and API key (the same key as the digital flow).
- A registered actor — token issuance refuses any
actorIdentitynot on the roster. - Your first Open Intent (OI) classification on a structured goal.
- Your first physical Authority Token — an RS256 JWT whose lifetime is the action's
deadlineMs.
Prerequisites#
curl, or Python 3.10+, or ROS2 Humble+. A robot is not required — the example uses a JSON snapshot of work-cell state, so the whole loop runs on a laptop.
ACTOR_IDENTITY should ultimately be the IEEE 802.1AR DevID of your robot. For the demo, any stable string works — but it must be registered before it can be authorized.
1 — Get an API key#
Sign up at console.intended.so/register. If you already have a tenant from the digital flow, the same mrt_live_… / mrt_test_… key works here. Every /v1/physical/* call carries Authorization: Bearer $INTENDED_API_KEY and x-tenant-id: $INTENDED_TENANT_ID.
2 — Register the actor#
Token issuance for an unregistered actor returns 403 actor_not_registered. Register the robot once on your tenant's fleet roster:
actorKind is one of robot, cobot, drone, agv, amr, rov, vehicle, other. The server defaults actorIdentityKind to ieee-802-1ar-devid.
3 — Classify a structured goal#
POST /v1/physical/classify maps a non-text goal to an OI category. It does not mint a token — use it to inspect the classification before requesting authority.
If failClosed is true, no rule matched the goal with enough confidence. Treat that as a denial and transition to your declared safe-default — do not request a token.
4 — Mint an Authority Token#
POST /v1/physical/authority-tokens runs the full loop: classify (if you do not supply oiCode), evaluate policy over physicalState, and — on ALLOW — mint the token. Send an Idempotency-Key so a retry never double-issues.
A successful ALLOW returns:
The token's lifetime is your deadline
The physical token's exp / expiresAtMs is set to issuance time + dagNode.deadlineMs — typically sub-second. This is deliberately tighter than the platform's digital Authority Token (a flat 300s cap): a physical token is meant to authorize this one action within its real-time budget, not a session. Request a fresh token per DAG node.
5 — Try the deny path#
Set safety/emergency_stop to true and re-issue. The default policy denies with 422 policy_denied:
The default policy denies three conditions out of the box: emergency-stop (OI-2901/OI-2902), light-curtain breach (OI-2902), and human-in-cell (OI-2902/OI-2904). Upload your own policy with POST /v1/physical/policy to extend it.
6 — Inspect what happened#
The audit entry for any issued token is retrievable by its jti:
The token itself is an RS256 JWT (aud: "intended-edge-verifier"). Its body carries the physical claims under an intended object:
Verify against the right key — and the right audience
The token signer's public key is served at /.well-known/jwks.json. In dev/sandbox the signer is an ephemeral per-process keypair (it changes on restart), so cache JWKS short and refresh on a kid miss. Also note: tokens mint aud: "intended-edge-verifier", while the shipped intended-ros2 verifier samples default expected_audience="intended-edge". Set your verifier's expected audience to intended-edge-verifier to match what the issuer actually signs.
7 — Map it to your stack#
| Your component | What you do |
|---|---|
| ROS2 agent | Drop in the intended-ros2 package — see ROS2 integration. |
| Industrial PLC (TwinCAT / Studio 5000 / TIA Portal) | Run a non-RT mediator against the HTTP API — see C++ industrial controls. |
| Real-time motion controller (Rust) | The native Rust verifier is roadmap; verify against cloud-cached JWKS today — see Rust safety-critical firmware. |
| ML perception / planning (Python) | Python ML pipelines — same SDK as above. |
| Existing safety PLC + bus | Stays where it is. You implement a PhysicalStateProvider and submit the snapshot; Intended never reads your tags directly. |
Next#
- What is physical AI on Intended — architecture and where we sit.
- Authority API reference — every endpoint, claim, and error.
- Edge-verifier operator guide — the planned deployment and operations model.