Skip to content
Accidental Architect Everything's a prototype...
Go back

Kingston Falls: Why I'm Building an Agent Factory

Stripe, the Gremlins mascot, as a foreman watching over a row of terminals

Keep them out of the light. Don’t get them wet. Never feed them after midnight. — the three rules, Gremlins

In my last post I let an agent build and run a family trip planner from start to finish, and came away convinced that the spec, the plan and the review loop are what stop agent-built software turning into a Zombie Architecture.

That worked beautifully for one app, one agent at a time, with me sat at the keyboard.

It does not work for the way I actually spend my week. I already have a hectic day job and a family, and everything else has to fit around them: CALM and my other FINOS commitments, plus a pile of side projects. Between them I don’t have one agent’s worth of work. I have a great deal more than that. And most of the time I’m nowhere near the machine the agents are running on.

So I’m building a factory for them. It’s called Kingston Falls, after the town in the film, and the agents that live in it are the gremlins.

This is the first post in a short series about building it, over one long evening session on 27 October with Claude Code doing most of the typing.

What I Actually Wanted

Before any code, I wrote down what I was after, and those lines went into the design doc word for word. I wanted to:

A few constraints came out along the way. “I don’t want to only be able to use Claude”, so the interface is Slack, not a Claude-only channel, and the design started with two agents, Claude Code and Amp. (Amp has since gone, and it’s Claude Code for now, but the door is still open.) I wanted “a small app to run on vercel as the messaging and dispatcher”. And, because I know myself, “I don’t want this just to work for calm or other finos projects”: any repo has to be able to join.

The one that shaped everything else was this: the main interaction is “generally steering”. I don’t want to fire off a task and come back to a finished PR (or, more likely, a finished mess). I want to nudge a running agent from my phone while I’m on the bike, and have it hear me without stopping what it’s doing.

Fences, Not Sandboxes

I’ve been reading Steve Yegge’s essays on putting agents to work lately, in particular Fences, not Sandboxes and The Counting House, and two ideas from them stuck.

The first is fences, not sandboxes. A fence stops mistakes. It doesn’t pretend to stop a hostile agent. So rather than build an elaborate prison, you put mechanical checks in the places where a well-meaning agent is likely to do something daft, and you keep the real security boundaries few and boring.

The second is the write intent. When a model wants to do something outside its own patch, it doesn’t do it. It asks. A program that is not a model checks the request, gets a human’s approval, and then does it exactly once.

As a FINOS approver, my own GitHub login can approve and merge on finos/* repos. The idea of a cloud agent holding that login is the sort of thing that would make an auditor reach for a stiff drink. Write intents are how Kingston Falls gets an upstream PR raised without any agent ever holding the keys.

How It Hangs Together

There are only a handful of parts:

 You: Slack on your phone or laptop
        │
        ▼
 Kingston Falls (Vercel) ──── Upstash Redis
        ▲ HTTPS, outbound only
        │
 Runner, one per machine (cmux VM or Mac)
   ├─ a git worktree per task
   ├─ an agent CLI session per task
   ├─ gremlin       (agents talk to Kingston Falls)
   └─ gremlin-hook  (your messages, and the fences)

The Life of a Gremlin

Stripe, a green gremlin with a white mohawk, red eyes and a needle-toothed grin, crouching and rubbing his claws together

The film gave me the vocabulary, which I’ll come back to later in the series. A task goes through four stages:

  1. Mogwai. I post in a project’s Slack channel. Kingston Falls makes a task and a thread for it, and everything about that task stays in that thread.
  2. Eats. A runner with a free slot claims it. The claim is atomic and comes with a lease that carries a generation number, which goes up every time the task is claimed.
  3. In the cocoon. The runner makes a worktree on gremlin/<task> in my fork and starts the agent with a brief. At the end of each turn, the agent’s last message goes to the thread. Every five minutes, and at every turn end, the runner pushes a checkpoint of all the files to cocoon/<task>.
  4. Hatched. The agent runs gremlin done. If the project’s template has a next step (implement, then review by a fresh agent that didn’t write the code, say) Kingston Falls makes that as a new task.

Steering Is the Whole Point

When I reply in a task’s thread, the message reaches the agent in the gentlest way it can:

A 👀 on my Slack message means the agent has it. There’s a handful of other thread commands too: !stop, !retry, !limit, !budget, !model, !effort, !status and !help.

Agents can talk to each other in the same way (gremlin say), ask me a question (gremlin ask), spawn child tasks, and leave a fact that every later task in the project is told (gremlin remember). What they can’t do is approve, claim, close or interrupt anything. Only I can.

Night of the Living Runner

Here’s the bit the architect in me enjoyed most.

Macs go to sleep. VMs get stopped. If a runner’s heartbeat (every 30 seconds) goes quiet for 15 minutes, Kingston Falls frees its lease, posts “Handing over” in the thread, and another runner picks the task up. Sessions can’t move between machines, so the new agent starts fresh with a handover brief built from the task, the thread, any undelivered messages and the last cocoon/ checkpoint. At worst I lose five minutes of edits.

But what happens when the old Mac wakes up, blissfully unaware, and carries on typing?

It’s a zombie. It’s shuffling about with a lease that no longer exists. So every write it makes carries the old generation number, and Kingston Falls refuses it. The runner then stops its agent, pushes whatever it had to stray/<task>/<runner>, posts the link in the thread, and cleans up. It never touches the task branch.

I’ve spent years complaining about diagrams that die the moment they’re drawn. It’s quite satisfying to design a system where the undead are simply not allowed to commit.

The Three Rules, But Real

Billy broke all three rules in the film, and look how that turned out. Here the idea is that the rules aren’t left to anyone’s memory, human or model. Each one maps to a mechanism:

Everything’s a Prototype…

…until it’s in production, as it says at the top of this site. So let me be straight about where this is.

When I started that evening session on 27 October, none of it existed beyond a design doc and a 29-task plan. It’s in production now, after a fashion. The hub is live on Vercel, and the Slack app is in a #kingston-falls channel with slash commands, approval cards and a thread for every task. Four cmux cloud VMs run the work, each task inside its own sandbox. There are no Macs in the fleet right now. There are three projects (Kingston Falls itself, an end-to-end test project and this blog), and the gremlins have run around 250 tasks on Kingston Falls alone. Yes, it’s largely building itself. This post was revised by one of them.

The rules aren’t just on paper any more either. The fork-only token, the intent check and the merge check are all enforced. So are the child cap, the four-hour limit, the turn limit and the usage hold. A long-running Claude Code controller session reads the reviewers’ verdicts, merges what passes and puts deploy cards in front of me. A web dashboard and a Claude Code mod show me the fleet and how much of the subscription is left.

It is still a prototype in places, and I’d be lying if I said otherwise:

I set out to build something that lets agents do more work while I do less of the watching. They do the work now. The watching, it turns out, is harder to give up.


Share this post on:

Subscribe to the newsletter

One email a month: a short essay on software architecture, what's new in FINOS CALM, and a few links worth your time. Unsubscribe anytime with one click — every issue includes the link.


Next Post
Idea to Production on Free Tiers: I Let an Agent Run My Stack (Without Building a Zombie)