Run a real robot Shift.
Use the console to create a Teleoperator and register a robot. The robot receives one credential. Send that credential only from the robot adapter.
Four objects
Teleoperator. A persistent named worker with one Supervisor brain, instructions, allowed skills, Handoff rules, and immutable revisions.
Robot. A registered machine and adapter with a local safe hold, watchdog, and local control authority.
Shift. One Teleoperator assigned to one connected robot for bounded work. This is the live and billing object.
Handoff. A transfer of responsibility for the next decision between the Operator, Supervisor, and human. Safety authority never transfers.
1. Register in the console
Create a Teleoperator, select one of Factor's six brains, and list the skills it may call. Then connect a robot. Factor shows the robot token once. Store it on the robot, not in browser code.
2. Send a heartbeat
curl https://factor.ac/v1/factor/robots/ROBOT_ID/heartbeat \
-H "Authorization: Bearer $FACTOR_ROBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"ready","capabilities":{"camera":true}}'The robot is connected while its authenticated heartbeat is less than two minutes old. A Shift cannot start on stale connectivity.
3. Ask the Teleoperator
curl https://factor.ac/v1/factor/shifts/SHIFT_ID/supervise \
-H "Authorization: Bearer $FACTOR_ROBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"robot_id":"ROBOT_ID",
"instruction":"Clear the blocked pickup and continue",
"state":"safe hold; gripper open; tote visible",
"images":["data:image/jpeg;base64,..."]
}'The response is a bounded Supervisor decision under the exact brain and Teleoperator revision pinned when the Shift started. The local stack decides whether to execute any skill call.
4. Record evidence
curl https://factor.ac/v1/factor/shifts/SHIFT_ID/events \
-H "Authorization: Bearer $FACTOR_ROBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"robot_id":"ROBOT_ID",
"kind":"local_rejection",
"payload":{"skill":"retry_grasp","reason":"force limit"}
}'Valid kinds are task, observation, decision, action, local_rejection, outcome, and note. Factor never invents an outcome.
5. Hand off
Calling /supervise records an immediate Operator-to-Supervisor transfer. When the onboard Operator takes the next decision again, post a Supervisor-to-Operator Handoff. AI-to-AI transfers resolve immediately and stay billable. Human transfers remain open until a person resolves them in the console.
curl https://factor.ac/v1/factor/shifts/SHIFT_ID/handoffs \
-H "Authorization: Bearer $FACTOR_ROBOT_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"robot_id":"ROBOT_ID",
"from":"supervisor",
"to":"human",
"reason":"Occluded grasp after two bounded retries",
"safe_hold":true,
"robot_state":{"mode":"safe_hold"}
}'A human Handoff requires explicit safe-hold confirmation. It pauses Supervisor inference and the Factor robot-hour meter until resolved in the console.
Control boundary
Factor owns task-level reasoning and Handoff state. The customer's onboard executor owns transforms, rate limits, collision checks, reflexes, watchdogs, emergency stops, safety, and actuators. A cloud response is never direct motor authority.