Towards the Harness of Embodied Agents

CDemo Execution Logs

The first three logs were collected on the Astribot S1, and the final log on the Unitree G1 with the same harness. Turn counts follow the definition in §3.1. Final responses contain no tool calls and are therefore shown without turn numbers.

C.1Beverage Retrieval

User request. “Bring me a bottle of water and place it on the table.”

Turn 1. Reasoning: The user requests a drink, so the pantry is the next search location. Navigate there before selecting the target bottle.

navigate_to(target="pantry")
Navigation. The robot reaches the pantry.

Turn 2. Reasoning: The navigation result confirms arrival and alignment at the pantry, and the refreshed clearance evidence permits a 0.80 m forward step. Advance to improve the torso-camera view and manipulation distance.

move_base(direction="forward", distance_m=0.80)

Turn 3. Reasoning: The fresh torso view shows no unambiguous plain water bottle but includes several alternative drinks. Query the user rather than treating the navigation anchor as the grasp target.

query_user(
    question="No plain water; which drink should I bring?")
User response. Orange juice.
Each move_base is one turn, decided after the previous completes. Folded runs show the move count and one reasoning summary, here and in the logs that follow.

Turns 4–6. Reasoning summary: The user selects orange juice. Apply two leftward corrections followed by a 0.28 m forward step to bring the selected bottle into the grasp envelope.

Base motions3 moves
move_base(direction="left", distance_m=0.30)
move_base(direction="left", distance_m=0.15)
move_base(direction="forward", distance_m=0.28)

Turn 7. Reasoning: The user response and local alignment establish orange juice as the target, but no reliable object reference is available. Bind it by name, execute the grasp, and verify control.

pick_up(obj="orange juice")
Evaluator. The harness invokes evaluate_run() after the manipulation.Grasp verified. The evaluator marks the pick as successful.
The manipulation calls in these logs run self-terminating Coding-as-Policy backends, so their evaluations take the two terminal states of the contract in §4.2.

Turn 8. Reasoning: The grasp evaluator confirms control of the orange juice. The destination is desk_24; navigate there while retaining the object.

navigate_to(target="desk_24")
Navigation. The robot reaches desk_24 with the drink.

Turns 9–12. Reasoning summary: The navigation result confirms arrival at desk_24 with the drink held. Apply a 0.58 m approach followed by 0.05 m, 0.04 m, and 0.03 m corrections to reach the placement pose.

Base motions4 moves
move_base(direction="forward", distance_m=0.58)
move_base(direction="forward", distance_m=0.05)
move_base(direction="forward", distance_m=0.04)
...

Turn 13. Reasoning: The orange juice remains controlled, the final base correction has completed, and the destination is desk_24. Place the drink there and verify the resulting object state.

place(target="table")
Evaluator. The harness invokes evaluate_run() after the manipulation.Placement verified. The evaluator marks the placement as successful.
Final response. The drink has been delivered.

C.2Power-Bank Search

The user asks for a power bank. The power bank is not visible in the scene graph, and the robot searches the cabinet drawers in order. After finding the power bank in the lower drawer, the robot delivers it.

User request. “The computer is out of power. Find me a power bank and place it on the desk.”

Turn 1. Reasoning: The requested power bank is absent from the visible scene graph. The drawers in cabinet_87 may contain objects outside the current view, so navigate there and inspect them in order.

navigate_to(target="cabinet_87")
Navigation. The robot reaches cabinet_87.

Turns 2–7. Reasoning summary: The navigation result confirms arrival at cabinet_87. Apply a 0.55 m approach, a 0.17 m rightward correction, and four centimeter-scale adjustments to enter the drawer manipulation pose.

Base motions6 moves
move_base(direction="forward", distance_m=0.55)
move_base(direction="right", distance_m=0.17)
move_base(direction="forward", distance_m=0.05)
...

Turn 8. Reasoning: The cabinet is now within manipulation range. Start with the upper drawer and open it to inspect its contents.

open_drawer(drawer_level="higher", container_ref="cabinet_87")
Evaluator. The harness invokes evaluate_run() after the manipulation.Upper drawer opened. The evaluator verifies that the upper drawer opens successfully.

