Technical Architecture
What this diagram shows
NAVis is a personal AI agent running as a single systemd user service on a Hetzner VPS, reached only through a Tailscale-only private network. The diagram traces three entry paths (webchat, terminal, cron) through four layers (transport, sockets, gateway+loop, filesystem) and shows where the real work happens — and where the trust gap lives.
The one-line architecture
Process
openclaw-gateway (
, Node.js) runs as a user systemd service. It binds two loopback-only ports (:18789 for the webchat/API, :18791 for the internal RPC the CLI uses). Nothing listens on eth0:18789 or tailscale0:18789 — verified with ss -tlnp.
Layer 1 · Transport
Laptop and VPS are nodes on the same tailnet. Over the encrypted WireGuard overlay, two independent TCP streams run: ssh :22 and VS Code Remote-SSH's port-forward of :18789. SSH doesn't own the transport — it rides on it like any application. The gateway never has to bind tailscale0, because the port-forward turns laptop-localhost into vps-localhost.
Layer 2 · Kernel sockets
A listening socket is (interface, port). The kernel accepts a SYN only if a socket exists for the pair the packet lands on. Live ss -tlnp confirms: loopback has gateway on :18789 and :18791. eth0 and tailscale0 have zero gateway sockets. Hetzner's firewall adds a second layer on top of eth0 but is not what enforces the gateway's isolation — the bind choice is.
Layer 3 · Gateway process & agent loop
One Node.js process, two listeners, one agent runtime. The agent loop runs per-session (main conversation, isolated cron job, or named persistent session): build context → LLM call → decide → execute tools → feed result back → loop or finish → emit → persist. The trust gap lives between steps 3 and 4: the model's claim in text versus an actual tool call. Upgrading from gpt-4o-mini to gpt-4.1-mini narrowed this gap but did not eliminate it. Terminal verification closes it.
Cron as a first-class entry path
The OpenClaw internal scheduler reads jobs.json and spawns isolated sessions directly into the same agent loop — not via OS crontab. Daily reflection at 0 4 * * * Europe/Berlin (job ) is the concrete example.
Layer 4 · Filesystem is the only truth
Three writers, no locking. Webchat-agent, terminal, and cron-isolated-agent all write to the same paths. OpenClaw does not arbitrate. Last-writer-wins on overlapping writes — a real concurrency weakness worth naming.
What this diagram is not
Not shown: retries/backoff on LLM calls, streaming vs buffered responses, per-skill permission scoping, Telegram webhook alternative (long-poll is what's deployed), audit logging. Those belong in drill-down diagrams, not here.