Understanding Agentic Robotics from a System Perspective

The system around the model decides much of what an agentic robot can do: the three properties it should have, and the two design choices that shape them.

Vision-language models are now good at spatial understanding, reasoning, and tool use: Gemini 4 Argon (Google, 2026), GPT-6 Astra in Astranomy (NVIDIA, 2026), and Agent as Policy (Jia et al., 2026), which runs coding agents directly as robot policies, all manipulate objects from instructions.

End-to-end policy

A model maps each observation directly to an action.

ObservationPolicyone forward passAction

Model + program execution

A model writes programs; a tool call is the one-line case.

run coderesultsObservationVLMwrites a programActiongrasp(cup)tool callingfor o in find("cup"): grasp(o) if not holding(o): regrasp(o) place(o, "tray")code as policy
Two ways to put a large model in the robot loop: an end-to-end policy maps observations to actions; otherwise the model writes programs, from a single tool call to code with branches and loops.

Most reviews ask how capable the model is and how to train or prompt it (Qin et al., 2026); Li and Yao (2026) map the agent–environment loop. This post is about the software system around the model. Our test: if swapping the framework while keeping the model changes a property, the property belongs to the system. Whether the VLM recognizes a new cup is about the model; whether a new decision can interrupt a reach under way, or a command that would drive the arm into the table can reach the motors, is about the system.

We name three properties we want from that system, and the two design choices that shape them most.

A Running Example

The robot is asked to put a cup on a tray, and halfway through the grasp, someone nudges the cup aside.

In a ReAct-style system (Yao et al., 2023) the model calls one tool at a time, such as get_position(cup) and then grasp(cup), and reads each result. In a code-as-policy system it writes a short program that calls such tools. A program handles the nudge only if the model anticipated it; a ReAct loop notices only after grasp returns. Neither can interrupt an action in progress, and that is a limit of the system, not of the model.

Grasp as a blocking call

the call returns only when the reach is over

traynudgeold positiongrasp(cup) running…missed: the cup movedlook again, re-plangrasp(cup) againplaced, late

Grasp as a running task

an event can update it while it runs

traynudgetask: grasp(cup)cup moved → update targetplace(tray)done
The running example, from above. Left: a blocking grasp reaches for the old position and closes on nothing before the system looks again. Right: a running grasp task is redirected and follows the cup.

Three Properties

Expressiveness

Can the system express the logic a task needs, and give each decision the information it needs?

Logic. Branches, loops, and reuse come free with any programming language. What a plain program lacks is logic that spans physical time: a slip monitor beside a grasp, a handler that fires when the cup moves, an action that continues while the model thinks. That depends on the runtime. The model in Guava (Liu et al., 2026), for instance, works through nine fixed tools one call at a time, so a parallel monitor cannot be expressed at all.

Single path

One fixed route from input to output.

ObservationPolicyAction

Branches and loops

Conditions pick a path; failures loop back.

yesnoDetectGraspGrasped?Place

Concurrency and events

Tasks run side by side; events redirect them.

slip!updateDetectGraspPlaceSlipmonitorVLMreplan
Robot tasks need control structures of increasing richness: a single path, branches and loops, and concurrent tasks redirected by events. A system is expressive when the richer ones are as natural to write as the simple one.

Information. A model knows only what its tools return, and whoever repairs a failed program, a person or a coding agent, needs to know what happened. ASPIRE (Lu et al., 2026) records every primitive call with its inputs, outputs, and keyframes; adding this trace alone raises its success on LIBERO-Pro from 14% to 62%.

Too little

We know that it failed, not where or why.

$ run put_cup_on_tray
…
ERROR task failed

Too much

Everything is logged; the cause is buried.

