Skip to main content
The control agent turns a request like “move the Go2 to waypoint A” or “run the pick skill on the SO-101” into concrete actions. It only proposes actions the twin can actually perform: each twin exposes control surfaces, derived from its metadata, that list the controls it supports. Nothing moves until a person approves one action. Use it from:
  • 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 agent plans in the cloud. The action runs wherever the twin runs: in simulation, or on the real robot through its edge device.

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

Surfaces are derived from each twin’s metadata. If a twin shows no available controls, the agent has nothing to plan with. Fix the twin’s controller setup first. When you omit 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

Dispatch one action at a time. Check its result, and the twin’s measured state, before you send the next one. wait() needs the twin UUID because the status endpoint is scoped to the twin.

Modes

Pass the same mode 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

Planning never authorizes motion. confirmed defaults to False on dispatch(). Set it to True only after a person (or a check you trust) has approved that specific action.
  • 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() or wait() 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.
If the resolved plan reports missing setup, fill in only the fields it asks for, then resolve again.

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.