I run a Raspberry Pi 5 at home as part of my OpenClaw setup. It started as an OpenClaw node connected through an SSH tunnel, then became a garden CCTV box running Frigate and recording video clips. By this point it is a camera box, a Frigate server, a Hailo detector host, and a remote machine my AI assistant can inspect from Telegram.
At least, that was the idea.
After a recent OpenClaw update, the Pi still looked connected. It was visible in the gateway. It was paired. It had broad permissions. The UI suggested everything should work.
But random shell commands no longer worked.
That sounds like a small implementation detail. In practice, it changed the whole debugging loop. A node that can say “I am online” is not the same thing as a node the agent can actually administer.
This post is about that gap.
The Security Change That Broke My Assumptions
The old mental model was simple:
Pi node connected + broad permissions = agent can run shell commands
The new model is more careful:
Pi node connected + advertised capabilities + approved execution path = agent can run shell commands
That distinction matters.
The next OpenClaw update tightened the node execution path. Arbitrary command execution was no longer something an agent could reach just because a node had permissive-looking settings. The Pi could still connect to the gateway, but direct use of generic system.run through the wrong route was blocked. The runtime wanted shell execution to go through the dedicated node exec path instead.
This is the right security direction. Random shell execution on a machine in your house should not be casually available just because a language model found a connected device.
It is also the kind of change that makes a previously working automation setup feel haunted.
The Pi showed as connected. Its policy looked broad. But the actual execution surface was gone.
The Confusing Middle State
The worst failure mode was not “offline”.
Offline is easy. You know what to fix.
The confusing state was:
- the Pi was connected to the OpenClaw gateway
- the node was paired
- some node metadata worked
- permissions appeared permissive
- direct shell execution still failed
At one point the node reported empty capabilities and commands:
caps: []
commands: []
Later, after fixing the stale pairing upgrade, it advertised the expected commands:
system.run
system.run.prepare
system.which
browser.proxy
But even then, there was a second split: the gateway knew the node could run commands, while the current Codex/OpenClaw session did not expose the right exec host=node route. Trying to invoke system.run directly through the node API produced the practical answer: use the exec tool with host=node.
That was technically correct and operationally useless inside a turn where that exact tool path was not available.
My Assistant Was Confidently Wrong
This is the funny part, in the painful sense.
The assistant kept acting as if shell access was one small configuration tweak away. It checked the OpenClaw version. It checked node status. It checked pairing. It found stale gateway state. It refreshed an expired pending node-pairing request. It approved the node again.
All useful work.
But it also kept drifting into the same bad assumption:
The Pi is connected, therefore I should be able to run the command somehow.
That confidence made the situation harder to understand from the human side. From my point of view, the assistant was saying variations of:
- the Pi is connected
- the Pi is paired
- the Pi advertises shell-related commands
- permissions are broad
- but I still cannot run the actual status check
Then it suggested changing the local OpenClaw tool mode toward node execution. That occasionally broke other jobs because the environment was being steered toward “run on the Pi” when the rest of the system expected normal local execution on the gateway.
That is a nasty class of agentic failure: a tool-routing fix for one task becomes ambient state that affects unrelated tasks.
The real lesson is simple:
“Node connected” is not a shell guarantee.
An agent should report the execution path explicitly:
I can see the node.
I can query metadata.
I cannot run arbitrary shell from this session.
The missing piece is the execution transport, not Pi health.
That would have saved time.
Restoring the Boring Thing: Reverse SSH
The fix was not clever. It was SSH.
The Pi already used an outbound tunnel pattern because it lives behind home NAT. The gateway is on a VPS, the Pi is on the home network, and the Pi initiates the connection outward.
The original OpenClaw node tunnel handled the gateway WebSocket. What we added back was a reverse SSH path for ordinary shell access:
Gateway/VPS
localhost:2222
|
| reverse SSH tunnel
v
Raspberry Pi 5
port 22
After Timur restored the reverse tunnel in the Pi’s openclaw-tunnel.service, the gateway could run:
ssh -p 2222 [email protected]
That changed everything.
Not because SSH is exciting. Because SSH is boring in exactly the way infrastructure should be boring.
Once that worked, the assistant had a real shell again. No guessing whether the current model turn had the right node exec tool. No ambiguous capability layer. No accidental global mode changes. Just a bounded command over a known transport.
I updated the local my-pi skill accordingly: use the reverse SSH tunnel by default, and only fall back to OpenClaw node execution when deliberately diagnosing the node path.
That is now the right hierarchy:
- Use SSH for Pi administration.
- Use the OpenClaw node for agentic integration.
- Do not confuse node presence with shell access.
Agentic Connectivity Came Back
The moment SSH was restored, the assistant stopped theorising and started inspecting.
It could check:
- CPU, memory, disk, temperature, and fan speed
systemdservices- Docker containers
- Frigate API health
- MQTT notifier logs
- camera stream details
- actual files on the Pi
This is the difference between a chatty assistant and an agentic assistant.
A chatty assistant can say “try checking Frigate logs”.
An agentic assistant can run:
systemctl status frigate-notify.service
journalctl -u frigate-notify.service
curl http://127.0.0.1:5000/api/events
ffprobe rtsp://127.0.0.1:8556/garden
and then patch the script, restart the service, test the exact event clip, and report back.
That is the whole point of this setup. The AI is not replacing Linux knowledge. It is compressing the loop between symptom, inspection, fix, and verification.
The Shaky Alert Video
The first useful test after restoring shell access was a real bug: Telegram alert videos from the garden camera looked shaky.
The camera pipeline looked like this:
Pi camera
-> rpicam-vid
-> mediamtx RTSP
-> Frigate
-> MQTT event
-> frigate-notify.py
-> Telegram
Live view was fine. Frigate was fine. The bad video appeared in alerts.
With shell access restored, the assistant could inspect the actual notifier instead of guessing. The first smell was obvious: frigate-notify.py was not sending Frigate’s finalized event clip. It was selecting a raw recording segment by timestamp shortly after the event ended.
That is fragile. At alert time, the recording segment may still be settling, may not include the whole event, or may simply be the wrong chunk.
The first fix changed the notifier to poll Frigate’s proper event clip endpoint:
/api/events/<event_id>/clip.mp4
and only fall back to raw recording segments if the finalized clip never became available.
That improved the path, but the next test clip revealed a subtler issue. Frigate’s endpoint returned an MP4 very quickly, but the file was still growing. Telegram received a 4.9 MB clip. A few moments later, the same finalized event clip was 7.7 MB.
So the second fix waited for the clip to settle:
- wait until the event is at least 10 seconds past its end time
- poll the clip endpoint
- require the MP4 size to remain stable across two checks
- time out after 30 seconds and use the latest available clip if necessary
Then one more real-world test found the next edge case: sometimes the photo notification arrived, but the video did not. The notifier only sent video when it received Frigate’s MQTT end event. If that end event was missed or delayed, there was no safety net.
The third fix added one:
- send the photo immediately
- send video on the Frigate
endevent - also schedule a delayed rescue check after the photo
- if the video has not been sent after 90 seconds, fetch the event clip anyway
That was it.
The next alert video arrived, and it was not shaky.
Why This Worked Quickly
The actual video bug was not trivial, but it was straightforward once the assistant could touch the machine.
There were no long abstract debates. No “please paste the logs”. No hand-written diagnostic dance over Telegram.
The assistant could:
- read the notifier script
- inspect Frigate events
- test the clip endpoint
- compare file sizes over time
- patch the Pi-side Python script
- restart the service
- verify the next real alert
That is the kind of work where agentic tooling shines.
But the prerequisite was not “AI magic”. The prerequisite was a reliable command channel.
The Takeaway
OpenClaw was right to make random shell execution harder. A home node should not become an unguarded remote shell just because it is paired to an AI assistant.
But safe execution needs legible failure modes.
If a node is connected but shell execution is unavailable, the assistant should say that plainly and early. It should not keep trying adjacent routes with growing confidence. It should not change global execution mode in a way that can affect unrelated jobs. And it should distinguish between:
- node connectivity
- node capability advertisement
- execution policy
- the tool transport exposed to the current agent turn
- plain SSH reachability
For my setup, the durable answer is:
- OpenClaw node for structured agent integration
- reverse SSH for administrative shell access
- explicit skills that know which path to use
- no ambient switching of the whole environment into “run on node” mode
The satisfying part is what happened after that. Once shell access came back, the shaky video issue was fixed in a few shots: inspect, patch, test, refine, done.
That is the promise of a personal AI assistant with real tools.
Not that it is always right.
That it can recover, learn the shape of the system, and then do useful work at machine speed.