12.020 INFO planner: joint_states ok
12.106 DEBUG planner: gripper width 0.082
12.194 DEBUG gripper: control loop dt=2.0ms
12.287 DEBUG planner: pose estimate updated
12.370 DEBUG gripper: tokens in=2481 out=96
12.473 INFO camera: tokens in=2481 out=96
12.576 DEBUG gripper: control loop dt=2.0ms
12.678 INFO planner: heartbeat ok
12.773 DEBUG perception: heartbeat ok
12.832 DEBUG bus: control loop dt=2.0ms
12.918 INFO camera: heartbeat ok
12.988 DEBUG planner: joint_states ok
13.090 DEBUG planner: heartbeat ok
13.170 INFO arm_ctrl: publish /tf (34 transforms)
13.226 DEBUG planner: queue depth 3
13.276 DEBUG gripper: joint_states ok
13.378 DEBUG bus: control loop dt=2.0ms
13.455 DEBUG arm_ctrl: pose estimate updated
13.559 DEBUG gripper: joint_states ok
13.632 DEBUG planner: queue depth 3
13.724 INFO camera: subscriber connected
13.751 DEBUG perception: frame received (1280x720)
13.860 DEBUG gripper: publish /tf (34 transforms)
13.922 DEBUG camera: trajectory segment sent
14.021 INFO bus: subscriber connected
14.110 DEBUG camera: joint_states ok
14.136 DEBUG gripper: joint_states ok
14.223 DEBUG gripper: joint_states ok
14.323 DEBUG planner: subscriber connected
14.353 DEBUG camera: trajectory segment sent
14.431 INFO camera: subscriber connected
14.467 INFO arm_ctrl: pose estimate updated
14.511 DEBUG perception: control loop dt=2.0ms
14.536 INFO gripper: pose estimate updated
14.601 DEBUG camera: trajectory segment sent
14.633 DEBUG bus: frame received (1280x720)
14.732 INFO bus: trajectory segment sent
14.821 DEBUG perception: gripper width 0.082
14.821 WARN perception: no frames for 1.8 s
14.920 DEBUG perception: queue depth 3
15.020 DEBUG planner: control loop dt=2.0ms
15.106 DEBUG vlm: queue depth 3
15.144 DEBUG bus: trajectory segment sent
15.221 INFO bus: joint_states ok
15.299 DEBUG arm_ctrl: control loop dt=2.0ms
15.389 INFO arm_ctrl: joint_states ok
15.449 DEBUG gripper: tokens in=2481 out=96
15.519 DEBUG vlm: heartbeat ok
15.607 DEBUG planner: tokens in=2481 out=96
15.645 DEBUG planner: joint_states ok
15.725 DEBUG camera: gripper width 0.082
15.819 INFO bus: pose estimate updated
15.925 DEBUG vlm: control loop dt=2.0ms
16.010 INFO camera: publish /tf (34 transforms)
16.037 DEBUG camera: frame received (1280x720)
16.112 INFO perception: publish /tf (34 transforms)
16.150 DEBUG perception: tokens in=2481 out=96
16.260 DEBUG gripper: gripper width 0.082
16.315 DEBUG camera: joint_states ok
16.408 INFO perception: trajectory segment sent
16.474 DEBUG perception: control loop dt=2.0ms
16.509 DEBUG perception: pose estimate updated
16.579 DEBUG bus: frame received (1280x720)
16.636 DEBUG camera: frame received (1280x720)
16.694 DEBUG perception: trajectory segment sent
16.744 ERROR task failed

Structured trace

Each failure linked to its cause.

  • ✕ task put cup on tray
  • ✓ decide: grasp cup VLM · obs @12.4 s
  • ✕ grasp(cup): missed object
  • input cup.pose age 1.8 s · stale
  • perception: no frames 12.1–13.9 s
  • camera driver restarted @12.1 s
The same failed run three ways. An error line hides the cause; a full log buries it; a structured trace links the failed action to the decision and the data behind it.

Efficiency

Utilization: if every call blocks, the arm waits while the model thinks and the model waits while the arm moves. In Agent as Policy, about 80 seconds of motion overlapped with generation under Codex CLI and none under Claude Code, a difference of harness, not model. Feedback: when the cup is nudged, how long does the arm keep reaching for the old position? TypeGo (G. Chen et al., 2026) runs reflexes at 100 Hz, ReKep (Huang et al., 2024) re-solves its constraints at about 10 Hz, and HAMSTER (Li et al., 2025) plans a path once per episode and cannot adjust it.

Safety

