Taking AI agents from a working demo to production
Agent demos are easy to build and easy to believe. The gap between one that works in a meeting and one that runs against real customer data is not a model problem — it's everything around the model, and almost none of it shows up in the demo.
Why the demo always works
A demo is a curated happy path. The question is one someone chose because it works, the data is clean, and if the agent takes an odd route the person driving quietly runs it again. None of that is dishonest — it's just not evidence about the other 95% of inputs.
Production is the tail. It's the ambiguous request, the record with a null where nothing should be null, the customer who phrases things in a way nobody anticipated, and the third-party API that returns a 500 halfway through a six-step plan. A demo tells you the ceiling. What you need to know is the floor.
So the useful question isn't "can it do this?" — the demo already answered that. It's "what does it do when it can't, and who finds out?"
Decide what the agent is allowed to do
This is the decision that determines how hard the whole project is, and it gets made by default far too often.
Read-only agents are a different category of problem
An agent that reads, summarises and drafts is roughly an order of magnitude easier to ship than one that writes. A wrong answer is visible to the person who asked, and they can ignore it. A wrong write is a corrupted record someone finds three weeks later, with no memory of how it got there.
If a read-only version delivers most of the value — and for research, triage, drafting and support-assist, it usually does — ship that first and let it earn the trust that a write scope requires.
Size the blast radius before the capability
For every tool you expose, ask what the worst plausible call does. Sending one email to the wrong person is recoverable. Issuing a refund, deleting a record, or messaging a customer list is not. Those belong behind an explicit confirmation step, a spend or rate cap, or a human approval queue — not behind a better prompt.
Prompts are not a security boundary. Anything the agent can reach, a sufficiently strange input can eventually make it reach. The controls that hold are the ordinary ones: scoped credentials, allowlisted actions, hard limits, and an audit log of every call with its arguments.
Evaluation is the product, not a phase
Conventional software is deterministic, so tests assert exact output. An agent gives a slightly different answer to the same question twice, which means the usual test suite either fails constantly or asserts so little that it passes when the system is broken.
What replaces it is a graded evaluation set: a few dozen real inputs with a recorded judgement of what a good response looks like, run on every change to the prompt, the model, the tools or the retrieval layer. It doesn't need to be elaborate — a spreadsheet of cases and a script is enough to start — but without it you cannot tell whether a change helped, and you will make changes.
Build it from real traffic rather than imagination. The cases that matter are the ones your users actually send, especially the ones that went wrong; each production failure should end up as a case in the set so the same failure can't return unnoticed.
This is also the honest answer to "is it good enough to ship?". Without an eval set that question can only be answered by vibes, and vibes are how a system that works in September quietly degrades by November after a model version changes underneath it.
Context beats model choice
For most business tasks, the difference between a mediocre result and a good one is not which frontier model you picked. It's whether the right information was in front of it.
That makes retrieval the real engineering work: what gets indexed, how it's chunked, how freshness is maintained, and how you keep a stale document from confidently outranking a current one. A retrieval layer that returns the wrong three paragraphs will make any model look incompetent, and no amount of prompt tuning recovers it.
It also means the unglamorous data work pays off first. If entitlements, ownership and status live in three systems that disagree, an agent will faithfully reproduce the disagreement — at speed, in customer-facing language.
Cost and latency compound with every step
A single call is cheap enough to ignore. An agent is a loop, and the loop is where the arithmetic changes: each step re-sends the accumulated context, so a ten-step task can cost twenty times a one-step one rather than ten, and a rare pathological run can loop far longer than that.
Put hard limits in from the beginning — maximum steps, maximum spend per task, a timeout — and make exceeding them a logged, visible event rather than a silent retry. The first genuinely expensive week is otherwise discovered on an invoice.
Latency needs its own answer. People will wait two seconds for a chat reply and will not wait forty for a silent spinner. Either the work moves to a background job with a notification when it lands, or the interface streams its progress so the wait is legible. Deciding that late means rebuilding the interface.
The failure modes to design for
Four come up in nearly every build, and all four are ordinary engineering problems once you expect them.
Tools fail. APIs time out and return errors, and an agent handed a raw stack trace will often invent a plausible way around it. Return structured, explicit failures the agent can act on, and cap the retries.
Arguments get invented. A model will occasionally call a tool with a confident, well-formed, entirely fictional id. Validate every argument at the tool boundary the same way you'd validate untrusted user input, because that is exactly what it is.
Loops happen. Two tools that each look like the answer to the other's output will ping-pong until something stops them. The step cap is that something.
And it will be asked things outside its scope. Decide what "I can't do that" looks like and make it a first-class response, because the alternative is a fluent, plausible guess — which is far worse than a refusal in every business context.
What we build first
The order that works: pick one task narrow enough to describe in a sentence, build the read-only version, instrument every model and tool call with its inputs and outputs, assemble an eval set from real examples, and only then widen the scope.
Instrumentation is the part teams skip and regret. Without a full trace of what the agent saw and did, a report that "it gave a weird answer yesterday" is unfalsifiable and undebuggable. This is the same discipline as the operational floor any multi-tenant product needs on day one, which we go through in choosing the right backend for a new SaaS build.
It's also most of what we do on agentic AI and production LLM systems — the model is rarely the hard part, and the projects that stall are almost always the ones where evaluation and permissions were left until after the demo impressed someone.
When an agent is the wrong answer
If the task has a known, finite set of steps, write the code. Deterministic logic is cheaper, faster, testable, and doesn't need an eval set. Wrapping a decision tree in a language model adds cost and variance and buys nothing.
The case for an agent is genuine open-endedness: the inputs are unstructured, the path varies, and enumerating every branch in advance isn't realistic. That's a real category, and it's narrower than the current enthusiasm suggests.
Which is the same test we apply to any tooling decision — name the constraint that forces the choice, or take the ordinary option. We wrote that up in how we pick the right foundation for your product.
SYS — Common questions
What does it actually cost to run an AI agent in production?
It depends far more on how many steps a task takes than on the price per token, because each step re-sends the accumulated context. The practical approach is to measure cost per completed task on real traffic rather than estimating from token prices, then set a hard per-task spend cap. Teams are usually surprised by the variance between the median and the worst-case run, not by the average.
Do we need to fine-tune a model?
Almost never at the start. Most disappointing output is a retrieval or context problem rather than a model capability problem, and fine-tuning locks in behaviour that's harder to change than a prompt. Fix what the model can see first. Fine-tuning earns its place for consistent formatting or a narrow, high-volume task where you already have graded examples from production.
How do we stop an agent doing something harmful?
With ordinary engineering controls rather than prompt instructions. Scope the credentials so the agent can only reach what it needs, allowlist the actions it can take, validate every tool argument at the boundary, require explicit confirmation for anything irreversible, and cap spend and steps. A prompt is guidance, not a boundary — treat anything reachable as eventually reachable.
SYS — Keep reading
Choosing the right backend for a new SaaS build
How we decide what a SaaS product actually needs before committing to an architecture — and which decisions are genuinely expensive to reverse.
7 min read
How we pick the right foundation for your product
Frameworks change less than you'd think. What matters is picking tools your team can still run in three years — here's how we decide.
8 min read
