For most of this spring I ran two AI coding agents, and I had them in the wrong order.
One lives on my Windows desktop, in a sandbox. It reads a synced copy of my knowledge base, a git repo of rules, decisions, and changelogs that every agent I run is supposed to consult. The other is Claude Code on a Linux VPS, reachable from Discord on my phone, sitting on the same machine as the actual code, databases, and cron jobs.
The desktop agent was my primary. The justification felt obvious: I'm already at the desk. The window is already open. Why route a question through Discord to a server when the assistant is right here?
The failure mode that broke the default
The desktop agent kept being confidently wrong in a specific way. Not hallucination, exactly. It would answer questions about my systems from the synced knowledge files, fluently and with total assurance, and the answer would describe how things worked three weeks ago.
The cause is structural. That agent reasons from a copy of the notes and has no runtime that can falsify it. It can't run the query, grep the live config, or watch a service fail to restart. When my notes sound settled, its answers sound settled, regardless of whether reality has moved. I started calling this fluent-but-stale overconfidence.
The server agent has the opposite property. It gets contradicted by the machine mid-task. It claims a cron exists, lists the crontab, finds it doesn't, and corrects itself before I ever see the wrong version. The feedback loop is built into where it sits.
Asking three models to attack the question
I didn't trust myself to re-derive the split, since "I'm already at the desk" had survived months of my own judgment. So I ran the question through an adversarial review: one model proposes the division of labor, a second attacks it, a third reads the full exchange and rules. Three rounds.
One claim survived every round of attack intact, and it's the one that reordered my setup:
The desktop agent's edge is a residential IP and an authenticated browser session. Not the visible cursor.
I had been valuing the desktop agent for the wrong asset. Watching it move a mouse across my screen feels like capability. But server-side browser automation replicates the cursor just fine; I run headless Chrome on the VPS for all sorts of checks, though headless gets flagged more often, which is part of the same story. What the server cannot replicate is a logged-in browser session on a residential connection. Logging into vendor dashboards and account portals that flag datacenter traffic works from my desk and gets walled from the VPS. Everything else the desktop agent did, the server agent did with better information.
So the order flipped. The server agent is now primary for anything verifiable: code and its data, research that should be checked against live files, long-running jobs, anything where being falsifiable matters. The desktop agent kept exactly three jobs: things on my physical screen, local files that never sync, and logging into services that block datacenter IPs.
What I refused to build
The review's proposing model wanted to formalize all this with about seven new scripts: a task router, handoff tokens, a polling cron. The arbiter model flagged it as gold-plating, and it was right. The boundary between these agents is mostly physical. The desktop sandbox literally cannot touch the server's code or databases. A boundary the hardware enforces doesn't need a routing layer on top. For a solo operator, every script I don't build is one that can't silently break.
The review surfaced one real bug as a side effect: my sync pipeline's mirror step assumed the desktop clone was never written to locally, which had quietly become false, leaving a window where a freshly written session log could be deleted before it ever shipped. The fix was one token in a git clean exclusion. That bug alone justified running the review, even though I rejected most of what it proposed to build.
Routing by falsifiability
The rule I ended up with: route work by what each agent can be proven wrong about, not by which agent is closest.
An agent with no runtime has no falsification loop, and it grows more confident as your documentation improves, because better prose reads as better evidence. The agent that can be contradicted by the system it sits on is the one whose confidence means something. Convenience disguised that for months; one sentence about IP addresses is what finally fixed the order.
I build my products solo from Indianapolis, almost entirely with AI coding agents, so I spend a lot of time thinking about where those agents should sit. More at fillipkosorukov.net.
Top comments (0)