A failed grasp can be retried; an arm that sweeps the cup through the table, or hits the person who nudged it, cannot be undone. A safe system catches a bad command from any component, which takes three things:

  1. Identification: recognizing that a command or state is dangerous.
  2. Control authority: the power to block a command and stop the program that issued it.
  3. Fallback: a behavior, verified in advance, that brings the robot to a safe state.

Current systems implement pieces inside one component: Code as Policies (Liang et al., 2023) rejects exec in generated code, ReKep keeps targets in the workspace, and Agent as Policy checks every request against workspace and motion limits. None we surveyed has a safety layer independent of both the model and the generated code.

plancommandmove through tableallowedblockedpreemptsafe stoprejected: collisionVLM agentProgram / skillSafety layerchecks every commandArmFallbackstop · hold · retractunsafe outputsafe stateSafety requiresIdentify the problem1Identify the problemAuthority to intervene2Authority to interveneA fallback to execute3A fallback to execute

A model or program emits a command that would cause irreversible damage. The system identifies it, blocks it and stops the program, and runs a fallback to a safe state.

Two Design Choices

Managing Control Flow

How does it run? Current systems fall into five structures. MOKA (Liu et al., 2024), VoxPoser (Huang et al., 2023), and ReKep run a fixed loop in which the VLM fills in values; HAMSTER and ENPIRE (Xiao et al., 2026) are two-level hierarchies; in Guava, CaP-X (Fu et al., 2026), and Agent as Policy the model steps through calls; Code as Policies, ASPIRE, and GaP (K. Chen et al., 2026) write a program and run it without the model; TypeGo is a concurrent, event-driven runtime.

Fixed loop, fixed tools

Harness code fixes the steps; the model fills in values at set points.

MOKAVoxPoserReKep

Two-level hierarchy

The model gives an intent; a learned low-level policy carries it out.

HAMSTERENPIRE · deployed policy↻

Model steps through calls

The model picks each next call after seeing the last result.

GuavaAgent as PolicyCaP-X · multi-turn

Write a program, then run it

The model writes the control flow; an interpreter runs it without the model.

Code as PoliciesCaP-X · single-turnGaP↻ASPIRE↻

Concurrent, event-driven

Several loops run at different rates; events trigger planning and preemption.

TypeGo

↻ a development loop rewrites the program, graph, or policy between runs.

How control flow runs in surveyed systems.

Who decides, and what triggers the next step? Decisions are written in a program or made by the model step by step; steps follow one another or are triggered by events. One system can use all four combinations:

Programmatic decisions Model-mediated decisions
Sequential Skill composition; code as policy ReAct; explicit VLM calls
Event-driven Sensor-triggered rules and recovery Event-triggered VLM replanning

What is the unit of execution? A reach takes seconds, and the cup may move meanwhile, so the unit is a task: an action that keeps running after the call that started it returns, and can be updated or cancelled. (Code here uses the API of roborun, described in a companion post.)

g = start(grasp("cup"))     # returns at once; the grasp keeps running
g.update(target=new_pose)   # redirect it while it runs
await g.cancel_and_wait()   # returns when the arm is at rest

Cancelling must be distinct from having stopped, since control authority depends on it. A program changed mid-run should likewise let the step under way finish and continue from shared state, not from the old program’s variables.

