$ cat on-background-agents.md

cd ..
on background agents

on background agents

read about my experience building a rudimentary background agent

ive been spending a couple of my past weekends, absolutely obliterating my claude weekly sessions, hacking away at this:

meet knight, my new intern. (try it out at knight.zorro.works)

all i do is tag him in github issues, he grimly works on it, raises a PR when done, and then sits motionless in a docker container until its time to work again.

all this while i spend time watching movies or catching up on shows, waiting for knight to tag me back.


building knight

ill be honest, i found out about background agents a couple weeks ago, a day or two before i started working on knight actually and as such im still trying to figure it out from first principles.

here’s the architecture i came up with:

knight flow / architecture

the orchestration layer

the first thing i started working on was the orchestration layer, its powered by celery and redis. redis holds enqueued tasks and passes them to celery which distributes them across multiple workers.

the cloud layer (and why it exists)

the original plan was to have everything run locally in a single dockerized container that is fully self-contained so all you had to do was pull the docker image and set up your env files. i got that working, but then i ran into a wall: i wanted knight to be something anyone could actually use, and setting up github webhooks from scratch is not a cakewalk. it requires a publicly accessible endpoint, configuring the github app, handling secrets, and a bunch of other prerequisites.

so i added a cloud layer. now, the server handles all of that for you, you just run the cli, log in, and it gets a token and starts communicating with the server.

the other benefit that i didn’t calculate for was resumability. if your machine is offline and a webhook comes in, you miss it. with the cloud layer, events get stored in the database and whenever the worker comes back online it can ping the server and ask for available jobs or if for some reason the worker terminates in middle of a job, it would be able to pick it up again. no events are lost in the void anymore.

that said, this was a massive refactor of the original codebase and it does mean there’s a cloud dependency i’m not entirely happy with. i do intend to make the server runnable locally as well (eventually), so you could self-host it (i’m currently hosting it on cloudflare workers) or run it entirely on your own machine. that’s just a later priority.

worktrees and parallelism

the workers pick up tasks, spin up sandbox git worktrees and invoke pi, an open-source coding agent CLI, with instructions from the github issue it was tagged in. once pi is done with the implementation, it conducts a self-review of the changes and then raises a PR.

worktrees were the natural choice for parallelism. each worker gets its own isolated worktree, a separate working directory pointing to its own branch, so multiple agents can work on different issues simultaneously without stepping on each other. no shared state, no merge conflicts mid-task, each agent has a clean slate to work from. this was completely inspired by cursor’s agents and their use of worktrees.

finding pi

the original plan for invoking the coding agent was to write one myself. then i found pi.

i was digging through codebases trying to figure out how others had approached this problem when i noticed another background agent framework using pi. i went through their code to understand how they wired it up, turns out pi has an rpc mode that lets other processes communicate with it over a socket. for typescript/javascript you can call the coding agent directly, but for python that rpc mode is the bridge. so that’s what knight uses: python passes instructions to pi over rpc, pi handles the actual coding.

the fallback wouldve been writing my own wrapper around pi that translated python calls into something it could understand. thankfully it didn’t come to that.

building the cli

i wanted knight to feel like plug and play, so i spent a decent chunk of time building a cli so users didnt have to go through manuals and figure out the setup themselves.

this cli walks you through setup with a series of prompts (with options to select from wherever applicable), generates your env and config files based on your choices, and pulls and starts the docker container.

you can try it yourself:

bun add -g @prnsh/knight

or npm i -g @prnsh/knight if you prefer npm.


inspiration

parasyte is one of my favorite sci-fi works, whats stuck with me over the years is the following quote:

When I was absorbed into Gotou and became dormant… I experienced something extraordinary. I touched upon things that could be called ‘the universe’ or ‘the world’ from many different directions. Inside that state, I gained the ability to follow multiple paths of thought simultaneously, processing different lines of thinking in parallel.

(for some context, this quote is about the deuteragonist (migi - a parasite)‘s experience of living in a body with multiple other parasites)

this quote resurfaced a couple days into the build and had me reframe my vision for the project.

i started building knight on a whim because i’d just randomly stumbled upon the concept of background agents (even though they had existed for a while) and i wanted one of my own, that way i could offload simple tasks or features to the agent while i worked on more crucial aspects or when i was afk.

to expand further on the relevance of the quote, computing shifted the moment we figured out multi-core processors, and i think we’re at a similar inflection point with agents. and none of this is actually profound, honestly it’s just the “apes together strong” meme personified (agentified?) but something as simple could be the start of something incredible.

going forward, all we need to do is figure out how to build workflows that let us:

  1. direct these agents well without being verbose and micro-managing every action
  2. them to be in sync with the users such that their thinking process / rationale behind decisions would resemble that of the humans orchestrating them

as for knight, i think one of the key goals i have is to introduce proactivness i.e. can knight suggest ideas, discover bugs and even improve something that requires “taste” like ui/ux on its own with end users in mind. that’s probably what ill try and experiment upon whilst improving the current version.

you can try out the current version of knight here: knight.zorro.works

created: 2026-05-12T00:00:00.000Z last modified: 2026-05-12T00:00:00.000Z estimated read time: 6 min