Anton, chapter 6: The sandbox, the mesh, and the cost of cleverness
2026-03-27 → 2026-04-14
Across several long coding sessions, Anton starts moving beyond a single personal server. That changes the questions I need to answer: how much authority should an agent have, how much access should a skill have, and where is an LLM actually worth using? A few decisions from these sessions end up defining most of the current architecture.
I start with the skill runner. The Node skill-runner I built earlier has no runtime isolation: a skill can read any env var, exec anything, hit any URL. For a personal server this was tolerable. For anything more, it's not. So I rewrite the runner on Deno. Each skill runs in a Worker with the minimum permissions it needs and nothing more. The rewrite spans roughly 25 commits over two days, because Deno's strict execution model exposes every implicit assumption Node was letting me get away with; each commit unblocks one more skill that never previously had to care about isolation. By the end I have a two-boundary security model written down. Agent boundary: who can invoke which agent. Skill boundary: what this code can do. Two boundaries, two questions, neither one swallows the other. While I'm there, secrets move into one encrypted Postgres table and reach a Worker only through postMessage, never the parent process env. A permission model is only as honest as the boundary you actually defend.
At the same time, I begin connecting Anton instances through a mesh. I want Anton instances to find each other: not share a database, not share secrets, just find each other and forward calls. The contract is simple: the instance is the identity, and the relationship between two instances scopes what one may ask of the other. A clone running for a different household can ask my Anton to run a media query without ever seeing the wine collection or the family vault. Federation as relationships, not as shared infrastructure.
I also want to stop writing a separate brittle browser script for every website. Three sites were each a hardcoded Playwright script with copy-pasted intent and brittle selectors. I replace the pattern with one generic browser agent: navigate, click, type, screenshot, and let the LLM drive. Three hardcoded scripts deleted in one afternoon. The principle that comes out is the one the whole period keeps teaching: explore agentic, build deterministic. The LLM is fantastic at finding the right button on a page it's never seen. It's overkill, and expensive, for the same flow you run twice a day. Use it to scout, then write down what it found.
The building-management domain is where I begin applying that approach repeatedly. The first cut of document extraction was vision OCR over every PDF: slow and expensive. A second pass replaces it with plain text extraction first and vision only where text comes back garbage, ten times faster on 90% of files. Then the swap I'm most pleased with: the syndic portal was being driven by the browser agent, and a morning of reverse engineering reveals that every screen is just an HTTP call to a stable backend. The browser agent comes out, a direct HTTP sync goes in, and bank reconciliation auto-matches 99% of statement lines in one pass. The same rule then gets stress-tested on my own vanity: a four-hour spike drives train-departure lookups through the browser agent, it works, I do the cost arithmetic, and I revert it, because a deterministic path exists and the agentic one is roughly 100× more expensive per run. The revert is itself the lesson. Cost discipline beats cleverness, applied to my own code two days after I wrote the rule down.
Cost becomes a first-class concern in the same window. Every provider call carries a per-request token budget and attribution metadata: which agent, which domain, which user. Memory consolidation moves from every-write to a nightly batch because the old shape was contributing real money to the per-request bill and nobody had asked for it. When a provider's billing hiccup takes the primary model down mid-day, an auto-fallback lands the same afternoon. If a provider is your single point of failure, your system is your provider's reliability, not yours.
I also begin building a feedback loop I have wanted for some time. Anton starts critiquing his own performance: a nightly review reads the day's execution traces, classifies failures, and files an issue per cluster. This is only possible because traces are honest, full rows of what the LLM actually thought and called, not summaries of outputs. And a heartbeat starts ticking: a background survey loop that checks operational state and only speaks when there's something to act on. It looks; it does not do. Every outbound message, whatever produced it, now leaves through a single gateway with an audit trail. One chokepoint, one log.
By the time I come up for air, the shape is set. Skills run sandboxed with minimum permissions. Secrets live in one encrypted table. Any site with a form is a browser-agent target, and anything run twice becomes deterministic code. Every night Anton reads his own day and files the work to fix it. The system is now big enough that its operational concerns are first-class, and the rule threading through all of it is the same: figure out the cheap path, reserve the expensive path for what actually needs it.