We read the code agent's cells on every benchmark, in solved and failed episodes, and counted what they do
over all 11,145 cells of the 700 episodes. Four kinds of cells keep coming back, and none of them fits in
one tool call. Each example is a real cell, exactly as the model wrote it.
Guarded chains
19% of cells · 45% on LIBERO-PRO
Several primitives in a row, each run only if the one before worked: move above the bowl, grasp with the
VLA policy only if the move arrived and the task is not done, and look only if it is still not done.
With tool calling, each link of the chain is an LLM call.
assert bowl.found and plate.found
bowl_xy = np.array(bowl.world_xyz[:2])
plate_xyz = np.array(plate.world_xyz)
table_z = robo.back_project(837,660).world_xyz[2]
prepose = [float(bowl_xy[0]),float(bowl_xy[1]),table_z+0.22]
approach = robo.move_to(prepose,gripper=robo.OPEN)
print('APPROACH',approach)
if approach.reached and not robo.done:
picked = robo.pi0_pick('pick up the black bowl between the plate and the ramekin', max_chunks=20)
print('PICK',picked)
print('STATE',robo.state())
if not robo.done:
robo.show('agentview')
robo.show('wrist')
Cell 2 · LIBERO-PRO, spatial swap, task 0, seed 0
Retries
8% of cells · 18% on RoboCasa365 atomic
Where a VLA policy may stop short of the goal, the cell runs it again until the task reports success.
With tool calling, every retry is a round trip that brings back three camera images.
print(robo.task)
print(robo.success_criteria())
for attempt in range(3):
result = robo.rldx_arm()
print(result)
print(robo.state())
if robo.done or result.status != 'cap':
break
if not robo.done:
robo.show('agentview')
robo.show('wrist')
Cell 1 · RoboCasa365 atomic, CloseToasterOvenDoor, seed 1
Perception of its own
30% of cells compute with NumPy
The cell reads a camera's image and point cloud as arrays and locates objects itself: a colour mask for
a block, the points above a height for its top, their principal axis for its orientation, and from that
the yaw of the grasp. A tool-calling agent gets only what its tools compute.
mask=red&(rows<92)&(cols>98)&(cols<165)&(world[...,2]>0.745)
points=world[mask]
upper=points[points[:,2]>0.794]
mean_xy=np.mean(upper[:,:2],axis=0)
eigenvalues,eigenvectors=np.linalg.eigh(np.cov(upper[:,:2].T))
long_axis=eigenvectors[:,1]
if long_axis[1]<0: long_axis=-long_axis
short_axis=np.array([long_axis[1],-long_axis[0]])
projection_long=upper[:,:2]@long_axis
projection_short=upper[:,:2]@short_axis
block_center=long_axis*((np.min(projection_long)+np.max(projection_long))/2)+short_axis*((np.min(projection_short)+np.max(projection_short))/2)
print('flat centre',block_center,'long axis',long_axis,'extents',np.ptp(projection_long),np.ptp(projection_short))
left_grasp_xy=block_center+0.045*long_axis
right_grasp_xy=block_center-0.05*long_axis
yaw=math.atan2(long_axis[1],long_axis[0])
q_down=np.array([math.cos(yaw/2)/math.sqrt(2),-math.sin(yaw/2)/math.sqrt(2),math.cos(yaw/2)/math.sqrt(2),math.sin(yaw/2)/math.sqrt(2)])
print('grasp',left_grasp_xy,'receive',right_grasp_xy,'quat',q_down)
safe=np.array(robo.state().left.eef_pos);safe[2]=1.03
if checked_move('left',safe,quat=robo.state().left.eef_quat,substeps=20):
waypoint=np.array([left_grasp_xy[0],0.015,1.03])
if checked_move('left',waypoint,quat=q_down,substeps=25):
print(robo.move_to('left',[left_grasp_xy[0],left_grasp_xy[1],0.97],quat=q_down,substeps=25))
print(robo.state().left)
robo.show('head')
Cell 5 · RoboTwin 2.0 without the VLA policy, handover block, seed 100003.
checked_move is a helper the agent defined in an earlier cell.
Skills of its own
2% of cells define a helper · 7% reuse one
The agent writes a descent that moves down in 8 mm steps and stops as soon as a step does not reach
its target, stops going down, or drifts sideways, and reuses it in its next cell. Helpers like this are
how it grasps without a VLA policy.
def lower_guarded(arm_name, target_tcp_z):
initial=robo.state().arm(arm_name)
target=np.array(initial.eef_pos)
final_eef_z=target_tcp_z-0.12*initial.approach[2]
while target[2]>final_eef_z+0.001 and not robo.done:
before=robo.state().arm(arm_name)
target[2]=max(final_eef_z,target[2]-0.008)
result=robo.move_to(arm_name,target,substeps=8)
after=robo.state().arm(arm_name)
print('descent',result.reached,tuple(round(v,4) for v in after.tcp_pos))
if result.terminated or not result.planned or not result.reached or after.eef_pos[2]>=before.eef_pos[2]-0.001 or np.linalg.norm(np.array(after.eef_pos[:2])-target[:2])>0.01:
print('stop',result)
break
lower_guarded('right',0.800)
robo.show('right_wrist')
robo.show('head')
Cell 7 · RoboTwin 2.0, place object stand, seed 100002
It also chooses when to look: 84% of cells ask for a camera image,
and 20% look only if the task is not yet done.