Blog · Engineering

The real invention was turning a coding agent into a webservice.

By Michael Hairetis

I have spent the better part of a year building OpenRed, an orchestration platform that runs autonomous data operations on a schedule. It plans work, dispatches it to specialist agents, checks the result, publishes it downstream, and heals itself when something breaks. 136 scheduled jobs. 2,242 runs so far. Nearly 28,000 agent turns on the record.

OpenRed is the thing I set out to build. But the piece I am actually proud of is smaller, sits underneath it, and took the longest to see clearly.

It is a service I call gamma, and all it does is expose a native coding agent as a webservice.

That sentence undersells it, so let me put it the other way round. Everything above gamma, the scheduler, the pipelines, the orchestrator, the retry logic, the chat interface, is ordinary software. It is the kind of thing I have built many times. The unusual part is that when any of it needs judgment, it makes an HTTP call, and on the other end is a full coding agent with a role, a memory, and tools. Not a model. An agent.

Capable and callable were not the same thing

When I started, there were two ways to put intelligence in the platform.

The metered API gives you a model behind an endpoint. Clean, callable, easy to integrate. What it does not give you is the agent: the thing that reads files, runs commands, iterates on a problem, holds a role definition across a long conversation, and knows when it is finished. That whole apparatus lives in the CLI product.

I could have rebuilt it. Reimplemented the tool-use loop, the file handling, the iteration and the skills scaffolding, then paid per token for the privilege of running my own worse version.

Or I could take the agent that already exists and make it answer HTTP.

So gamma is a harness around the native CLI. It publishes one endpoint that matters: give me a role name and a prompt, get back that agent's answer. Everything upstream believes it is calling an ordinary API. It never learns otherwise.

Two things fell out of that, and both were bigger than I expected.

The economics inverted. The platform runs on a flat-rate subscription instead of per-token billing. At 136 scheduled jobs and roughly 190 runs a week, every architectural decision I would otherwise make to conserve tokens simply stops being a decision. I let agents be thorough. I let them iterate. I add a verification pass because it makes the output better, not because I have priced it.

I inherited a product roadmap. Because gamma wraps the real CLI rather than reimplementing it, every improvement shipped to that product arrives on my platform for free. Better reasoning, new tool handling, context management. I integrate none of it. My agents just get better between Tuesdays. That is a strange and very pleasant position to be in, and it is a direct consequence of co-opting the product instead of rebuilding it.

What actually runs on it

Ten named agent roles are registered with gamma. Eight do pipeline work, two are utility. Four of them, the orchestrator, the primary worker, the delivery liaison and the classifier, stay warm permanently because they are on the critical path. The rest wake on first use.

Each one is a persistent session, not a fresh call. It boots once, gets primed with its role definition, and keeps that context across every job it handles. When the orchestrator hands the worker a brief, it is handing it to an agent that already knows what it is and what it did earlier today.

Those roles compose into five pipelines, from a two-phase fetch-and-publish up to a five-phase build with validation, reporting, notification and archival. A scheduled job names a pipeline, the pipeline names its roles, and gamma supplies the agents.

The classifier is the part nobody expects

Here is the thing that changed how I write code.

Somewhere in every system I have ever built there is a function that has to make a judgment call from messy input. Which category is this? Did that actually succeed? What kind of failure is this? The traditional answers are a chain of if statements, a keyword list, a regex, a lookup table, and they are all the same answer wearing different clothes: enumerate the cases in advance and hope reality complies.

Reality does not comply. You ship the regex, it works for a month, then something arrives phrased in a way you did not anticipate and your code confidently does the wrong thing. So you add a branch. Then another. Eventually the function is four hundred lines of accumulated special cases that nobody can safely modify, and it still cannot handle a sentence it has not seen.

Gamma let me stop writing those. When OpenRed needs a judgment now, it calls the classifier and gets a structured answer back. Not a chat interface: a function call that happens to have an agent behind it.

The last two could not have been written the old way at all. Not "would have been tedious." Could not. There is no regex for did this satisfy what the person meant.

But I do not lead with the agent. The failure-classification path tags every verdict with its source: mechanical, classifier, or fallback. Cheap deterministic checks run first and settle the obvious cases without a round trip. The classifier is what happens when the deterministic layer says I do not know, and there is still a dumb fallback beneath everything in case the classifier is unreachable.

That ordering matters, and it is the opposite of how people usually reach for a model. The model is not there to replace the logic. It is there to handle the residue the logic was always quietly getting wrong: the long tail you used to absorb with another elif.

What this actually is

The framing that matters is this: a coding agent is a general-purpose judgment primitive, and it can be called from code.

We have been handed extraordinarily capable agents and we mostly use them by typing at them in a terminal. That is a human interface to a thing that does not require a human. The moment you put an HTTP endpoint in front of one, it stops being a tool you use and becomes a component you build with, something a scheduler can invoke at 4am with nobody watching.

OpenRed is what I built with it. The scheduling, the pipelines, the self-healing, the 136 jobs. That is the application. But the reusable idea underneath is smaller and more portable than any of it: take the capable agent that already exists, wrap it so your code can call it, and then stop writing the functions that were always going to be wrong.

The invention was not the platform. It was noticing the agent did not need a human in front of it.

This is the engine behind our builds. The architecture described here is what runs every OpenRed client automation — see the services page for what it does in plain terms, or book a free 30-minute call.

More from the OpenRed blog