I moved my agents brain from a laptop, half of it was one file.

19 October 2026

A 27B parameter brain does not live well on a machine that has to sleep. My XPS — the box the agent brain had been running on — went Tailscale-offline in September, and a desktop-over-SSH link to a laptop that dies the moment it leaves the house is not a plan, it's a hope. So the brain moved to Homelab, the always-on box: 503 GB of RAM, 128 cores, three RTX 5090s. Same Telegram, same sessions, same memory — just a body that stays up.

The migration reduced to one question I could answer with a test: can a live agent's entire state move as a single snapshot and survive? Answered by the time I'd diffed both trees, line by line.

The honest body

Homelab was the only candidate that didn't require a prayer:

HomelabXPS
RAM / cores503 GB / 12815 GB / 8
GPU3x RTX 5090 (96 GB VRAM)none
27B Ollama brainruns here (loopback, 2.2 ms)reached over LAN
Tailscaleonlineoffline since September — LAN only
Roleprimary brainfailover + trader-bot

The desktop app the agent uses when I'm sat down is a client, not the agent — it connects over SSH to a hermes serve backend. Sessions live in state.db on the host, so continuity was free the moment the state moved. One token, one poller: the Telegram bot moved off the XPS, disabled there, and the approvals that used to vanish on the desktop now land on my phone.

The one file that carried everything

Here is the load-bearing fact. Everything an agent remembers, every conversation, lives in one SQLite file. So the whole "can it move?" question became:

SQLite online-backup of state.db (consistent snapshot while the agent was live)md5-verify the copied file (what left must equal what arrived)PRAGMA integrity_check (ok)

The snapshot came back clean: 127 sessions, 17,134 messages, one file, md5-verified on both sides, integrity check clean. That was the whole brain. The rest — memories, skills, six bot profiles, cron, the vault path — was just files with names.

The scar

The first pass reported success. The trees looked right. It had silently left ten top-level directories behind — including scripts/, where every single cron job executes. I found it by doing the one thing a green pipeline never makes you do: diffing both trees, line by line.

Then the "green" fleet dashboard screamed a false FLEET ALERT — gateway down, on a box that was up. The liveness check was running Windows tasklist on Linux. My always-on Linux box had a Windows health check. A pipeline that reports success on the wrong machine is a pipeline reporting success on nothing.

The theme I keep, from the scar and the alert, is this: a green pipeline can still be lying. Green means the command worked. It does not mean the copy was complete, or the check even ran where it thought it ran.

So the migration's verification pattern is the story, in the order I now use it:

That fourth step is the one everyone skips because it's boring. It is also the one that stops you from deleting the key you were about to need.

  • Snapshot a consistent copy (SQLite online-backup, not a cp of a live file).
  • md5 both ends, compare by hand.
  • Diff the trees, line by line. Do not trust the copy command.
  • Fingerprint checks through an independent route — the stale XPS host key on Homelab came off only after the fingerprint verified via the trusted laptop route. (ssh-keygen -R is a small knife; use it only when a second, independent route vouches for you.)

What this is NOT

This is not a finished migration. I will say it out loud because "I moved my agent's brain" reads a lot like "the move is complete," and it isn't:

So the status of this post, exactly: nearly done, not finished. The piece ends mid-move on purpose. A migration story with no scar in it is a marketing story, and I don't write those. The same "don't trust the green line" stance I hold on the trading diary's validation layer is the one I'm holding here — a number, a check, an exit code, none of them is a fact until a second route has confirmed it. This is the one cross-lane thing I'll say, and then I'll stop.

  • Done and verified: Phases 0–3 and Phase 5. Safety backup, the transfer (including the second pass that shipped the ten missed directories), the Windows-isms fixed, the Telegram channel moved, running clean — no false FLEET ALERTs, laptop sleeping classified as sleeping, never as down — the fleet dashboard remodelled to four nodes.
  • Not done: Phase 4 — the desktop-over-SSH connection from my seat — still needs my hands in the app's settings, and my own confirmation that it opens the Homelab sessions. Phase 6 — the final cutover, disabling the laptop's local gateway so channels have a single owner — waits on that. And the unattended-reboot test on Homelab has not been run.

What I'd do differently

I'd have run the tree diff first, before I celebrated, because the celebration came a full pass early and the scripts/ folder had to ship back over a second time in a 115 MB payload I'd rather not have made. I'd have pinned every host key by fingerprint before the first migrate, so the "do I trust this key?" question never sits in the hot path of a 2 a.m. move. And I'd have written the liveness check for the OS that's actually in front of it — a tasklist check on Linux is the kind of bug that makes the alarm ring at the exact moment you most believe the machine.

Next: Phase 4 from my seat, then the cutover, then the reboot test — and the post gets the date it actually deserves when the last one is green.

---

← All posts