HORUS/blog

Sep 5, 2026 · ai-agents · robot-safety · middleware · embodied-ai

Best Ways to Give an AI Agent Access to Physical Hardware

Give an agent named skills with checked preconditions, never raw motor commands; here are the access methods ranked and which one fits your project.

Give an agent named skills with checked preconditions, never raw motor commands and never a ROS 2 topic opened directly to a model. Skills give a model a vocabulary it cannot exceed and refuse when the world is not what the plan assumed, with ROS 2 or HORUS underneath holding the timing. That changes only if the hardware cannot hurt anything. The rest of this post ranks the ways people actually wire an agent to hardware, and names the one that fits each kind of project.

You have an agent that works. It reads, it plans, it calls tools, it does genuinely useful things inside your codebase, and the obvious next thought is that the same loop could drive something with wheels. Then you open the robot's code and the question stops being obvious. There is a serial port, or a driver library, or a stack of topics with names somebody else chose, and none of it looks like a tool definition. Maybe you have already tried the direct route, handed the model something that writes to a motor, watched it work three times and then do something you cannot explain, and quietly turned it off. Maybe you got as far as reading about a protocol for exposing tools and could not tell whether it was the right layer or a fashionable detour. Or maybe you are further back and simply want to know whether this is a thing responsible people do at all, or a category of demonstration that never leaves the video. All of those are the same question underneath: what exactly should sit between a model and a motor, and who checks it.

Should I give an AI agent direct access to my robot's hardware?

No, and the version worth building instead is close enough that the distinction sounds pedantic until the first time it saves you. Direct access means the model can produce a value that reaches an actuator without anything in between deciding whether that value is sane. The alternative is a small set of functions you wrote, each of which takes a request, checks whether the request makes sense right now, and either performs it or reports why it will not. From the model's side these feel identical: it asks for something and something happens. From your side they are entirely different systems, because the second one has a place to put every rule you learn the hard way. The joint that must not go past a certain angle, the gripper that must not close on a hand, the drive that must stop when a reading goes missing — each of those is one line in a skill and nowhere at all in the direct version. Building the checked layer first costs a day. Retrofitting it after an incident costs considerably more than a day.

What does hardware access for an agent actually mean?

Hardware access means the agent can cause something physical to happen, and the whole design question is how many steps sit between the asking and the happening. At the far end is a model writing bytes to a device — no interpretation, no validation, nothing between intent and current. One step in, the model calls a driver function, which at least means somebody typed the units. Two steps in, the model calls a skill: a verb with a stated precondition and a defined end state, such as move to the pick position or open the gripper, which knows how to refuse. Three steps in, the model requests a skill and a person approves it before anything moves. Each step you add costs some autonomy and buys back a place to enforce a rule. The mistake people make is treating this as a single yes-or-no decision about trust. It is a dial, and different actions on the same robot deserve different settings: reading a camera and driving toward a person are not the same kind of request and should not sit at the same setting.

What are the actual ways to connect an agent to hardware?

Seven arrangements cover nearly everything built, and they differ by what the agent may name and who checks the request. A skill API called through function calling is the ordinary answer: your Python functions, described to the model, invoked by name. A tool server speaking a standard protocol is the same idea with a defined wire format, which matters when several agents are involved. Direct service calls on an existing stack skip the wrapper and inherit whatever that stack already exposes. A human-approval queue puts a person between request and motion. A simulator-only sandbox gives the agent full reach over nothing that can be damaged. Underneath any of these sits the layer that carries the request to the code that moves things, and that is where ROS 2 competes with leaner middleware — HORUS, for example, is open source under Apache-2.0 for Rust, Python and C++, where all three languages share the same shared-memory ring buffers, so an agent process in Python and a compiled control loop on one machine are not serialising messages to each other. The seventh option is a fixed menu with no agent at all.

How do these access methods compare?

Read the last two columns first, because the method that fits is decided by what happens when the model is wrong rather than by which one is most elegant. Nothing here is exclusive: the usual mature shape is a skill API for ordinary actions, a human-approval step for the two or three actions that could ruin something, and a simulator for anything new. The middle column is the one that catches people out, since most of these ask for knowledge that has nothing to do with models.