Turn 9. Reasoning: The refreshed head-camera observation shows the upper drawer open and the power bank absent. Close the searched compartment before continuing to avoid leaving an obstruction.

close_drawer(
    drawer_level="higher",
    container_ref="cabinet_87")
Evaluator. The harness invokes evaluate_run() after the manipulation.Upper drawer closed. The closure is verified successfully.

Turn 10. Reasoning: The upper drawer closure is verified. Continue the ordered search by opening the lower drawer and exposing its contents.

open_drawer(drawer_level="lower", container_ref="cabinet_87")
Evaluator. The harness invokes evaluate_run() after the manipulation.Lower drawer opened. The evaluator verifies that the lower drawer opens successfully.

Turn 11. Reasoning: The refreshed head-camera observation shows the power bank inside the open lower drawer, and the gripper is empty. The object is reachable, so pick it and verify control.

pick_up(obj="power bank")
Evaluator. The harness invokes evaluate_run() after the manipulation.Pickup verified. The wrist observation confirms that the power bank is held securely.

Turn 12. Reasoning: The pickup evaluation confirms that the power bank is held, and the updated scene state removes it from the cabinet. Close the lower drawer before leaving the search location.

close_drawer(drawer_level="lower", container_ref="cabinet_87")
Evaluator. The harness invokes evaluate_run() after the manipulation.Lower drawer closed. The cabinet search concludes with both compartments closed.

Turn 13. Reasoning: The power bank is held and both drawers are closed. The destination is desk_96; navigate there while retaining the object.

navigate_to(target="desk_96")
Navigation. The robot reaches desk_96 while holding the power bank.

Turns 14–16. Reasoning summary: The navigation result confirms arrival at the destination with the power bank held. Apply a 0.80 m approach followed by two 0.03 m corrections to enter the surface-placement envelope.

Base motions3 moves
move_base(direction="forward", distance_m=0.80)
move_base(direction="forward", distance_m=0.03)
move_base(direction="forward", distance_m=0.03)

Turn 17. Reasoning: The final base correction has completed, the scene still marks the power bank as held, and the destination is desk_96. Place the object on its surface and verify the result.

place(target="table")
Evaluator. The harness invokes evaluate_run() after the manipulation.Placement verified. The power bank is placed successfully on desk_96.
Final response. The power bank has been delivered.

C.3Desk Cleanup

This episode starts without a user instruction. A standing monitor waits until the workstation is unoccupied while objects remain on the desk.

monitor_scene is an ordinary tool, the standing counterpart of query_user: where query_user waits for the user to answer, monitor_scene waits for the world to change. The agent gives it a natural-language condition, and the call returns once the condition is observed to hold. The returned event then takes the place of a user instruction, giving the task its goal. Only this log uses the tool.

Thea loads the workspace-cleaning rules, identifies an empty orange-juice bottle as trash while leaving the laptop and charging power bank untouched, and sends one non-blocking notification before acting. The robot then drops the bottle into the trash bin, and Thea sends a completion notification.

Turn 1. Reasoning: Keep the desk unchanged while the workstation is occupied. Set up the standing monitor and wait until the workstation is unoccupied while items remain on the desk.

monitor_scene(
    condition="workstation unoccupied and objects on desk")
Monitor event. The user is absent. The desk contains an empty orange-juice bottle, a laptop connected to a power bank, and several other items.

Turn 2. Reasoning: The returned monitor event identifies several desk objects, but visual presence alone does not justify discarding them. Load the workspace-cleaning rules.

load_skill(name="tidy-workspace")
Classification. The confirmed empty bottle is trash. The laptop, charging power bank, and items whose state is uncertain must remain untouched.

Turn 3. Reasoning: The rules and current observation identify only the empty orange-juice bottle as discardable; the remaining items must stay untouched. Notify the user, then begin the cleanup.

