12-Factor Agents: Patterns of reliable LLM applications โ Dex Horthy, HumanLayer
AI Engineer ยท video ยท 2026-10-08 Reader ๐ฅ๏ธ
Agent HarnessAgent Tool ManagementAgentic LoopAgentic vs. Deterministic System DesignContext EngineeringHuman-in-the-Loop
Reliable production LLM agents are built not by adopting an agentic framework that hides the hard parts, but by applying ordinary software-engineering discipline โ owning your prompts, your control flow (the loop/switch-statement/context-window triad), and your execution/business state โ to what is fundamentally a stateless-function (LLM) called inside a small, deterministic, developer-controlled loop.
practical ยท argumentative โ A conference talk distilling a published '12-factor agents' GitHub framework (borrowing the 12-Factor App naming convention) into a set of prescriptive engineering patterns for building production LLM agents, argued from the speaker's experience interviewing 100+ founders/builders.
Structure
| Part | Role |
|---|---|
| Opening anecdote: building a DevOps 'make-file' agent, hand-tuning the prompt for two hours, then concluding the approach itself was flawed | context |
| Origin story: interviewing 100+ founders/builders, noticing that the most successful production agents 'weren't that agentic at all' โ mostly software with a few key LLM-call patterns applied to existing code rather than a greenfield agent rewrite | evidence |
| Factor 1: natural-language-to-JSON as the one genuinely magical LLM capability; everything else is deterministic code built around that | evidence |
| Factor 4 ('tool use is harmful' as a provocation, modeled on 'Goto Considered Harmful'): tool calls are just JSON plus deterministic code, not an ethereal agent-environment interaction | evidence |
| Factors 8/5/3 bundled: own your control flow (the LLM-loop/switch-statement/context-window model), own your execution and business state (pause/resume via a state ID, REST/MCP-fronted), own your prompts (hand-write past the quality bar a library gets you to), own your context-window construction (arbitrary stringification, not just the OpenAI message format) | evidence |
| Contacting humans with tools / meet users where they are / small focused agents: push the tool-call-vs-message-to-human decision onto the model's first generated token; let agents be reached via email/Slack/Discord; keep agent loops to 3โ10 steps inside a mostly deterministic DAG | evidence |
| HumanLayer deploy-bot case study: a mostly deterministic CI/CD pipeline hands off single bounded decisions (which service to deploy first) to a small agent loop, with a human able to override mid-loop | evidence |
| Closing reframe: this is not an anti-framework talk but a 'wish list' for what frameworks should take off developers' hands (the non-AI-hard parts) so they can focus on the AI-hard parts (prompts, control flow, tokens) | conclusion |
Key terms
- 12-factor agents
A set of patterns (deliberately modeled on Heroku's 12-Factor App) for building LLM-based applications that are reliable enough for production, extracted inductively from observing what successful builders were actually doing to existing codebases rather than prescribed top-down. - tool use is harmful
A deliberately provocative framing (parodying Dijkstra's 'Goto Considered Harmful') arguing that treating tool calls as a magical, ethereal agent-environment interaction obscures the fact that a tool call is just an LLM emitting JSON that deterministic code then acts on โ demystifying it is what lets you engineer it well. - owning your control flow
Keeping the loop/switch-statement/context-window-building logic as code you write and can modify, rather than ceding it to a framework's internal agent loop โ because only this gives you levers like break, switch, summarize, or LLM-as-judge inside the loop. - micro agents
Small agent loops of roughly three to ten steps embedded inside an otherwise mostly deterministic DAG/pipeline, handling one bounded decision point rather than the whole workflow. - LLMs are pure/stateless functions
The model itself carries no memory between calls and cannot be made 'smarter' mid-task; the only lever an engineer has over output quality is what tokens are placed into the context window on each call.
Propositions
- explicitThe most successful production LLM agents observed across 100+ founder/builder conversations were mostly ordinary software with a handful of specific LLM-call patterns applied to existing codebases, not agentic greenfield rewrites.conf: high
- explicitThe single genuinely magical capability of an LLM, from which all other agent functionality is built, is turning natural language into structured JSON.conf: high
- explicitA tool call is not a qualitatively different, ethereal agent-environment interaction; it is an LLM emitting JSON that deterministic code then acts on, structurally identical to any other JSON-producing LLM call.conf: high
- explicitLetting an LLM freely determine its own next step in an unbounded loop (the naive 'just tell it the goal' agent model) breaks down in practice, principally because of long-context-window degradation as workflows lengthen.conf: high
- explicitOwning your control flow โ the prompt, the switch-statement over model output, the context-window builder, and the loop-exit logic โ is what gives an engineer levers (break, switch, summarize, LLM-as-judge) that a framework's hidden internal loop does not.conf: highsupportsNo Vibes Allowed: Solving Hard Problems in Complex Codebases โ Dex Horthy, HumanLayer ยท p6 โ This talk's 'own your control flow' / sub-agents-only-for-isolation stance anticipates the later essay's explicit rejection of anthropomorphized sub-agent roles in favor of context-isolation-only sub-agent use.
- explicitAn agent's execution state (step, retries) and business state (messages, pending approvals) should be modeled explicitly and persisted via a state ID so the agent loop can be launched, paused, and resumed like any standard API โ including pausing for long-running tool calls.conf: highsupportsNo Vibes Allowed: Solving Hard Problems in Complex Codebases โ Dex Horthy, HumanLayer ยท p3 โ Same author's later essay restates and deepens the 'LLMs are stateless, only the tokens you control can be engineered' premise with explicit context-rot data (the 'smart zone'/'dumb zone' finding) that this talk only asserts.
- explicitBeyond a certain quality bar, prompts must be hand-written token-by-token rather than generated via a library's default primitives, because reliability is entirely a function of token quality and only careful manual control over input tokens can push past that bar.conf: high
- explicitContext-window construction should not be limited to the standard chat-message format; information can be stringified and modeled however the builder chooses, and curating/compressing error content (rather than dumping full stack traces) measurably improves recovery from failed tool calls.conf: medium
- explicitPushing the tool-call-vs-message-to-human decision onto the model's very first generated token (rather than treating human contact as a separate downstream branch) is an underused, subtle technique that most builders avoid despite its value.conf: medium
- explicitThe working shape for reliable production agents is 'micro agents' โ small loops of roughly three to ten steps for one bounded decision โ embedded inside a mostly deterministic surrounding pipeline, rather than one large agent owning an entire workflow.conf: highsupportsAdvanced Context Engineering for Coding Agents (ace-fca.md) ยท p3 โ This talk's 'micro agents inside a mostly deterministic DAG' is the architectural precursor to the later essay's formalized 40-60% context-utilization, frequent-intentional-compaction workflow โ same author, earlier and coarser-grained version of the same practice.
- implicitAs models get more capable, the deterministic-code share of a pipeline will shrink and the agent-owned share will grow over time, but the engineering discipline of controlling context quality remains necessary regardless of model capability.conf: medium
- explicitFrameworks that abstract away the 'hard AI parts' (prompting, control flow, token curation) are solving the wrong problem; frameworks should instead absorb the hard non-AI parts (infrastructure, state persistence, protocol plumbing) so builders can spend their effort on the AI-hard parts.conf: high
Arguments
Reliable agent engineering is software engineering 101 applied to LLM calls, not a new discipline requiring an AI background. strength: medium
Explicit premises:
- The naive LLM-agentic loop model breaks down on long workflows due to context-window degradation.
- Treating the LLM call as a stateless function and everything else (loop, switch, state, control flow) as ordinary code gives you the levers needed to engineer around that degradation.
- Patterns like DAG orchestration, pause/resume via state IDs, and REST/MCP-fronted services are decades-old software patterns, not novel AI patterns.
Implicit premises:
- Software engineers already possess the relevant skills (switch statements, while loops, state machines) and lack only the specific LLM-adjacent patterns (tool-call-as-JSON, context-window curation) to apply them.
- A framework's value should be measured by how much non-AI-hard infrastructure it removes, not by how much of the agent's own reasoning loop it owns.
Inferences:
- Teams that cede control-flow ownership to a framework are trading away exactly the levers (break/switch/summarize/judge) needed to clear the 70-80%-to-production quality gap the opening anecdote describes.
Agent reliability is bottlenecked almost entirely on context/token quality, not on model capability or framework sophistication. strength: medium
Explicit premises:
- LLMs are stateless functions: tokens in, tokens out.
- The only way to affect output quality (short of retraining the model) is to control what tokens go in.
Implicit premises:
- Context curation effort (hand-writing prompts, summarizing errors, choosing what to stringify) scales with the difficulty of the task in a way that generic framework defaults cannot match.
- 'Getting past the quality bar' is a threshold phenomenon, not a continuous improvement โ implying diminishing returns from generic tooling and increasing returns from hand-engineering.
Inferences:
- Future gains from larger context windows (e.g. 2M-token Gemini) will not substitute for this discipline, since the talk explicitly argues that unconstrained token volume degrades rather than improves reliability.
Narratives
- The speaker's own early DevOps agent: given a Makefile and told to 'build the project,' it executed steps in the wrong order; two hours of iterative prompt-fixing eventually produced a reliable prompt โ at which point the speaker realized a 90-second bash script would have solved the underlying problem.
โ Supports the proposition that not every problem needs an agent, and frames the entire talk's motivating tension: effortful agent engineering sometimes reveals the task didn't need an agent at all. - The HumanLayer internal deploy bot: a mostly-deterministic CI/CD pipeline hands a single ordering decision (deploy frontend or backend first) to a small agent loop; a human intervenes mid-loop to override the order; the pipeline resumes deterministically to run end-to-end tests, falling back to a rollback agent on failure.
โ Concretely illustrates 'micro agents embedded in a deterministic DAG,' pause/resume via state, and human-in-the-loop override โ the talk's central architectural recommendation made tangible.
Questions addressed
- โ
Why do agents that reach 70-80% quality on a task stall there instead of improving further with better prompting alone?
Because past that threshold, further gains require hand-engineering individual tokens/context rather than iterating on a framework-generated prompt โ a qualitatively different (not just more effortful) activity. - โ
What should a framework for building LLM agents actually provide, given that frameworks are widely criticized?
Infrastructure/plumbing (state persistence, pause/resume, protocol handling) rather than the agent's reasoning loop itself โ the talk frames this as a 'wish list,' not a rejection of frameworks as such. - โญ How should an agent decide between acting (calling a tool) and escalating to a human?
A technique (push the decision to the model's first generated token) is offered as a means to make this choice more legible to the model, but the talk does not resolve when/how often this decision should favor the human versus the tool.
Gaps
- incompleteThe talk does not address how a team coordinates or reviews this hand-engineered, token-by-token prompt and control-flow discipline across multiple engineers over time โ it is framed entirely from a single practitioner's vantage point, with no discussion of code review, documentation, or onboarding for the 'owned' control flow and prompts.
Read next: extract-humanlayer-advanced-context-engineering-ace-fca.json and extract-horthy-no-vibes-allowed-complex-codebases.json (same author's later, team-scale essays) take up exactly this gap โ team mental alignment, review at the plan/research layer, and scaling the practice beyond a single motivated practitioner. - incompleteThe claim that 'tool use is harmful' is framed rhetorically but the talk does not examine any downside of the demystified view itself โ e.g., whether treating tool calls as 'just JSON and code' obscures real risks (prompt injection via tool outputs, tool-call hallucination against live systems) that a 'the model is doing something special' framing might have made more salient as a safety concern.
Read next: Compare against the corpus's agent-security and lethal-trifecta material, which treats tool-call outputs as an attack surface rather than purely an engineering-reliability concern.
Related documents
- AI Root Cause Analysis Shifts from Model Reasoning to Context Engineering
- The Anatomy of an Agent Harness
- What is โloop engineering?โ
- 11 Tips For AI Coding With Ralph Wiggum
- Software Factories, Light and Dark
- Agent Harness Engineering
- Don't train the model, evolve the harness
- Designing a Multi-Agent System for Engineering Support at Scale: A Case Study From Grab
- No Vibes Allowed: Solving Hard Problems in Complex Codebases โ Dex Horthy, HumanLayer
- Loop Engineering: Building Blocks, Adoption, and Impact