The 80% That Breaks AI Features: Building Production Agents Beyond Prompting A developer published a deep-dive arguing that prompting accounts for only about 20% of a working AI feature, with the remaining 80% made up of orchestration, tool reliability, context management, guardrails, observability and evaluation. The writeup lays out five engineering layers — runtime, tooling, context, guardrails, and observability plus eval — and provides TypeScript-style pseudocode for a finite-state-machine agent loop with hard budgets on iterations, tokens, tool calls and wall-clock time, plus abort handling and tracing. Originally published on tamiz.pro https://tamiz.pro/insights/production-ai-agents-beyond-prompting . The most common failure mode in AI engineering isn't a bad prompt — it's everything around the prompt. Teams iterate on system instructions for weeks, ship a frontier model, and still watch agents hallucinate tool calls, blow past context windows, double-charge customers, or fail silently in production. The uncomfortable truth: prompting is roughly 20% of a working AI feature. The other 80% is orchestration, tool reliability, context management, guardrails, observability, and evaluation — the unglamorous engineering that turns a clever chat completion into a dependable system. This deep-dive maps that 80% and gives you the concrete patterns to build agents that survive real traffic. The prompt is a contract, not a solution. It declares intent; it does not enforce behavior. In a demo, that's fine. In production, the contract is violated constantly because the model isn't the only moving part. The agent's environment is. Consider what actually happens when an agent runs in production: None of these are prompt problems. All of them are system problems. That's the 80%. The 80% breaks down into five engineering layers you must build before the prompt matters: | Layer | What it owns | Typical failure without it | |---|---|---| | Runtime | Loop control, state, termination | Infinite loops, runaway cost | | Tooling | Schemas, retries, idempotency | Broken calls, double charges | | Context | Budgeting, compression, retrieval | Window overflow, lost goals | | Guardrails | Validation, injection, sandboxing | Security breaches, bad output | | Observability + Eval | Traces, cost, regression gates | Silent failures, no trust | In the rest of this article, we'll build each layer in TypeScript-style pseudocode against a generic LLM SDK, because the patterns matter more than the provider. The first thing to kill is the naive while true { await chat } loop. A production agent is a finite state machine with hard budgets. It must be able to terminate, yield, and fail gracefully. type AgentState = 'plan' | 'act' | 'observe' | 'terminate'; interface AgentConfig { maxIterations: number; // hard cap, e.g. 12 maxTokens: number; // total token budget, e.g. 60 000 maxToolCalls: number; // e.g. 8 maxWallClockMs: number; // e.g. 30 000 signal: AbortSignal; } async function runAgent goal: string, tools: Tool , config: AgentConfig : Promise