- The dashboard: in Simulate → Agent, describe the task and any limit, then select Plan. Check the robot, controller and limits before you execute. Cancelling stops only that run.
- Python:
cw.agents.control, shown step by step below. - Your own AI tools: the MCP server exposes the same calls to Claude Code, Cursor and any MCP client (see below).
The four calls
cw.control is an alias for cw.agents.control. All four calls wrap REST endpoints. Failures raise CyberwaveAPIError with a Failed to ... prefix.
Walk through it
1
Get the environment and twin IDs
Every call takes the environment UUID. Get it from a twin you already have:
2
See what the twins can do
mode, surfaces are evaluated as live.3
Ask for a plan
plan() never executes anything. Read warnings and missing_requirements before you go on. dispatchable_actions holds the actions you can send. Each one is a dict with a kind, a target_twin_uuid and a payload.4
Have a human approve one action
5
Dispatch it and wait
wait() needs the twin UUID because the status endpoint is scoped to the twin.Modes
Pass the samemode to surfaces, plan and dispatch. A plan made for simulation is not a plan for hardware: plan again when you switch.
A MuJoCo simulation is a billable cloud instance, about 0.6 credits per hour. Start one with
sim = cw.environments.simulations.start(env_uuid, backend="mujoco", duration=300) and call sim.stop() when you are done. See credits.Safety rules
- One bounded action per dispatch. One pose, one joint target, one navigation goal, or one stop.
- Simulation first. Run the same instruction in simulation, check the result, then plan again in
live. - Before a live dispatch, make sure that: the request really is for physical execution, exactly one physical twin is targeted, the twin’s edge device and telemetry are current, and a stop is available.
- Don’t retry blindly. If
dispatch()orwait()times out or returns an unclear status, don’t resend the motion. Read the twin’s state, send a stop if it is safe, and ask the operator. - Keep a human controller one click away. See safety and takeover.
cw.actions.wait() returns when the action reaches completed, failed, cancelled or blocked. With the default raise_on_failure=True, any status other than completed raises RuntimeError. If no terminal status arrives within timeout seconds, it raises TimeoutError. A single failed status poll does not end the wait.
Choosing the model and the controller
plan() accepts optional arguments to steer the agent:
Skip the LLM: resolve a route directly
When you already know which control you want, skip the language step.options() lists the environment’s control routes and action specs. resolve_route() turns one route and its inputs into a plan, without executing it. Dispatch its dispatchable_actions exactly as above.
Automate it instead
For standing behavior, such as “inspect every pallet and alert me if one is damaged”, use the workflow assistant. It drafts a workflow that runs on its own instead of a single action.From your AI tools (MCP)
The same flow is available to Claude Code, Cursor and any MCP client, with no code:cw_plan_control_action only plans. The assistant must call cw_dispatch_control_action with one explicit action. If the environment’s control-plane access is set to workflows only, the MCP server refuses direct dispatch with CONTROL_PLANE_POLICY_DENIED. The Claude skill applies the safety rules above before any live dispatch. Set it up with the MCP server guide.
Want your own LLM in the loop instead? The natural-language SO-101 agent calls Claude directly with a camera frame, gets a JSON motion plan, and runs it with the SDK.
Common errors
Next steps
AI agents
The environment assistant, the control agent and the workflow assistant.
Ways to control a robot
Where the agent fits next to manual input, skills, workflows and learned policies.
Workflow assistant
Turn a recurring task into a workflow from one sentence.
MCP server
Give Claude Code or Cursor the same planning and dispatch tools.