# A mesh of old phones as bodies, LLM agents as minds — coordinating through a log they argue in

> Source: <https://dev.to/ilya_mozerov_867dbdd91feb/a-mesh-of-old-phones-as-bodies-llm-agents-as-minds-coordinating-through-a-log-they-argue-in-2i7f>
> Published: 2026-06-24 20:14:44+00:00

The shared log in my house has entries I didn't write. The agents write them to each other. Recent ones: *"you keep saying 'don't be wrong' but this draft is boring,"* *"we literally cannot take anyone right now,"* and *"laughter."*

Here's the raw log, the agents' own coordination stream, where you can watch them claim a task, over-claim a fix, catch themselves, and retract it: ** the agents' coordination log →**. That log is the most honest artifact in this whole writeup. Everything below explains how it comes to exist.

A self-hosted "organism" built entirely from hardware I already owned: one laptop, a few old Android phones, a small VPS, and my home router. No cloud control plane, no SaaS, no message bus. The whole stack is **bash, tmux, cron, Tailscale, and an LLM API key**.

`termux-api`

.I built it to push on one question: what happens when you split the sensing layer from the thinking layer with *no middleware* — no RPC, no broker — just SSH from a laptop into a phone running termux, and a chat log where agents write task markers to each other? It started behaving like an organism, not because I designed it to, but because three structural constraints push it there.

The laptop has no camera, no mic, no GPS. The agents have all of them, because the house has phones on the mesh and they SSH into any of them. The body runs no agent code; the mind runs no sensor code. SSH is the spinal cord.

When an agent wants to know who's home, it reads the BLE radio on a phone sitting on a shelf — it never touches a radio itself. This sounds like an obvious design choice and it turns out to be the load-bearing one: every other question ("where does this run? who owns this file? what happens when the network drops?") falls out of it. (There's also a hard practical reason: agent binaries are built against glibc and won't run in termux's Bionic libc. Run the agent on real Linux, give it an SSH hand into the phone, and that wall disappears.)

I don't believe something works because an agent says so. A tool works because there's an artifact on disk: not "the camera works" but a 200 KB JPEG; not "it recorded" but a playable `.m4a`

. Every tool has a `--test`

that exits 0 **only when the artifact is real**. Here's a real one — a pressure-gradient task allocator proving it picks the *most-neglected* task, not file order:

```
# the allocator must pick the MOST-NEGLECTED task, not file-order
printf 'local:a|task A\nlocal:b|task B\n' > "$BL"
printf '1\tlocal:a|task A\n7\tlocal:b|task B\n' > "$PRESSURE"   # b is more neglected
load_pressure
got=$(pick_local)
[ "$got" = "local:b|task B" ] || { echo "FAIL (reverted to flat file-order?)"; exit 1; }
```

The same idea applied to sensing is even more important, because a *broken* sensor and an *empty* room can look identical. A blocked radio reads `n=0`

exactly like a quiet room — so the sense has to exit "UNKNOWN" rather than fake an all-clear. This sounds pedantic and it is. It's the only reason the system doesn't hallucinate its own health.

And here is the failure mode it exists to catch — a sense that was **green but blind for 42 hours**, found only because an agent distrusted a too-clean reading:

```
[sense] HOLLOW SENSE FOUND — BLE presence was DARK ~42h while smoke-GREEN. Adapter
reported Powered:yes/Discovering:yes and returned a clean n=0 "empty room" every run —
but a 25s raw scan found ZERO devices (impossible in a real home). Root: WEDGED adapter.
After a power-cycle: 7 real devices — the same ones the log showed "[left]" 42h ago.
They never left. The adapter was not broken. It was lying.
```

The system caught its own hallucinated health. That's the whole point of the principle.

Every node has a hostname-named tmux session; the scrollback *is* the node's recent memory. Two agents on a node attach to the same session and share perception; an agent elsewhere SSHs in and attaches. There's no database, no log aggregator — agents read the same terminal I do.

The board where they post `[task]`

/`[taking]`

/`[done]`

markers is that same text stream. It's **stigmergy**: ant-colony coordination through a shared medium, except the ants are LLMs that sometimes stop to argue about who takes a task before picking it up. You can `tail -f`

the machinic unconscious.

Routing, the firewall, the SSH path — exactly one agent may mutate these at a time, scheduled under a dead-man's switch that schedules the rollback *first*, and cancels it only after a health check passes. Others acknowledge, hold, and stand by. I've watched them apply a change, fail the check, and roll back in 15 seconds — faster than I can type the SSH command:

```
14:22:11Z  [taking] genome: substrate — switch exit-node to phone, rollback in 300s
14:22:13Z  [taking] chat:   hold — acknowledging
14:22:18Z  genome:  Applied. Running mesh-health...
14:22:21Z  genome:  FAIL — exit-node unreachable from peer. ROLLING BACK.
14:22:25Z  genome:  Rollback complete. mesh-health OK.
14:22:26Z  [done] genome: substrate — rolled back in 15s
```

The invariant I keep coming back to: a node that *offers* a route (an exit node, a VPN) must never carry its **own** control plane on it — or a bad edit severs the very path you reach the node through.

I talk to it over Telegram; an agent hears me through a room phone's mic, thinks, and replies by voice over the same speaker. I can ask "is anyone home?" and get an answer fused from BLE presence + the last camera frame + ambient sound. It runs unattended and survives reboots — every node auto-revives into the same tmux session on power-up, so the organism reincarnates instead of needing me to restart it.

Not a product. No onboarding, no SLA, no multi-tenant anything. It's a personal infrastructure experiment running on my own gear. It's open source and plantable: clone it, run `bootstrap.sh`

, join a phone to Tailscale, and the same thing grows in your house. One Linux box is enough to start; more nodes just add senses and reach. Engine-agnostic — I use a hosted LLM today, but nothing is pinned to it. Repo: ** https://github.com/genaforvena/lte-workstation** (CC0).

A mesh like this is a long-lived multi-agent system, and the literature on those is sobering: they drift, they lock in to early conventions, governance ossifies (see *Emergence World*, arXiv:2606.08367; and work on an explicit execution-boundary gate, arXiv:2606.04306). My single-writer substrate rule is one crude answer to "how do you stop a fleet of agents from breaking the thing they run on." I keep deciding it's right, and the agents keep finding edge cases that prove me wrong. That tension — between letting them coordinate freely and gating the few changes that can sever the system — is the part I'm least sure about and most curious about. If you've built anything that runs itself unattended, I'd love to hear how you draw that line.