pendingrunningcancellingsucceededfailedcancelled
    A task's lifecycle. Requesting cancellation moves a task to cancelling, not cancelled: the arm is still moving. Click the transitions to step through it.

    Managing Data

    Should a tool be a function call or a service? A function call, like Guava’s get_position, halts the caller and keeps nothing between calls, so a segmenter called per frame cannot tell whether this cup is the last one. A service keeps its state, answers while the program works, and says how fresh each answer is.

    Function callcaller waitsProgramSegmentationplanwaitinggraspwaitingplaceload, segmentload, segmentcallmaskscallmasksnothing kept between calls: is it the same cup?Servicecaller keeps workingProgramSegmentationplangraspplacesegmentsegmentkeeps masks, cup IDsidle, state keptquerycup #3querystill cup #3runs when asked, keeps its state, answers asynchronously
    The same segmentation model as a function call, which halts the program and keeps nothing, and as a service, which keeps its state and answers while the program works.

    Shared state needs the same care: each value should say when it was observed and by whom, and a reader should be able to refuse one that is too old.

    cup = world.get("cup", max_age=0.3)   # StaleData if older

    Messaging layers and frameworks such as ROS 2, Ray, and Temporal each cover part of this, but none says who may command the arm, when a command goes stale, or how conflicting behaviors are arbitrated.

    Future Work

    Imagine every model call were instant. The arm would still take seconds to move, the cup could still be nudged meanwhile, a cancelled motion would still have to stop, and a bad command would still have to be caught. Stronger models make the software around them thinner; they do not remove the need for the system. Open questions remain: how to trace and undo a change to a running program, where the boundary between thin tools and rich skills should sit, and whether a safety layer independent of the model can still allow useful behavior. roborun is our first answer.

    A good system should not prescribe how intelligent a robot agent must be. It should provide the abstractions to express, coordinate, and evolve different forms of robotic intelligence, and keep the robot safe while it does.

    References

    • Chen, G., Schott, A., & Zhong, L. (2026). TypeGo: An OS runtime for embodied agents. arXiv preprint. arXiv:2607.05482
    • Chen, K., Xie, S., Fu, L., et al. (2026). GaP: A graph-as-policy multi-agent self-learning harness for variational automation tasks. arXiv preprint. arXiv:2607.05369
    • Fu, L., et al. (2026). CaP-X: A framework for benchmarking and improving coding agents for robot manipulation. In International Conference on Machine Learning (ICML). arXiv:2603.22435
    • Google. (2026). Gemini 4 Argon for robotics. Google Developers Blog. developers.googleblog.com
    • Huang, W., Wang, C., Zhang, R., Li, Y., Wu, J., & Fei-Fei, L. (2023). VoxPoser: Composable 3D value maps for robotic manipulation with language models. In Conference on Robot Learning (CoRL). arXiv:2307.05973
    • Huang, W., Wang, C., Li, Y., Zhang, R., & Fei-Fei, L. (2024). ReKep: Spatio-temporal reasoning of relational keypoint constraints for robotic manipulation. In Conference on Robot Learning (CoRL). arXiv:2409.01652
    • Jia, M., et al. (2026). Agent as policy for robotic manipulation. arXiv preprint. arXiv:2609.12541
    • Li, X., & Yao, S. (2026). Agent robotic systems [Blog post]. xirui-li.github.io
    • Li, Y., Deng, Y., Zhang, J., et al. (2025). HAMSTER: Hierarchical action models for open-world robot manipulation. In International Conference on Learning Representations (ICLR). arXiv:2502.05485
    • Liang, J., Huang, W., Xia, F., Xu, P., Hausman, K., Ichter, B., Florence, P., & Zeng, A. (2023). Code as policies: Language model programs for embodied control. In IEEE International Conference on Robotics and Automation (ICRA). arXiv:2209.07753
    • Liu, F., Fang, K., Abbeel, P., & Levine, S. (2024). MOKA: Open-world robotic manipulation through mark-based visual prompting. In Robotics: Science and Systems (RSS). arXiv:2403.03174
    • Liu, H., Li, X., Yao, S., et al. (2026). Guava: Distilling frontier VLMs into a compact agent through a robotic manipulation harness. arXiv preprint. arXiv:2606.18363
    • Lu, R., Wu, Y., Kou, E., et al. (2026). ASPIRE: Agentic skills discovery for robotics. arXiv preprint. arXiv:2607.00272
    • NVIDIA. (2026). Astranomy [Technical report]. research.nvidia.com
    • Qin, C., Wu, D., Feng, K., et al. (2026). Towards agentic robots: Model, data, environment, and harness. arXiv preprint. arXiv:2610.20442
    • Xiao, W., et al. (2026). ENPIRE: Agentic robot policy self-improvement in the real world. arXiv preprint. arXiv:2606.19980
    • Yao, S., Zhao, J., Yu, D., Du, N., Shafran, I., Narasimhan, K., & Cao, Y. (2023). ReAct: Synergizing reasoning and acting in language models. In International Conference on Learning Representations (ICLR). arXiv:2210.03629