Back to Blog

Electra v1: The Agent Orchestrator I Built to Find Out What I Wanted

An always-on host running a Telegram-fronted agent gateway and a task orchestrator, dispatching coding agents across isolated identities. It worked well enough to show me what I actually needed instead.

Agentic CodingOrchestrationSelf-HostingLinux

Electra v1 was an experiment that ran for real. One always-on Linux host in my homelab running a coordination layer: a Telegram-fronted agent gateway I could message from my phone, and a task orchestrator with an embedded Postgres behind it. Between them they dispatched coding agents across two isolated identities, personal and work, keeping the credentials and the context separated at the operating system level.

I called it v1 because I assumed there would be a v2. There will be, but it is not going to be a version of this.

What it got right

Messaging is the correct interface for an agent. Not a web dashboard, not a terminal I have to be sitting at. I would be somewhere else entirely, think of something, send a message, and come back later to a branch. A chat client instead of a UI removed the requirement to be at a desk to start work, and that changed how much got done more than any model upgrade did.

Identity isolation belongs to the operating system. Two identities meant two OS users, and that boundary is real in a way that an application-level check is not. Nothing in the personal context could reach the work credentials, because the kernel said so.

A human opens and merges every pull request. This was the invariant I refused to relax, and it is the reason the whole thing was safe to run unattended. Agents work on branches. Branches become PRs. A person reviews and merges. The system could be completely wrong about something and the blast radius was still a branch nobody merged.

I have not found a good argument for loosening that, and I have been looking.

What it got wrong

It was a pet. Every piece was configured by hand on one machine over months. When I wanted to add a second machine, I could not, because the knowledge of how it worked lived in my head and in a scattering of config files I could not fully account for.

That is what eventually killed it, and the death was instructive. I did an exhaustive read-only audit of the running system, reconciled what the machine actually did against what I remembered doing, and wrote it all down: architecture, a full inventory, sanitized templates of every config file, and twenty-five verified failure modes with symptom, cause, detection, and fix. Reconciling the two turned up a decent number of things I remembered wrong. Some of the design decisions I had to recover from old transcripts, because I genuinely could not remember why a thing was the way it was.

Writing that document was more valuable than the system. It is the difference between something I ran and something I could rebuild.

Scheduling was naive. Work went to whichever agent was configured for that context. There was no notion of which model or account was actually good at a given kind of task, no measurement of whether a result passed, and no awareness of quota until something hit a wall mid-task.

It could not use what I already had. I pay for several model subscriptions and own several machines. Electra used a fraction of that, because everything was pinned to one host and one configuration.

What it made me want

The list of complaints turned out to be a specification.

If placement should depend on which model actually succeeds at a kind of work, then routing has to be driven by measured pass rates against verification gates, not by a hardcoded mapping. If quota keeps interrupting, quota has to be tracked live rather than discovered on failure. If machines should be addable, each one needs a daemon that dials out and advertises what it can do, with the scheduler placing work against declared capability. If it should use the subscriptions I pay for, those have to run through their official interfaces, which is both the supported path and the honest one.

So I am building that. Different architecture, different scope, and this time the documentation gets written first instead of recovered afterward.

The point of a v1

Electra was never going to be the final thing, and it was not wasted. It was the fastest possible way to find out what I actually needed, which is a different question from what I thought I wanted when I started.

The bit I would tell anyone doing something similar: keep the human in the merge path, put the isolation boundary somewhere the kernel enforces it, and write down how it works while it is still running. The last one is the one I nearly got wrong.