OptionWho it is forWhat it assumes you knowWhen to pick itWhen not to
A skill API through function callingAlmost everyone starting outPython, and how to describe a function clearlyYou already have working behaviours to exposeYou have no skills yet, only drivers
A tool server on a standard protocolTeams with several agents or shared toolingRunning a small service, and versioning its interfaceMore than one client will call the same robotOne script, one robot, one person
Direct service calls on an existing stackTeams already deep in ROS 2ROS 2 message types, services and actionsThe behaviours you want are already publishedThe stack exposes far more than the agent should touch
A human-approval queueAnyone near people, money or fragile objectsYour own review interface, and operator patienceA wrong action is expensive to undoNobody is available to approve at three in the morning
A simulator-only sandboxResearchers and anyone testing a new agentYour simulator, and how far it diverges from realityThe agent is new and you are still learning its habitsThe interesting failures are physical ones
HORUS under an agent processSolo builders and small teams on one machineOne of Rust, Python or C++, plus your own control codeA Python agent and a compiled loop share a computerYou want navigation, mapping and drivers handed to you
Raw driver or serial accessAlmost nobodyYour hardware's protocol, in detailYou are writing the skill layer itselfAn agent is the thing calling it
A fixed menu, no agentMost working robots todayNothing extra at allThe set of jobs is short and knownRequests arrive in language you cannot predict

Which method fits a hobbyist, a researcher, or a product team?

A skill API for hobbyists, a sandbox plus a skill API for researchers, and an approval queue over a narrow skill API for product teams. The hobbyist case is the happiest: your robot is small, the failure is a knocked-over cup, and wrapping four behaviours as functions takes an evening and immediately makes the agent useful. The researcher case is different because the agent itself is the object of study, which means it will do surprising things by design, and surprising things belong in a simulator until their surprises are catalogued. The product team case is the one people underestimate. Once a machine acts on requests from customers, every action it can take becomes a thing you may have to explain to somebody unhappy, and the size of your exposed skill list is exactly the size of that explaining. Teams that ship this well expose fewer actions than they built, gate the expensive ones behind a person, and log every request with the state the robot was in when it arrived. That log is not paperwork. It is the only way to answer what happened.

What hardware do I need to run an agent next to a robot?

Almost nothing extra if the model runs elsewhere, and a noticeably larger computer if it runs on the robot. A hosted agent needs a network path and a way for the robot to describe its situation in words or numbers the model can read; the robot's own computer keeps doing what it already did. A local model changes the picture, because that machine now runs inference and a control loop at the same time, and under pressure it is the loop that suffers, since the loop is the part with a deadline. The common escape is a second computer on the same bench or the same network running the agent, with the robot asking it questions, which keeps everything local without starving the timing-critical half. Microcontrollers do not participate in this conversation at all: a small board runs firmware, accepts finished commands from something larger, and has no idea an agent exists. If you are weighing where each piece belongs, what runs on the robot versus somewhere else is the fuller treatment.

How long does it take to give an agent working hardware access?

An afternoon to make it move something, a month to make it behave, and the month is spent on refusals rather than actions. The afternoon is genuinely that short: describe three functions, hand the descriptions to a model, and watch it call them in a sensible order. What follows is the real work. You discover the model asks for a location that does not exist, so a skill needs to validate names. You discover it calls two skills that fight each other, so something needs to reject a request while another is running. You discover it retries a failed action forever, so failures need to carry whether retrying is sensible. You discover it does something reasonable at a moment when nobody expected the robot to move, so there needs to be a way to say no globally. Every one of those is a small piece of code and none of them is interesting, which is precisely why they get skipped. Budget for them explicitly, and the demonstration becomes a system rather than a video.

What do I need to know before opening hardware to an agent?

You need to be able to write a function with clear arguments, and you need a written list of every physical thing your robot can do. The bar is lower than people expect, since none of this requires understanding how a model is trained. What it does require is precision about promises: for each skill, what must be true before it runs, what state the robot is in when it finishes, and what it does when the preconditions fail. If you cannot write those three lines for a behaviour, that behaviour is not ready to be exposed. The second thing worth understanding is why the layer beneath your skills cannot wait for a model to answer, which the explanation of control loops and their timing covers properly. The third is the shape of the tool interface itself, and what a tool protocol means when the tools have hands is worth reading before you commit to one. None of this needs a degree in anything.

What do I give up by putting an agent in front of the hardware?

You give up knowing in advance what the robot will do, and you give up the ability to reproduce a run exactly. The same request in the same room can produce two different sequences, both defensible, and your debugging becomes reading a transcript and inferring intent rather than following a trace. You also acquire a dependency that changes without your involvement: a hosted model updates, and your machine behaves differently on a morning you shipped nothing. Timing becomes something you observe rather than schedule, because an answer arrives when it arrives. And you take on a genuinely new security question, since anything that can reach the agent's input can now suggest a physical action, which is not a category most software teams have dealt with. None of this is an argument against agents. It is an argument for keeping the unpredictable part above a layer that behaves identically every time, so the worst outcome of a bad plan is a refused request rather than a moving arm.

