Skip to main content

12-Factor Agents Is the New 12-Factor App: A Deploy Tool's Field Guide

11 min readDora NodaDora Noda
Share

An agent calls a deploy tool and says "roll back the payments service to the last healthy release." Three questions decide whether that sentence is safe to execute: does the agent's tool call carry enough state to know which release was actually healthy, does anything stop it from acting before a human signs off, and can the same tool call be retried without doubling the blast radius if the network blips halfway through. Most "AI-native" platforms shipping deploy tools to agents in 2026 haven't answered any of the three — they bolted an LLM onto an existing API and called it agent-ready.

Dex Horthy, founder of HumanLayer, spent early 2025 interviewing more than 100 founders and engineers building production LLM agents and found the same failure mode everywhere: teams grab a framework, get an agent to 70–80% of the desired behavior fast, then hit a wall — it loops, it hallucinates a tool call, it loses track of what it already did — that the framework can't get them past. His answer, published as 12-Factor Agents in March 2025, is deliberately not a new framework. It's twelve engineering disciplines, modeled explicitly on Heroku's 2011 Twelve-Factor App, for the same reason Heroku wrote the original: patterns Heroku's engineers saw repeat across thousands of hosted apps, codified so the next team doesn't have to learn them by breaking production first. The repo has pulled 24,000+ GitHub stars and become the reference doc AI engineers link when a Slack thread turns into "why doesn't our agent framework just work."

The irony we build bex around: we're a Render-alternative whose whole pitch is that AI agents should be able to deploy and operate real services through MCP — and the discipline that makes that safe is the same discipline Heroku's own methodology preached for apps, back when nobody was letting software decide when to redeploy itself. Below is what each factor concretely costs us to satisfy in bex's own MCP-exposed deploy and rollback tooling — not the abstract principle, but the design decision it forces.

The 12 factors, mapped to a deploy tool an agent can call

#FactorWhat it saysWhat it costs a deploy-from-chat platform
1Natural Language to Tool CallsTurn user intent into structured function calls a deterministic system executesThe MCP tool schema (deploy, rollback, scale) is the contract — the LLM's job ends at picking the tool and filling typed parameters, not writing the deploy logic itself
2Own your promptsDon't outsource prompt engineering to a framework defaultbex's own agent-facing prompts for interpreting deploy intent are first-class source, versioned and tested — not whatever a framework's default system prompt happens to say this week
3Own your context windowControl exactly what the LLM sees, don't dump raw logs/state at itA rollback call gets the last N releases, health status, and diff summary — not a raw kubectl get events dump the model has to parse
4Tools are just structured outputsA tool call is a JSON schema the LLM fills in, not a special abstractiondeploy/rollback/scale are ordinary typed RPCs; nothing about "being callable by an agent" changes their contract
5Unify execution state and business stateAgent progress tracking should live in the same data model as the app's real state, not a shadow storeDeploy status the agent polls is the same release-history row the dashboard renders — no separate "agent memory" of what it thinks it did
6Launch/Pause/Resume with simple APIsAgents must be stoppable and resumable without bespoke state machinesA deploy an agent triggers can be paused mid-rollout and resumed by a human (or a different agent) hours later, from the same release record
7Contact humans with tool callsEscalating to a human uses the same interface as any other tool callAn irreversible action (delete a service, roll back past the last N releases) calls a request_approval tool and blocks — approval is a tool call, not a side-channel Slack ping the agent can't see the answer to
8Own your control flowExplicit code decides what happens next; the LLM doesn't drive its own loopbex's deploy pipeline is a state machine bex owns; the agent requests transitions, it doesn't get to loop deploy → check → retry on its own judgment
9Compact errors into context windowSummarize failures instead of dumping stack traces into the token budgetA failed build returns "TypeScript error, 3 files, see summary" not 400 lines of raw CI log
10Small, focused agentsNarrow-purpose agents beat one agent that does everythingA "deploy agent" and an "incident-diagnosis agent" are different tool surfaces with different scopes, not one agent with god-mode over the whole platform
11Trigger from anywhereAgents should be invokable from chat, webhook, cron, or another agent — not just one chat UIThe same MCP tool that answers a Claude Code prompt also answers a GitHub webhook or a scheduled job — one tool surface, many callers
12Make your agent a stateless reducerThe agent process holds no state between calls; state lives in the storeRestarting bex's agent-facing service mid-conversation loses nothing — every call reads/writes the same release-history state a restart can't touch

That table is the deliverable — twelve rows, twelve concrete decisions. The next section is why four of them are the ones that actually determine whether an agent is allowed to touch a production deploy at all.

The four factors that decide whether an agent gets root

Four of the twelve are named explicitly because a deploy tool fails differently — and more expensively — than a chatbot when it skips them.

Own your prompts (Factor 2). A generic agent framework ships a default system prompt tuned for general tool use. Point that at a rollback tool and it will interpret "roll back the payments service" as confidently for a staging sandbox as for a production database migration — the framework has no idea which one costs you customers. bex's deploy-intent prompts are written and tested against bex's own tool schema, with production services explicitly flagged in the context the prompt sees. "Roll back payments" resolves differently depending on the environment tag on that service — not because the model got smarter, but because the prompt shaping its read of the request was ours to write, not a framework's to guess at.

