Preview. Theservo.connectAPI is currently in developer preview and not yet shipped in general availability. Early feedback and testing are welcome. Code samples on this page importconnect/camera/inspect/gym_stepexplicitly fromservo.universal— they don’t yet resolve asservo.connectetc.
The Connection Pattern
Every VLA policy operates on a simple principle: it consumes observations (camera feeds, joint states) and outputs actions (target joint positions or velocities).servo.connect() binds these inputs and outputs in a few lines of Python:
servo daemon), camera frame capture, hardware video encoding,
and network transport automatically.
Discovering Model Contracts
Different VLA models expect different inputs and outputs. The exact contract is resolved for a hosted checkpoint and registered robot together: a model family can support several embodiments with different sensors. Servo’s built-in local development profile forallenai/MolmoAct2-BimanualYAM uses the top, left, right, and state observation slots.
Before writing integration code, inspect the server-resolved contract in Python:
1. Python inspection (servo.inspect)
The contract is a property of the (model, robot) pairing, not the model alone, so
robot is required — pass a registered robot name (same resolution as connect(robot=...)):
robot.check(policy) to
validate the complete live path.
2. Immediate preflight error detection
For the exact built-in MolmoAct2 development profile,servo.connect() checks the observed slot
names immediately at startup. A missing slot or typo (such as "front" instead of "top") fails
before a control loop starts:
3. Static type checking & IDE autocomplete
The Servo SDK providesTypedDict definitions so your IDE (VS Code, PyCharm) can autocomplete slot names and flag errors with static type checkers like mypy or pyright:
connect() does
not infer a model-specific TypedDict from a string literal.
Supplying Observations (observe)
The observe argument accepts several flexible formats depending on your hardware and software stack:
Option A: Dedicated hardware camera handles
For USB and RealSense cameras, useservo.camera(serial="..."). Servo opens cameras using zero-copy DMA-BUF streaming directly into hardware video encoders:
Option B: Python callable functions
Pass any non-blocking callable returning a NumPy array or PyTorch tensor:- Images:
(H, W, 3)uint8RGB NumPy arrays. (If OpenCV outputs BGR, passservo.camera(..., color_space="bgr")or convert withcv2.cvtColor). - Joint States: 1D vector
(N,)float32in radians for revolute joints, meters for prismatic joints.
Option C: Unified observation method (Simulators & existing environments)
If you already have a custom driver or simulation environment with an atomic observation function, pass that function directly:Option D: ROS 2 topic strings
If your robot runs on ROS 2, pass your active node and topic names directly:sensor_msgs/Image, sensor_msgs/JointState) and publishes commands.
Commanding Motor Actuators (act)
On each control cycle (e.g. 30 Hz), Servo passes the target action array (e.g. (14,) float32) to your act callable:
Return semantics
Wrapping existing Gym environments
If wrapping a standard Gymenv.step method, use servo.gym_step to cleanly handle step tuples:
Built-in Safety: Zero-velocity hold on fault
When controlling physical hardware, software errors must never cause runaway motor movements. If youract function raises an exception (such as motor overcurrent, joint limit reached, bus timeout, or E-stop trigger):
- Active Zero-Velocity Hold: Servo catches the exception immediately and commands actuators to lock position or hold zero velocity.
- Telemetry Preservation: All video frames, network round-trip traces, and joint timestamps leading up to the exact moment of failure are flushed and preserved.
- Structured Reporting:
session.run()exits safely and returns aRunReportwithreport.status = "fault"andreport.error = str(exception).
Running Episodes & Controlling Motion
Executing an episode (session.run)
session.run() executes a bounded autonomous rollout and returns a RunReport:
until=/on_step= are only implemented for mock=True sessions
today — passing either to a real (non-mock) run raises rather than silently no-op’ing, since
the real chunked control loop has no per-step hook or early-stop predicate yet (only a coarser
on_chunk= via robot.run()). report.dataset_path is also always None on a real run today:
a bare connect(model, robot=...) binding has no deployment to record episodes against, unlike
deployment.policy()/fleet.policy() — see ROBOT_INTEGRATION_SPEC.md’s “Known limitation” note.
Non-blocking camera preview
To display a live camera feed in a local OpenCV window or web viewer without slowing down the 30 Hz control loop:Pausing and resuming motion
If an obstacle appears or a human enters the workcell:Direct Functional Control Loop (servo.Policy)
If your system already manages its own custom while loop (for custom safety filters, low-level trajectory smoothing, or custom step logging), use servo.Policy:
policy(...) returns the first row of the chunk the model returned. It does not buffer or prefetch — every call is one real network round trip — so call it no faster than your model’s round-trip allows, or add your own buffering for a tighter loop.
Remote Operations (session.listen)
In automated workcells and production lines, the robot script often runs continuously on the cell IPC while tasks are triggered remotely by a central scheduler, web console, or CI script:
Zero-Motion Preflight (servo check-rig)
Before powering on robot motors, run zero-motion preflight against your integration script:
How Servo Manages Streaming Under the Hood
Servo is designed to give you smooth, stutter-free 30 Hz control even when connecting to remote cloud GPUs over the internet:- Local Background Daemon (
servo daemon): Decouples your robot control loop from network traffic and video encoding. Video compression happens on hardware silicon without consuming CPU cycles needed by your motor drivers. - Pipelined Action Prefetching: VLA models predict chunks of future actions (e.g. 30 steps ahead). While your robot executes step 15, Servo captures the next observation and prefetches the next action chunk from the cloud. When step 30 finishes, step 31 is already waiting—eliminating boundary pauses.
- Smooth Teleoperation Blending: When transitioning between autonomous policy control and human gamepad teleoperation, Servo applies a 50 ms velocity blend to eliminate sudden motion jolts and protect robot gearboxes.