RAX

An agent explores on a real robot for 2 hours, then runs the skills it learned as code.

We ported and evaluated RAX on a UFactory xArm 6 on two tasks: placing a brick in a tray, and seating one LEGO assembly onto another. The agent first solves each task by interacting with the environment through tool calls, writes and debugs its own controller, then at inference synthesizes learned skills into an executable program with no model in the loop.

RAX generalized from only a few training episodes and remained safe in every deployment run. We observed that every deployment failure was the agent stopping on a safety check it wrote for itself, usually an overly strict one. In all runs the arm never approached a grasp incorrectly, collided, dropped an object, or otherwise exhibited unrecoverable errors in its reasoning.

Zhuojie Kuang

LEGO stacking, 4× speed. The learned controller picks, places, seats the block with 3 presses and lift-tests the connection, with no model calls and no operator help.

More embodiments soon WujiBrainCoAgileXYAMUnitreeUniversal Robots
Setup

1 arm, 3 cameras, MCP tool backend

The agent acts only through tools that control the arm, enforce a workspace, and does perception using all 3 cameras.

The xArm 6 at its table with the tray, a brick and a fixed camera on a stand The G2 gripper with the wrist camera mounted above it

The workcell. Left: the xArm 6 with the tray, brick and a fixed camera. Right: the G2 gripper and wrist RGB-D camera.

Left, right and wrist camera views of the pick and place scene

The agent's 3 views: 2 fixed side cameras and the wrist camera.

RobotUFactory xArm 6, 6-DoF
GripperUFactory G2 parallel gripper, 84 mm maximum opening
Cameras3 Intel RealSense RGB-D: 2 fixed (left, right) and 1 on the wrist, 640 x 480
WorkspaceTCP box checked on every target and along joint paths
AgentGPT-6 Astra (frozen weights) in the RAX harness
Toolsxarm_observe, xarm_move_pose, xarm_move_joints, xarm_gripper, xarm_hold, xarm_pixel_to_position, xarm_status, request_operator
Budget4 hours and 4,000 model calls per session
OperatorResets scenes on request, answers questions in plain text, holds the e-stop

Protocol

01

Solve it manually

The agent drives the arm one tool call at a time until the task succeeds once.

Training
02

Write and repair a controller

The agent distills what worked into reusable code skills, then runs and patches them on scenes the operator resets.

Training
03

Run the executable

The agent synthesizes an executable program from its skill library and runs it on fresh scenes. No model is queried during deployment.

Deployment

Porting RAX from Franka to xArm

RAX was built for a Franka FR3. We ported the RAX backend to xArm 6 with the same 5-method interface; the frontend robot service, audit log, operator channel and agent workflow are unchanged. One challenge we faced during the port: the G2 gripper driver always reports is_grasped: false, so grasps can only be confirmed visually, which the agent figured out during training.

Coding agentthrough the MCP bridge
Agent-written controllerthrough the Python client
Shared Unix socket
Robot serviceserialized calls, audit log, operator requests
xArm backendxArm SDK → xArm 6 + G2
RealSense camera serviceleft, right and wrist RGB-D

The agent and its controller reach the robot through the same socket and checks. Highlighted parts are new for the xArm.

Franka FR3xArm 6
Arm connectionHTTP bridges to PolymetisDirect xArm Python SDK
Cartesian motionRepeated targets with a host-side integral correction loop1 SDK move, then polling the measured pose until it settles
GripperSeparate bridge with grasp feedbackSDK position commands, standard and G2
CamerasZEDIntel RealSense
Task 1

Pick and place

TASK PROMPTPick the cube/brick from the table and place it into the tray using the xArm 6 and UFactory Gripper G2. Use the calibrated RGB-D cameras, verify live wrist depth and fitted grasp geometry before low descent/contact, and keep motions inside the configured workspace.

The full training session, recordings on robot motion only. Manual episodes at 8× speed, trials at 12× and 8× speed, trial 15 at 4× speed. The clock shows live session time.

How the skills evolved

0:02
M1

A manual episode with an upright brick

The agent fits the brick top in wrist depth and descends in stages. Below about 15 cm the brick leaves the wrist camera's depth range; it backs up, refits and finishes in 22 motions.

KeptFit the full geometry at 15 cm before descending; near contact, trust the last fit.
0:17
T1, M2

The operator lays the brick on its side

The first controller finds no upright brick and asks the operator to stand it up, to which the operator responded: “I intentionally laid the brick sideways to test generalization.” The agent measures the 31 x 61 mm footprint by hand and grasps across the narrow side.

KeptClassify the pose from measured height; close across the narrow axis with at least 5 mm of finger overlap.
0:38
T3 to T7

Sharpen perception

Runs stop because the left and wrist cameras disagree on the brick: left depth misses the blue cap. Then the wrist sees only 40% valid depth on the top. Rather than loosen thresholds, the agent adds bounded re-captures, an inspection pose and an RGB fallback where depth is missing.

KeptCompare corresponding surfaces across cameras. Agent decides to do bounded retries only.
1:19
T8 to T12

Occlusion near contact, and an operator who pushes back

Near contact the fingers hide the brick in the side views and stability checks halt the run. The agent keeps its geometric gates and relaxes only the redundant visual ones.

1:34
T13 to T15

Retention from motion, then the first success

With no usable grasp flag, the agent verifies a grasp by checking that the brick rises the expected distance in both side cameras. Trial 15 is the first full autonomous success, in 65 s.

1:47
T16 to T19

The tray becomes an obstacle

With the brick beside the tray, a finger lands on the tray wall. The agent writes a clearance model that tests each finger's swept footprint against the tray outline, tries both grasp axes, and refuses when neither clears.

KeptCheck finger sweeps against the tray before every descent.
2:11

Training paused

