By nghxni

Technical article

The robot AI approval gate: from edge inference candidate to one-shot submit

RobotEdgeInferenceSrv and the robot AI approval API show how an AI-proposed robot command reaches dispatch only after policy validation, signed provider approval, and a one-shot submit — with every bypass path failing closed.

AI output is a proposal, not a command

Edge models can suggest high-level robot commands, but a suggestion must never reach dispatch directly. LightESB-Camel treats AI output as a candidate: it cannot declare its own source identity, risk level, policy version, or approval result, and the normal command API rejects AI-reserved command IDs with 422 ROBOT_AI_APPROVAL_REQUIRED.

From candidate to persisted decision

Every step is explicit; missing or incomplete configuration fails closed.

Policy validation

Candidates are checked against allowlisted commands, confidence thresholds, freshness windows, identity binding, anti-replay, and shared safety policies. Failures return rejected with a specific error code.

Explicit enablement

The capability is off by default. Enabling it requires a global HMAC provider configuration plus an approval switch in the service route, and secrets are injected through environment variables — never written to files, logs, or responses.

Persisted decision

Safe candidates become server-side validation decisions with an expiry derived from inference freshness, command TTL, and the configured maximum decision age. A pending decision is not an approval.

HMAC approval callback

The configured provider signs callbacks with HMAC-SHA256 over the raw request body. Verified callbacks move the decision to approved or rejected; retries are idempotent, and same-ID different-body replays return 409.

One-shot submit through the decision-only path

Submitting an approved decision takes no command payload. The server restores the candidate from the persisted decision, re-verifies the digest, denylist, capability, and current safety policy, then writes command, audit, outbox, state snapshot, and the consumed binding in one transaction — any failure rolls everything back.

The CLI mirrors this boundary: it can query a decision and submit it with --yes, but it cannot approve or reject, never reads candidate command files, and never stores the HMAC secret. Expired decisions, replayed events, and double consumption all fail closed.

A mock boundary you can verify offline

RobotEdgeInferenceSrv ships as a direct: + mock: route package with server.running=false and no HTTP, MQTT, or gRPC ingress. Post robot-edge-inference.v1 JSON to direct:robot-edge-inference-mock and read decisions from mock:robotEdgeInferenceDecisionSink.

The fixed ingress profile is not production authentication, the in-memory replay registry covers a single instance only, and the HMAC provider contract still needs field verification against a real approval platform. The mock package exists to prove the gate semantics before that integration starts.

Try it yourself

  1. Copy example/routes/RobotEdgeInferenceSrv into the runtime service directory and keep server.running=false.
  2. Post a robot-edge-inference.v1 candidate to direct:robot-edge-inference-mock and read the decision from mock:robotEdgeInferenceDecisionSink.
  3. Confirm safe candidates return pending_approval with submittable=false, while stale, low-confidence, identity-mismatched, or replayed candidates return rejected.
  4. Enable the HMAC provider and the service approval switch, send a signed approval callback, then query and submit the decision with lightesb robot inference submit --yes.
AI approval APIEdge inference mock guide