
Six Machines, One Control Room: AI Agents That Only Ask When It Matters
Four Macs, a Linux PC, a server, each with its own AI agent. Instead of talking to every one of them separately, there is now a control room: the agents propose, I decide with Touch ID, and the machines clean up after themselves.
The problem
My working day happens on two MacBooks, and I switch between them all the time: the 16-inch M4 MacBook stays in the office, the 14-inch M5 MacBook is for working on the go.
On top of those there is a Mac mini, an older MacBook that runs everyone else's Docker containers, a Linux PC and a rented server at Hetzner. Each of these six machines runs an AI agent (Hermes), and the Macs run Claude Code on top.
That sounds like a lot of help. In practice it meant asking the same question six times, checking six times whether there was still room on the disk, and knowledge that grew on one machine never reaching the others. Each agent was smart on its own. Together they were a pile of separate conversations.
So the goal was not "more AI" but less noise: one place where everything comes together, and agents that only ask me when a decision really is mine to make.
Step 1: One hub instead of six separate conversations
All machines sit in a private network (Tailscale). The server is the hub the agents connect to. A tool called mesh runs every 15 minutes on the office Mac and syncs everything: knowledge, skills and program versions reach every machine, and whoever was offline catches up on the next run.
The knowledge itself lives in two places:
- Curated knowledge (rules, recipes, lessons from earlier projects) as a Git repository, identical on every machine.
- A shared memory, the "brain": a database on the server holding summaries of every work session, the project documents, and notes that agents leave for later sessions. Every agent on every machine can search it and write to it.
Step 2: A memory that understands meaning
At first the brain only searched for words. Anyone asking "Why is the restaurant feature limited to one country?" found nothing if the note said, in German, "beta restricted to Germany".
Before building this myself, I looked at what already exists. TencentDB Agent Memory, for instance, is an impressive project. But it works as a proxy that sits between the agent and the language model. For Claude Code that would mean a separate API key instead of the subscription, and every conversation landing unfiltered in yet another database. So I only borrowed two ideas:
- Search by meaning. Every entry gets a vector, computed with the
bge-m3model, locally on the server, no cloud. A search takes about 0.07 seconds. Results from keyword search and meaning search are merged. Since then, an English question also finds the German note. - Facts, not just transcripts. At night a small local model (
qwen3.5, 4 billion parameters, on the server's CPU) reads every session and pulls out up to five lasting facts: decisions with their reasoning, corrections, measured values. Each fact points back to its source. That takes about 75 seconds per session and runs between two and five in the morning, when nothing else is going on.
Step 3: The control room
The most important building block is a rule: agents propose, I decide.
Instead of messaging me, agents file a proposal: which machine, what exactly, what it gains, what could go wrong. One example: "Erase the contents of all iOS simulators? About 114 GB. Risk: installed test apps are gone, the simulators themselves stay."
To keep this from turning into new noise, three rules apply:
- One entry per machine and topic. If an agent proposes the same thing again, only a counter goes up.
- A no holds for 30 days. Nobody asks the same question again before then.
- Only urgent things reach my phone. An almost full disk, for example. Everything else waits in the control room.
The control room itself is a plain web page, reachable only inside the private network. At the top, one sentence says whether anything is waiting. Below that, the open decisions, grouped by machine. Then one card per machine, worst first, and a detail page for each machine.
Step 4: Why a passkey and not a password
Clicking "Yes" in the control room triggers something, such as clearing caches. So it has to be certain that it was me and not an agent.
The obvious answer would have been the login of the private network. It doesn't work for this: all machines run under the same account, so to the server an agent on one of my Macs looks exactly like me. And any password or key the page knows, the agents on the same machine know too.
That is why every yes and every no requires a passkey with Touch ID (Face ID on the iPhone). No agent can give a fingerprint. Each confirmation covers exactly one proposal and one answer, and can only be used once. Another device is added via a one-time link that is valid for ten minutes. The control room lists every passkey with the time it was last used. Since then I approve on either MacBook with Touch ID, each with its own passkey.
One limit belongs here, honestly stated: while such a setup link is open, an agent with a remote-controlled browser could register a passkey of its own. But the link is only created when I request it, and every passkey shows up in the list.
Step 5: Machines that know what they are for
Every machine has a role, described in a small configuration file:
- what it is for (the office Mac does development, the server runs production apps),
- which cleanups may be proposed there,
- what is never touched (on the server, for example, the databases of the production apps),
- which services may be reachable from outside.
Every 15 minutes it measures disk space, memory and swap. Once a day it also measures how much space caches, simulators and Docker take up, plus security: disk encryption, firewall, pending updates, and which services listen on all networks.
Measurements plus role produce proposals. The first run turned up things I hadn't been aware of, including:
- The travel MacBook, the 14-inch M5, was 99% full, 12 GB free, with over 100 GB of that in iOS simulators. I hadn't noticed a thing. Those proposals went to my phone as urgent.
- On the office Mac, a Gradle cache took up almost 27 GB.
- On the Linux PC, 387 updates were waiting, and the firewall wasn't running.
I approved four proposals. They ran on the next sync, and only as fixed commands from a catalog, never as free-form shell commands written by an agent. Result: about 78 GB freed, the travel MacBook down from 99% to 94%.
One thing surprised me: right after the simulators were deleted, the system reported only 0.7 GB more free space. macOS releases that kind of space with a delay, and the size measurement double-counts data that several simulators share. A few minutes later it was about 35 GB.
Step 6: What else a control room needs
- A backup. The brain now holds decisions, passkeys and facts. Once a day, the brain and the agents' memory are copied over an encrypted connection to another machine, and 14 days are kept. I restored the first backup and counted whether everything was there. Only then does it count as a backup to me.
- A history. One data point per machine per day. That turns into a forecast like "full in about 20 days", so the warning comes before the disk is full, not after.
- Expected ports. Every role lists what may be open to the outside. Only what isn't on the list gets reported. On the first run that was four places across six machines, each of them a real question.
- A page per machine. With history, space usage, ports and a "Clean up now" button for everything the role allows. That one asks for Touch ID too.
What I take away
- The real problem was noise, not a lack of intelligence. Six smart agents without a shared place add up to six conversations. A rule like "one entry per topic, a no holds for 30 days" did more than any bigger model.
- Humans decide, machines run fixed commands. The agents may propose anything. Only what is in a catalog and what the machine's role allows gets executed, and only after I approve it.
- Measure first, then write rules. The thresholds and roles came from the real values of all six machines, not from assumptions. That is why the first run was useful instead of loud.
- Small local models are enough for background work. Meaning search and fact extraction run on the server's CPU, no cloud and no per-call cost. Slow, but at night that doesn't matter.
- Limits belong in the documentation. Where the passkey protection ends, where the measurement misleads: that is written down right next to it, not in the fine print.
I built this together with Claude Code, in a handful of sessions over five days at the end of October. The agents wrote most of the code. What they did not take off my hands were the questions of what gets measured, what a machine is allowed to do, and where the line between proposal and execution lies. And that is exactly how it should be.
By the numbers
| Metric | Value |
|---|---|
| Machines in the control room | 6 (4 Macs, 1 Linux PC, 1 server) |
| Sync | every 15 minutes, health check daily |
| Entries in the shared memory | around 1,900, all with a meaning vector |
| Proposals on the first run | 16, 3 of them urgent |
| Approved and executed | 4 cleanups, about 78 GB freed |
| Backup | daily, 14 days, restore tested |
What about you?
Need something like this for your company? Or just curious how it works in detail? Write to me.
→ Email [email protected], the subject line is already filled in.
→ Book a 30-minute chat if you'd rather talk directly.
Tags:
AIClaudeHermesTailscalePasskeysSelfHostingBuildingInPublic
Ulrich Diedrichsen
Software architect & product builder
Professional software work since my computer science studies. Ex-IBM, ex-PwC. Now building products with AI in Hamburg.