Training ends after 19 trials with a 711-line controller and 18 regression tests.

Every training trial

Deployment

The agent synthesized a controller that ran on 18 fresh scenes with no model calls: 6 unassisted successes, mean episode .

None of the 12 failures was a wrong approach. All 9 grasps landed at the planned pose and closed on the brick. Every failure was one of the controller's own checks stopping the run:

  • Stopped after a good grasp (3): the fingers hid the brick in 1 view, or the placed brick rested against the tray wall.
  • Perception checks before contact (5): a missing silhouette, a split color patch, noisy tray depth.
  • Correct refusals (2): no finger sweep cleared the tray wall.
  • Robot fault before the start (2).

Approach accuracy

Every deployment grasp, including those in runs stopped later.

The gripper closed at 30 mm every time, on the brick's narrow side; the long side would read about 61 mm and air below 25 mm. Sideways bricks were grasped within 1.3° of the long axis.

All 6 successful deployment runs, 4× speed, on real time. Click a row to play any run.

Where the time goes

Stage durations of the 6 successful runs.

Task 2

LEGO stacking

TASK PROMPTThere are 2 lego blocks. Stack the yellow and blue one on top of the green and dark blue one, making sure they are interlocking and perfectly aligned.

The full training session, robot motion only. Manual work at 8× speed, trials 2 to 8 at 12× speed, trial 9 at 4× speed.

From aligned to seated

The agent thought the first manual stack was fully seated but the operator found it only partly seated. With no force sensing and no view of the seam, the agent seated it through presses guided by operator feedback, then compiled them into its learned skills.

The first manual stack: the yellow and blue assembly sits on the green and dark blue one, aligned but not pressed fully down
The first manual stack. Aligned, but only partly seated.
OPERATOR
Although the cubes were perfectly aligned, they were only partially interlocking.
AGENT
Closed-gripper press at the center, down to 120 mm in 1 to 2 mm steps. The top drops about 2.8 mm.
OPERATOR
It did better than episode 1, but there's still a gap on one side.
AGENT
A second press to 116 mm, with no change. Asks where the gap is rather than pressing harder.
OPERATOR
There is still a very small gap. It is on the right-camera side, toward the robot.
AGENT
Presses 6 mm off center, toward the robot.
OPERATOR
The gap is almost completely gone but still there, on the left side of the cube.
AGENT
Presses 6 mm off center, toward that side.
OPERATOR
Both sides are now fully seated. Well done.
CONTROLLER
Writes seat(): 3 bounded presses, at the center and at 2 offsets of 6 mm, never below 116 mm, then a height gate and a lift test.

The manual seating sequence above, 8× speed.

Other things it learned along the way

  • Studs, not edges, set the yaw: 4 Hough circles fit to a 16 mm square, instead of unstable depth edges.
  • Wrist calibration drifts with yaw: rotate at clear height, then re-localize before targeting.
  • Distrust bad depth: the right camera's depth was off by about 0.2 m, so it is used for RGB checks only.
  • Use the unoccluded view: checks accept whichever fixed camera can still see the base.

Every training trial

Evaluation after training

The controller was frozen after training. No evaluation run failed because of a bad motion: every grasp and placement was on target.

Comparison

RAX vs. Astra as the policy

The baseline is the same model, GPT-6 Astra, acting as the policy: it chooses every tool call from the latest observation. RAX uses the model only in training and deploys the synthesized Python program it wrote.

AXIS 1Execution speed on LEGO stacking

RAX controller

Astra as the policy

Both on the real episode clock.
faster per episode
RAX
Astra
model calls per episode
RAX
Astra

RAX: full trial 9, from first motion to the verified lift test. Astra: manual episode 1, which ended with the blocks aligned but only partly seated.

AXIS 2Behaviors the controller carries

Each behavior was learned from a training failure and now runs as code in every episode. Clips are from the controller's own runs.

SUMMARY

AXIS 3Success rate influenced by learned skills

On LEGO stacking, each success criterion depends on a learned skill. Alignment comes from reading yaw from the studs, which both policies learned, so both place the block aligned. Seating comes from the 3 bounded presses, which only RAX learned: Astra's lift test passed on a partly seated stack, so it could not tell the difference.

Astra as the policy

The Astra baseline's stack: aligned on the base but not pressed fully down

Aligned, but the top block is not fully seated.

RAX controller

3 bounded presses, 2× speed. Operator-confirmed fully seated.

Aligned on the base
Fully seated

RAX: all 5 placements across training and evaluation; fully seated is out of the 3 the operator inspected, since the 2 evaluation placements were not inspected. Astra: 5 attempts as the policy. End-to-end unattended success was 1 of 9 training trials and 0 of 5 evaluations.

Credits

RAX

This project is a fork of RAX from Scaling Online Exploration for Robot Agents. The method, the agent harness and the robot service are the original authors' work. We add a branch containing xArm 6 port, Wuji Hand 2 port, and our evals.

Runhan Huang, Xiangcheng Zhang, Haoyu Chen, Yitong Li, Yen-Jen Wang, Bohan Lyu, Haotian Ye, Chuye Hong, Yixuan Wang, Chloe Su, Haoyu Xiong, Yangzhen Wu, Enze Xie, Travis Manderson, Stefano Ermon, Pieter Abbeel, Antonio Torralba, Dawn Song, Weirui Ye, Yilun Du

BIBTEX

@article{huang2026scaling,
  title={Scaling Online Exploration for Robot Agents},
  author={Huang, Runhan and Zhang, Xiangcheng and Chen, Haoyu and Li, Yitong and Wang, Yen-Jen and Lyu, Bohan and Ye, Haotian and Hong, Chuye and Wang, Yixuan and Su, Chloe and others},
  journal={arXiv preprint arXiv:2610.22496},
  year={2026}
}