We have shipped a fair number of agentic features in the last two years, and the pattern that predicts whether one survives contact with real users has very little to do with which model is behind it.
Validate at the boundary, not in the prompt
The most common failure we are called in to fix is a system that trusts model output structurally. A prompt asks for JSON, the model usually returns JSON, and the code parses it directly. It works in testing because the happy path is genuinely common.
Treat model output the way you would treat a request body from an untrusted client: parse it against a schema, and have a defined behaviour for the case where it does not match. Not a retry loop that runs forever — a bounded retry, then a failure the surrounding system knows how to report.
Give the agent fewer tools than you want to
Every tool you expose widens the space of things that can go wrong, and the widening is not linear. Two tools that each work reliably can combine into a sequence that does something nobody intended.
The version that ships well is usually the one where the tool list was cut in half and the removed capabilities became ordinary code paths triggered by the agent’s structured output, rather than actions the agent takes directly.
Make the expensive step idempotent
Agents retry. Users refresh. Queues redeliver. If the action at the end of the chain charges a card, sends an email, or writes to a ledger, it needs to be safe to attempt twice, because it will be attempted twice.
The question worth asking during design review is not “what does this do when it works” but “what does this do when it runs twice and the second run has slightly different context”.
Log the inputs, not just the outputs
When something goes wrong in production the output is the least useful artefact. What you need is the exact context the model saw — the retrieved documents, the tool results, the state of the conversation at that turn. Reconstructing that after the fact is close to impossible, and teams that skip it end up unable to distinguish a model problem from a retrieval problem.
None of this is about models. It is ordinary distributed-systems hygiene applied to a component that happens to be probabilistic, and it is the part that determines whether the feature is still running in six months.