notify_user(
    message="I found an empty orange-juice bottle on your
             desk. I will discard it and leave the other
             items untouched.")
Notification. The one-way message is delivered, and execution continues without awaiting a reply.

Turns 4–7. Reasoning summary: The target is fixed and the approach is clear. Advance 0.20 m, tilt the head by 45 degrees to refresh the local evidence, then apply 0.05 m and 0.03 m corrections to bring the bottle into the pickup envelope.

Base motions4 actions
move_base(direction="forward", distance_m=0.20)
tilt_head(pitch_deg=45)
move_base(direction="forward", distance_m=0.05)
...

Turn 8. Reasoning: The refreshed view and incremental alignment place the confirmed empty bottle within reach while the gripper remains empty. Execute the grasp and verify control.

pick_up(obj="empty orange-juice bottle")
Evaluator. The harness invokes evaluate_run() after the manipulation.Pickup verified. The wrist observations show the bottle secured between the gripper fingers.

Turn 9. Reasoning: The grasp evaluator shows the empty bottle secured between the gripper fingers. The disposal destination is trash_can_54; navigate there while retaining the bottle.

navigate_to(target="trash_can_54")
Navigation. The robot reaches trash_can_54 with the bottle.

Turns 10–12. Reasoning summary: The navigation result confirms arrival in the target area, but the bin is not yet centered for release. Apply a 0.55 m approach, a 15-degree left turn, and a final 0.05 m correction to reach the release pose.

Base motions3 moves
move_base(direction="forward", distance_m=0.55)
move_base(direction="turn_left", angle_deg=15)
move_base(direction="forward", distance_m=0.05)

Turn 13. Reasoning: The empty bottle remains held, trash_can_54 is unambiguous, and the final alignment succeeds. Release the bottle into the bin and verify the resulting state.

trash_drop(trash_ref="trash_can_54")
Evaluator. The harness invokes evaluate_run() after the manipulation.Drop verified. The bin opening is centered, both grippers are empty, and no bottle is visible outside the bin.

Turn 14. Reasoning: The drop evaluator confirms that both grippers are empty and no bottle is visible outside the bin, satisfying the cleanup goal. Notify the user that the bottle has been discarded.

notify_user(
    message="The empty orange-juice bottle has been
             discarded.")
Completion notification. The cleanup result is delivered to the user.
Final response. The empty orange-juice bottle has been discarded.

C.4Basket Delivery

The user (Jason) asks for snacks to be brought to friends. The robot packs snacks into a basket, carries it into the living room, walks up to Jason, and hands over the basket.

Routine low-level calls (controller checks, camera refreshes, setup queries, and the locomotion steps inside navigation) are folded and excluded from the turn numbering.
User request. “I am about to meet some friends. Bring some snacks over for them.”

Turn 1. Reasoning: The workspace is ready. Place the snack in the basket and wait for the manipulation to finish before lifting the basket.

pack_snacks()
Packing workflowrepeated controller updates folded
Evaluator. The harness invokes evaluate_run() after the manipulation.Placement verified. The snack is packed in the basket.

Turn 2. Reasoning: Packing is complete. Lift the loaded basket, retract the arm for walking, and prepare it for navigation.

lift_basket()
Evaluator. The harness invokes evaluate_run() after the manipulation.Lift verified. The basket is ready to be carried.

Turn 3. Reasoning: The basket is secured for transport. Follow the doorway route into the living room before selecting a recipient.

navigate_to(living_room)
Navigation. G1 reaches the living room while holding the basket.

Turn 4. Reasoning: The living-room view shows Jason seated in a white shirt and light trousers. Navigate to him while retaining the basket.

navigate_to(Jason)
Navigation. G1 brings Jason into front view while retaining the basket.

Turns 5–8. Reasoning summary: The recipient is now in front but not yet close enough for the handoff. Continue in short increments.

Carry motions4 moves
basket_carry_move(direction="forward", distance_m=3.0)
basket_carry_move(direction="forward", distance_m=1.5)
...
Navigation. Four short forward motions bring G1 close to the seated recipient.

Turn 9. Reasoning: The recipient is close in front of G1, and the basket remains held. Extend the arm to the handoff pose and open the hand, but do not infer transfer from the controller state alone.

hand_over()
Handoff. The right arm extends, and the hand opens successfully.
Evaluator. The harness invokes evaluate_run() after the manipulation.Release verified. The basket is released and rests securely with the recipient.