Hermes, the orchestrator, and the art of walking away
I’ve been building this AI development pipeline for a while and I think it’s finally worth writing down how it works. The short version: I plan with an AI on Telegram, then walk away while autonomous agents implement the feature on a VPS.
The split is the whole point.
Phase one is all conversation. I talk to Hermes (my agent framework) through Telegram — just messaging back and forth, refining the spec until it feels right. No markdown files to edit, no PRs to open, no ceremony. Just me and an AI iterating. When I’m happy, I type one command.
That command kicks off the orchestrator. It’s a custom Python CLI I built called opencode-orchestrator. It takes the spec, passes it to a cheap drafting model for plan generation, then sends that plan to a different (heavier) model for review. Same content, two perspectives, different providers — I’ve found this catches way more blind spots than any single model can.
Once the plan is reviewed, the orchestrator shards it into tickets and starts executing. Each ticket gets an OpenCode worker in its own git worktree — isolated, parallel where dependencies allow. The worker implements the ticket, runs the tests, and reports back. Then the review model checks the result. Pass or fail, the orchestrator advances the queue automatically.
The model split is the part I’m most proud of.
For drafting (plan generation, ticket implementation) I use OpenCode Go. It’s $10/month and fast enough that I don’t think twice about running it. For review I use a completely different model from a different provider. The orchestrator enforces they can’t be the same, which stopped me from cheating and using one model for everything. It’s made a real difference — the review model regularly catches things the drafting model misses, especially around edge cases and non-functional requirements.
Real example.
I ran this on the orchestrator itself recently. The feature was a --version flag. The spec said it should print a version number, and the drafting model implemented exactly that — hardcoded the version string. Tests passed. But the review model flagged it: “This should read from pyproject.toml, not be hardcoded.” I hadn’t even thought to specify that. The orchestrator kicked the ticket back for a fix, and the second pass got it right. That’s the whole philosophy in miniature — two models, two perspectives, better outcome than either alone.
It’s not all smooth sailing.
The orchestrator hit a real bug on its first contact form run. A VPS reboot left a ticket in an ACTIVE state, and resume crashed because the state machine didn’t allow transitioning from active to active. The fix was a one-line change in the state machine, but finding it required digging through logs, worktrees, and process tables. I wrote it up, fixed it, and the next run worked. These are the growing pains of running your own infra — and I kind of enjoy them.
The Telegram integration makes all of this feel effortless. I don’t need a dashboard or a web UI. I message Hermes, we shape the feature, I drop a resume command, and the VPS does the rest. I can check orchestrator status anytime, but mostly I just wait for Hermes to ping me when it’s done. It’s the closest I’ve come to the “describe the feature, get the feature” loop.
I’m still adding to it. Better worker monitoring, smarter retry logic, maybe a proper dashboard at some point. But for now, this pipeline lets me go from a Telegram message to a working PR without touching a file myself. That’s pretty wild.