Unify execution state and business state (Factor 5). The naive version of a deploy agent keeps its own log of "steps I've taken" — a scratchpad the agent updates as it works. The problem shows up the first time two things touch the same deploy at once: a human clicks "cancel" in the dashboard while the agent's scratchpad still says "step 3 of 5, proceeding." The agent has no way to know the ground truth changed, because it was never reading the ground truth — it was reading its own notes.

bex's deploy tool has no separate agent-state table. The row an agent reads to decide "should I retry" is the exact row the dashboard renders and the row the cancel button writes. There's one truth, and everything — human click, agent poll, webhook retry — reads and writes it.

Small, focused agents (Factor 10). The tempting design is one agent with a big tool belt: deploy, scale, rotate secrets, manage DNS, delete services. It demos well. It's also the reason "one wrong tool call" and "catastrophic wrong tool call" become the same failure mode — a prompt-injected support ticket that tricks a general-purpose ops agent doesn't just mislabel a ticket, it has a live path to delete_service. bex splits the surface: a deploy/rollback tool scoped to release management, a read-only diagnosis tool scoped to logs and metrics, nothing that touches DNS or secrets in the same tool call an agent uses to answer "why did the build fail." Narrow scope isn't a UX nicety — it's the blast-radius control.

Contact humans with tool calls (Factor 7). This is the one that actually reads as a design constraint, not a suggestion, once you sit with it: if "ask a human" isn't a tool call, it's a side channel the agent has no way to wait on. A Slack message pinging an engineer isn't a tool call the agent can block on — the agent has already returned control, the conversation has moved on, and by the time a human replies "yes, roll back" there's nothing left listening for the answer.

bex wires irreversible actions — deleting a service, rolling back further than the last N releases, anything that isn't cheaply undoable — through a request_approval tool that blocks the agent's turn until a human resolves it through the same interface. The approval isn't a notification bolted on after the fact; it's the tool call the agent is waiting on, which is the only way "wait for a human" is enforceable rather than aspirational.

The irony, made specific

Line the two documents up side by side and the parallel stops being a nice framing device and starts looking like the same problem, twelve years apart.

Heroku's original Factor III said store config in the environment — don't hardcode a database URL, inject it at runtime, so the same build runs identically in staging and production. 12-Factor Agents' Factor 3 says own your context window — don't let a framework silently assemble what the model sees; inject exactly the state that call needs, so the same tool behaves identically whether a human or an agent invoked it. Same instinct: don't let an environment-shaped detail leak into logic that should be portable.

Heroku's Factor VI said execute the app as one or more stateless processes — anything durable lives in a backing store, so a process can die and restart without losing state. 12-Factor Agents' Factor 12 says make your agent a stateless reducer — the same argument, aimed at a process that now might crash mid-tool-call instead of mid-request.

Heroku's Factor IV said treat backing services as attached resources, swappable without code changes; 12-Factor Agents' Factor 1 says a tool call is a structured contract the agent fills in, swappable independent of which model is on the other end of it. The vocabulary changed — "dyno" became "agent," "request" became "tool call" — but the discipline being reinvented is disposability and explicit contracts, the exact two things Heroku spent 2011 insisting distributed apps couldn't survive without.

The reason this keeps happening isn't nostalgia. It's that "a process that can be killed and restarted without losing correctness" and "a caller that can't be trusted to hold state between calls" are the same engineering problem wearing different clothes, and every generation of infrastructure re-derives the same answer to it independently before someone points out the previous generation already wrote it down.

What this buys a platform betting on agents as operators

The 70–80% reliability wall Dex Horthy's interviews kept surfacing isn't a model-capability problem that next quarter's release fixes — enterprise adoption data backs this up directly: Gartner predicts 40% of enterprise applications will carry task-specific agents by the end of 2026, up from under 5% in 2025, and yet a KPMG survey found only 11% of organizations had actually deployed agentic AI in production as of mid-2025, against 99% who say they plan to eventually. The gap between "planned" and "deployed" is the wall — and it's made of exactly the ten factors that don't get fixed by a smarter model: unowned control flow, unbounded context windows, agent state that drifts from the system's real state, and no enforceable point where a human actually has to say yes.

A deploy-from-chat platform can't treat that gap as somebody else's problem, because the whole premise is an agent holding a tool that can take down a production service. The twelve factors aren't a checklist you retrofit after an incident — they're the design decisions that have to be right before the first agent gets a rollback tool, because Factor 8 (own your control flow) and Factor 7 (contact humans with tool calls) are exactly the two things standing between "agent-operated infrastructure" and "infrastructure an agent operated once, badly, at 2am."

Bex.co is the open-source, AI-native Render alternative — push a git repo, get a running HTTPS service on machines you own, with an MCP surface built around these same twelve factors so an agent can deploy and roll back safely. Star the repo on GitHub or deploy your first app today.

Related articles

Give your agents a chain backend

Autonomous agents hit RPC endpoints very differently than people do. See what bex router handles on their behalf.

Read the agents guide