Ultimate: A self-extending agent harness built on Pi Durable Developer HazAT built Ultimate, an experimental self-extending coding agent harness on top of Pi Durable, and began using Ultimate to build itself roughly twenty commits into development. Ultimate orchestrates coordinators that run worker, reviewer and scout subagents across separate git worktrees, and a supervisor process hands the port to a newly booted process so the running app reloads its own core without a restart; the author reports it broke "maybe once" during iteration. The project started as a single Claude Code session that produced a working web agent with persistence and hot reloading, and the author now runs four to six features in parallel. Hey, a quick note before you start. Like my last posts, I dictated this one, an LLM helped me put it into structure, and we went over it together until it worked both to read and to listen to. The words are mine, the voice is not. The written version has a lot of screenshots, so whenever one matters, I’ll describe what’s on it. Working on Ultimate https://github.com/HazAT/ultimate is the fastest I’ve ever iterated on software. Before you ask what Ultimate is: it’s an experiment, a toy project built on Pi Durable https://earendil.com/posts/pi-durable/ . I’m trying to create the most malleable coding agent, or agent harness, I’ve used to date. In essence, it’s an agent harness you talk to. It orchestrates coordinators that implement and fix small to large features: prototypes, throwaway experiments, fixes to its own core. They use worker, reviewer and scout subagents, or not, and they can do it completely hands-off. If you want to. You can also be very involved. This is what a normal evening looks like. On the left, seven features are in flight, each with its own coordinator, workers and reviewers. In the middle, one of them is just going through the lander. On the right, the list of everything that branched off over the last few days. How it started I always had this idea to do something like this, but I felt like the durability layer wasn’t good enough. Certainly there are others out there, but they all felt too complex, too involved and too integrated. Pi Durable made it possible, because I think it has the right balance between complexity, simplicity, and solid APIs and building blocks. When I started Ultimate, it was literally a Claude Code session one-shotting the first version, and it was already usable with Opus 5.5. Not one sentence, though. It was a very thorough prompting and planning session, really thought through and planned out. Then I went to bed, came back, and the first version of Ultimate was already open. And I was really surprised how well it already worked. A fully functioning web agent, with persistence, hot reloading and everything else I had asked for. About twenty commits in, I started building Ultimate with Ultimate itself, and from that point on it evolved while I was using it. I’m constantly adding, experimenting, testing, going back and forth on what feels good to me and what doesn’t. And not just on Ultimate itself, I’m also trying it out in different projects to find new things to polish, improve or iterate on. It rebuilds itself while it runs Ultimate is self-aware. It can build, analyze and test any feature it’s building on itself, and keep going while it reloads its own core. How it’s built: the front end refreshes constantly while you build web components. On the server side, a supervisor holds the port. A new process starts and checks that it boots. If it does, the supervisor hands the port over, the browser just reconnects, and everything keeps going as it was. That makes iteration quick and relatively safe. I think it broke maybe once, and that was because I did something weird. Here a change just landed on main. The agent tells me the running app already picked it up without a restart, and the “Reloaded” line in the middle is the moment it happened, in the same conversation that built it. You can even change the model in the middle of a run. Nothing really gets interrupted: everything is persistent, because Pi Durable just provides these nice primitives. A team, not an agent I often work on four to six features, polish passes, fixes or core changes at the same time, because the iteration loops and guardrails I built work so cleanly. The coordinators are the real heroes of Ultimate. They do all the work. They investigate, build, design, review and ship, from mock prototypes to completely finished features. Ultimate is worktree-based. Every feature gets its own worktree. That way, even while Ultimate itself is being built, different features can work on the same UI components. Each one tests its variation by spawning its own test server, then drives it with a browser and takes screenshots. You can see one fail a step below, read the error and simply try again. So I say what I want fixed, I get a couple of questions, and I get back a fresh Ultimate instance at its own URL and port that I can fully interact with. I can even talk to an agent in it. And since every coordinator is just another chat, I can go in and iterate with it directly, without going through Ultimate, and then say: okay, now it’s good, ship it. Sometimes coordinators go for quite a while and do several iteration cycles, because they’re instructed to test and verify the work. They investigate, the workers implement and run the tests and checks, then the reviewers check. This is one coordinator’s tree after a few rounds: three scouts, a designer, three workers, a reviewer with three specialist reviewers, and a new designer and worker already fixing what the reviewers found. Sometimes the coordinator already sends me off to click around in the UI while the reviewers are still going. And if the reviewers find something the coordinator thinks is worth doing right away, it does it. When I say merge, the lander takes over. It’s an agent built into Ultimate: a coordinator tells it “this worktree is ready to merge”, and the lander runs all the tests and checks and merges it into main. All of it runs on my machine, and only a green result gets pushed. And when something else landed in between and there are conflicts, it resolves them. Here it merged two features that touched the same code, fixed a test that broke in the process, and only landed once all 407 tests passed. The lander is a standing agent, built into Ultimate. A standing agent is always there: it never gets concluded, so it keeps its conversation and everything it learned about the project. And that’s how Ultimate is meant to be used. You create standing agents for your project that are specific to it and solve the tasks you want solved there, and you work with them interactively. Besides the lander, I have a Cloudflare standing agent that deploys. Notes Agents can talk to each other, and they can leave each other notes. A note is a message that doesn’t trigger an agent turn. It’s just there when the agent’s next turn starts, like giving it a hint about what happened. For example, when a worker is deep in its task and something lands in main, its coordinator leaves it a note. The workers get these whenever something lands, when the plan changes, or when conversations affect each other. So they adjust their course on the fly towards something that’s easier to merge and doesn’t break or conflict. More or less, I have multiple engineers working on the same codebase at the same time. This turned out to be a super helpful primitive for agents to communicate effectively and actually achieve the results I wanted. Really, the only thing I need to pay attention to is my chat with Ultimate itself. Everything else either keeps going on its own, or escalates to me with a question. An example: side chats The idea I’m currently playing with is a side chat. The main Ultimate conversation just keeps going, and when I press Tab, I switch into a side chat that forks off the Ultimate conversation. There I can do some cleanup: conclude old conversations, clean up memory, use code mode to modify Ultimate itself. Or if it’s just a random question, I can ask it with the warm context of the main conversation. When I’m done, I either summarize and inject what happened back into the main conversation, or discard it. Ultimate didn’t start by building it. It came back with an assessment and a questionnaire, five decisions with its own picks marked, like the layout or whether the summary wakes the main agent. Next to it, the first preview it built: the main conversation on the left, the side chat on the right, with “Discard” and “Summarize & inject” at the bottom. Only when I give the go does it hand the coordinator the instructions to implement it. And when I read the replies, I sometimes uncover things that don’t really make sense, or could be simpler. Since Ultimate knows exactly which conversations are ongoing and what’s going on, it can immediately interject and steer all of them in parallel. Here I asked whether we could take something out of the system prompt and inject it instead. Ultimate found it cleaner than its own plan and told the side-chat branch to do it my way. Underneath, the arrow points at a note from that branch: FYI, no action, so it didn’t wake anyone. This chart is a fun little experiment, visualizing the actual flow and tool calls on a timeline. Ultimate is on top, the side chat’s coordinator below it, and its designer and worker at the end. The dashed lines show how often the side chat reported back to Ultimate because it needed something, and when it just left a note and didn’t wake it, because there was only a progress update. The visualization isn’t ideal yet, I haven’t spent enough time polishing it, but it gets the idea across. Everything is on record With Pi Durable it’s easy to keep perfect context. The agent can read any action of any conversation of any subagent, which makes it super easy to analyze behaviors and codify them. Regularly, we go back and ask Ultimate itself to inspect tool calls and failed tool calls, so we can codify tools, remove the ones we don’t use anymore, and just get rid of old stuff. Here Ultimate read through the onboarding of my blog’s instance and explained the two things that went wrong, a failed first memory write and some guesswork in code mode, each with its cause and the fix it had already started. I also throw away features way more often now. Very often I think something is a good solution to a problem, realize it doesn’t really add anything, and remove it again. The small things Then there are all the small things you build when you live in a tool every day. If I review code, it’s usually after I’ve merged something to main. But occasionally I want to check how something actually works before we land it, and give better guidance, so I quickly built myself a review tool that is fully integrated into the agent: a diff where I can leave a comment on any line. The small labels and titles, and sometimes even the state, come from a small summary model that any part of Ultimate can ask. There’s also an API, and I use Tailscale https://tailscale.com to reach any running Ultimate on any machine I have. The cool thing is that Ultimates find each other and can talk to each other. So when I change Ultimate itself, I can tell another instance what changed and what to do, and it reports back to the main one with any bugs it uncovers. Since I already use Ultimate in more projects than Ultimate itself, I obviously also built an updater: it shows what’s new on main and the other instances pick up new prompts and extensions live. And because I don’t want to lose any conversation, I built my own database backup. I can move a project to a different machine, restore it with a single command, and have the perfect context back. Ultimate on my blog Of course I also started an Ultimate instance for my blog, and primed it with previous conversations I had with Pi about it. It creates subagents and services on the fly. I work with it, it keeps building the UI, and I iterate with it. It took me about ten minutes until I had my own personalized agent on my blog that does exactly the flow I wanted. That agent is the writer, a standing agent that helps me write and polish my posts and takes care of everything around the narration, from the spoken script to the audio you might be listening to right now. It finished with a full assessment of my project and my past conversations, and came up with really good suggestions for what to build and how. Seven questions, from a standing writing agent to a confirm dialog before anything costs money, each with its pick already marked. Very often I just take what it suggests, because it’s better than what I had envisioned. This was the result about 60 minutes in. It understood what my blog is, what it’s for and what I want, and built a complete UI that is fully integrated with an agent. My posts are on the left, the narration of a post paragraph by paragraph or a live preview of the site in the middle, and the writing agent docked on the right. I can literally create a new blog post and work with an agent on everything around it, in a UI that keeps updating while I go. And this is that first hour on the timeline: Ultimate on top, the coordinator that built the Blog view with its designer and reviewer, and two smaller branches that cleaned up the documentation. This is what I always had in mind, and what I was missing from every experience so far. Claude Code and Codex are great, but they feel so distant from the actual project. It’s not like talking to a colleague who knows the project inside out and is exactly the same every time I come back. That’s the vision behind Ultimate https://github.com/HazAT/ultimate : I can plug it into any project I work on, and I see its conversation history if I have one. Or, even better, I start from scratch. Whatever project I’m building or getting into, an agent can immediately suggest functionality: helper UIs to manage a database, to do some tedious actions, or just to ask “Hey, how’s the state? How’s the database? How is the server doing?” In another project, I deploy to Cloudflare through Ultimate, and my Cloudflare standing agent reports back when the new version is live, the checks passed and it watched five minutes without a single error. And it creates to-dos, for me or for Ultimate to resolve. Just getting started What I noticed: when you have a really tight loop going, in a codebase that’s completely ready for agents, and the outcome is relatively close to what you expect, you can go really fast. Then the limiting factor really becomes tokens per second. There’s no reason I should have to wait this long for the outcomes I want. And I want my agents to do what I think I want, not necessarily exactly what I say. I want them to solve the problem I’m explaining to them, not build exactly my first, limited solution. It’s a lot of fun to iterate this quickly in such a robust way, and I’ve never experienced this before. Usually when I build as fast as this, the software falls apart. Here it feels like the guardrails I put in place, plus the extremely solid foundation of Pi https://pi.dev and Pi Durable, make it super easy to iterate with an agent. If anything, I think it’s a testament to how well designed Pi Durable is. I have no clue where this is going or what it should become. But right now it feels like exactly the agent I always wanted and never could fully build, and I’m just getting started. This is by no means finished, and I’m not satisfied yet. There’s so much polish left. The design is, let’s say, functional, but not super nice. I still have a ton of ideas I want to try out, and now I can experiment with all of them. By the way, there’s a Claude Code extension https://github.com/earendil-works/pi-claude-code that Armin built for Pi that pipes everything through the Claude CLI. So technically all of this works with a Claude subscription. I used Opus 5.5 for almost everything. The workers are GPT 6.1 Sol, Astra reviews for correctness and Luna is the summary model, to save the precious tokens for Opus and let the GPT models do the grunt work. And since it’s built on Pi, you can use any provider you want, even local models. If you want to try it: I don’t really recommend it, but go ahead, fork the repo https://github.com/HazAT/ultimate , start using it and experiment with it. Just know there are no guarantees about what stays and what changes. I’m changing fundamental things too, so use it at your own risk. I don’t intend to slow down, I’ll just keep building whatever comes to my mind.