ed@edheltzel: ~/log/agent-does-not-own-the-workflow
ed@edheltzel:~/log$ cat agent-does-not-own-the-workflow.md

Your agent does not need to own the workflow

Phosphor Blip pressing a punched card into a switch-box

Most of the agents I see billed as autonomous are a language model sitting on top of a switch statement. Dex Horthy wrote that down in 12-factor agents. I keep running into the same shape. This is a reading of that guide. The text is CC BY-SA 4.0. It is not a dump of the twelve headings.

The useful part is smaller than the pitch. The model turns a sentence into a structured next step. Your code decides whether that step runs, how it runs, and what happens after.

Natural language in, a typed object out

Horthy’s first factor is the whole trick. Someone asks for a $750 Stripe link. The model does not “use Stripe.” It emits something your code can switch on: create this link, for this customer, with this memo. Ordinary code picks up the payload. Mailcrew is the worked example. Stripe still wants real customer and price ids. You look those up in code, or you put them in context on purpose.

Anthropic’s Building effective agents draws the same line from the other side. Workflows are code-directed. Agents are model-directed loops. A lot of products called agents are workflows with one LLM step in the right place. That is not a failure. That is the design.

A tool call is JSON you chose to honor

Factor 4 is the unglamorous version of tools. CreateIssue and SearchIssues are not magic bindings. They are shapes. The model prints JSON that parses into one of those shapes. Your switch statement may call Linear, or wait, or refuse. A tool call is a request, not a promise that the matching function will run.

That is why the JSON-mode vs function-calling vs constrained-decoding argument is secondary. Boundary on schema-aligned parsing and Vellum’s comparison are worth reading if you are picking an API. The product decision is still the same. The model names an intent. Your code owns the side effect.

Keep the model on a short leash

Factor 10 is why you should not hand the whole DAG to one loop. Longer tasks mean longer context. Longer context is where models lose the plot. Horthy’s range is a handful of steps, maybe twenty. Treat that as a smell test, not a law. NotebookLM’s team said the interesting work sits near the edge of what the model can do consistently. Past that edge you get fluent wandering.

If models get better at long jobs, you still want small agents. You grow the slice of the DAG they own. You do not throw away the surrounding program. Same lesson as refactoring a large deterministic codebase. Expand the module that earned it.

I keep the model proposing and the program disposing. One agent, one job, short enough that I can read the thread. The rest stays in code I can test without an LLM.

Next: the context window is an application interface.