When is ROS 2 the better choice?

ROS 2 is the better choice whenever the actions you want to expose are ones ROS 2 already provides. If your agent should be able to send the robot to a named room, the navigation stack is the thing that gets it there, and writing a replacement so an agent can call it is work done for no reason. The same applies to arm motion planning, to sensor drivers whose vendors ship ROS 2 support and nothing else, and to anything involving more than one computer, where ROS 2 answers questions you would otherwise answer yourself. In a lab, ROS 2 is how another group reproduces your agent's behaviour. And if your team already knows the tooling, that fluency beats any property of a transport layer. HORUS is not the answer in those cases and makes no such claim: it gives you no navigation, no mapping and no driver library, it is validated in simulation rather than across deployed fleets, and replacing a working stack to chase something you cannot yet articulate is a good way to lose a quarter of the year.

Can I just let the agent write and run code on the robot?

No, and here is why: code the model writes has not been read by anyone before it executes, which removes the only checkpoint the whole arrangement depends on. Generated code is fine — genuinely useful, in fact — when a person reviews it and it ships as part of your software. What breaks is the shortcut where a model produces a snippet at runtime and the robot runs it immediately. In that arrangement there is no bounded vocabulary, because generated code can call anything on the machine, which means every rule you encoded in your skills can be bypassed by a plan that simply does not use them. It also destroys your ability to say what the robot is capable of, since the answer becomes whatever the model thought of. The failure is not that models write bad code; they often write good code. The failure is that "often" is doing load-bearing work in a sentence about a machine that moves. Related reading: whether an agent can run a robot unsupervised.

Is this just an API with extra rules?

Partly, but not the way you think. The mechanics really are an API: named functions, typed arguments, return values, errors. What the framing misses is who the client is. A normal API client is a program that behaves the same way forever, so an error message is read by a developer once and the calling code is fixed. Your client here is confident, capable of paraphrase, and occasionally wrong in ways that look correct, and it reads your error messages at runtime and acts on them. That changes what a good interface is. Error text becomes an instruction rather than a diagnostic, so "no object matching that description is visible; try looking around first" is a better return value than an error code. Argument names become prompts, because the model reads them to decide what to pass. Fewer functions beat more functions, since a long menu of similar options produces worse choices. It is API design with the reader changed, and that changes almost every decision.

What does agent hardware access look like when it goes wrong?

It looks like the robot doing something plausible and wrong while nothing crashes and no error is logged. The most common version: the agent names an object that is not present, the skill takes the closest match rather than refusing, and the arm moves toward the wrong thing with total confidence. The second: the plan is coherent as language and impossible as physics, placing an item into a container that a later step was going to open. The third catches experienced engineers hardest, and it is staleness. The agent receives a description of the scene, thinks, returns a sequence, and by then something has moved, so the robot acts correctly on a world that stopped existing while it was reasoning. Nothing malfunctioned; the information was simply older than anyone assumed. This is the same class of trouble covered in why robots behave differently between runs, and the defence is unchanged: skills that verify what they are about to touch instead of trusting the plan that named it.

How do I decide which access method to use?

Start with the worst thing your robot can physically do, because that single answer eliminates most of the options. If the worst case is a knocked-over cup, a skill API is plenty and anything heavier is ceremony. If the worst case is a damaged part, a bruised person or an expensive mistake, put a person in the loop for the actions that can cause it and leave the rest direct. Then count your skills: three or more behaviours that each end in a state you can name and that you would let a stranger trigger. If you cannot count to three, that is your project, not the agent wiring, and no protocol choice will rescue you. Then ask whether anything other than your own script will ever call this robot; if not, skip the tool server and call functions directly. Finally, decide what the machine does when the agent is unreachable, slow, or confidently wrong, and write that behaviour before you connect anything. If the answer is unclear, keep the agent in your editor writing code you review, and revisit in a month. The speech-driven version of this same chain is worth reading alongside, since voice is one instance of it.

Take the line that matches your situation:

The HORUS Fit Framework is the checklist behind those lines, and none of its five axes is a number: ecosystem size, setup effort, team size fit, deployment target, and licence. Score each access method on all five, and the axis you cannot compromise on decides the rest.

Whichever way the agent reaches the hardware, something underneath still has to be on time. When you get to that layer, HORUS is open source under Apache-2.0 at github.com/softmata/horus. Star it so it is in your list when you start building.

Found this useful? Share it:Discuss on HNShare on X