How to get from an impressive demo to something on-call can support
The gap list between an AI demo and a supportable feature: identity scoping, secrets, budgets, logs, evals, rollback, escalation, alerts and a runbook.
Between a working demo and a feature on-call can support sit nine pieces of platform work: identity and data scoping, secret handling, cost and rate budgets, timeouts with idempotent retries, structured logs and traces, an eval suite wired to a release gate, a rollback plan, an escalation path, and alerts with a runbook behind them. Close them roughly in that order, since each one makes the next cheaper to build.
What the demo skipped
The prototype ran against one account, with a provider key pasted into an environment variable, on a question the builder had already watched it answer. That is what made it fast to build. Six weeks later it is still not shipped, and the reasons repeat across teams: no auth boundary, no limits, no logs anyone can query, no evals, no rollback, and one hard-coded happy path.
Skipping that work is correct for a prototype and fatal for a launch. Almost none of it is model work, so a roadmap written from the demo underestimates it by a factor of several, and the project stalls somewhere between "it works" and "we can support it". That stall has a shape, described in more detail in why AI pilots stall. The wider set of shipping decisions sits under AI agent deployment.
How do I take my AI prototype to production
Work the list in order. The effort column assumes one or two engineers who already know the surrounding codebase, and assumes you are adding an agent to a product that exists, which is the case covered in adding an AI assistant to an existing product.
| # | Item | What it buys | Rough effort |
|---|---|---|---|
| 1 | Identity and data scoping | No cross-tenant reads; every later item can be scoped | 3 to 5 days |
| 2 | Secret handling | Keys out of prompts, traces and tool arguments | 1 to 2 days |
| 3 | Cost and rate budgets | A runaway loop costs dollars instead of thousands | 2 to 4 days |
| 4 | Timeouts, retries, idempotency | A slow provider degrades instead of hanging | 2 to 3 days |
| 5 | Structured logs and traces | On-call can answer "what did it do" without a repro | 3 to 5 days |
| 6 | Eval suite and release gate | A prompt edit cannot silently regress last month's fix | 4 to 6 days |
| 7 | Rollback plan | A bad release is a five-minute revert | 1 to 2 days |
| 8 | Escalation path | The agent hands off instead of guessing | 2 to 4 days |
| 9 | Alerts and runbook | Someone is paged, and knows the first three checks | 2 to 3 days |
1. Scope every request to an identity
Resolve three identities at the edge of every request: the tenant that owns the data, the end user who asked, and the caller that carried the request (a browser session, a customer's API key, a scheduled job). Pass them into tool execution as trusted context. A tool whose tenantId argument is filled in by the model is one prompt injection away from a cross-tenant read, because the model treats that field as data it may choose.
2. Move secrets out of the prompt path
Provider keys, database credentials and third-party tokens resolve server-side at call time, never in a system prompt, a tool argument, or anything written to a trace. Log the name of the secret a call used and never the value. A trace store that captures raw tool arguments quietly becomes the most sensitive database you own, and it is usually the one with the loosest access control.
3. Put a ceiling on every loop
An agent with tools has three unbounded dimensions: turns per run, tool calls per turn, and wall-clock time. Cap all three, plus spend per tenant per day. The classic runaway is a tool that returns an empty array when its upstream fails; the model reads empty as "that did not work" and calls it again, and the loop ends only when a limit stops it or the context window fills. Decide in advance what a tenant hitting its daily cap sees, since a silent failure at the cap reads as an outage.
4. Give every call a timeout, and make retries safe
Thirty seconds is a reasonable default tool timeout; anything slower belongs in a background job with a handle the agent can poll. Retry only calls that are safe to repeat, with jitter and a ceiling of two attempts, so a provider blip does not turn into a self-inflicted load test. Every write tool needs an idempotency key derived from the run id and the call index, honored by the system downstream. A retried refund that lacks one issues two refunds, and the model has no way to know it happened.
5. Log the run so a stranger can read it
On-call will not have your notebook. Emit one structured record per step with the identity, the version, the model, the tool, timings, token counts split into cached and uncached, and the stop reason. Redact values and keep keys, so the shape of a call survives without its contents.
{
"runId": "run_8f21c3",
"tenantId": "acct_4417",
"endUserId": "user_90b2",
"surface": "web-chat",
"agentVersion": "12",
"model": "claude-sonnet-4-5-20250929",
"step": "tool_call",
"toolName": "lookup_order",
"argumentKeys": ["orderId"],
"durationMs": 812,
"tokensIn": 4310,
"tokensInCached": 3900,
"tokensOut": 260,
"stopReason": "tool_use",
"outcome": "ok"
}
Two fields earn their keep during an incident. stopReason separates "the model finished" from "it hit the token cap mid-sentence", and the cached token split explains a cost jump that no traffic change accounts for. The step-by-step reading technique is in how to debug an AI agent.
6. Build the eval suite from real failures, then gate the release on it
Start the suite from transcripts, not from imagination: every bug someone reported becomes a case, with the input, the tenant shape that triggered it, and the property that has to hold. Score with assertions where the answer is checkable and a judge model where it is not, and keep the judge prompt in version control beside the cases. Wire the suite into the deploy so a prompt edit, a model swap or a tool schema change cannot ship red. A release gate that a human can wave through is a release gate that gets waved through at 5pm on a Friday.
7. Make the release reversible
Pin the model to an exact dated version rather than a floating alias, so a provider's silent upgrade cannot change behaviour under you. Version the prompt, the tool set and the agent configuration together as one publishable unit, and keep the previous published version deployable without a rebuild. Ship behind a per-tenant flag and roll forward through a few accounts before everyone. Rollback should be a version pointer change, not a git revert and a fifteen-minute build.
8. Give the agent a way out
Decide what happens when the agent cannot help, and make that path better than a hedge. Three exits cover most cases: hand off to a human queue with the transcript attached, file a ticket with the structured fields the model did manage to extract, or refuse plainly and say what the person should do instead. For actions that are expensive to undo, put a human approval in front of the tool call rather than in front of the whole conversation, with a timeout and a defined behaviour when it expires.
9. Alert on the four signals that actually page
Error rate by tool name, cost per hour by tenant, p95 turn latency, and approval or escalation queue depth. Each alert links to the runbook row below and names an owner. An alert that fires on "model quality" with no query behind it trains everyone to ignore the channel.
The five things that break, and what on-call does about each
Write this table before launch, not after the first page. Every row names the symptom a customer or a dashboard reports, the first place to look, and the action that stops the bleeding while someone finds the cause.
| Symptom | Likely cause | First check | Immediate action |
|---|---|---|---|
| Turns hang or time out | Provider degradation, or one slow tool holding the turn | Per-step latency in a recent trace; provider status | Cut the tool timeout; switch to the fallback model if one is wired |
| Cost per hour jumps | A tool loop, a retry storm, or a prompt edit that broke cache reuse | Cost per execution grouped by tenant and agent version | Throttle the tenant at its cap; roll back the version |
| Answers got worse after a ship | Prompt, model or tool schema change | Eval suite run before and after the change, compared run to run | Revert to the previous published version, then diff the cases |
| One tool fails constantly | Expired credential, upstream 5xx, changed response schema | Tool error rate by name; a raw failing call | Disable the tool so the agent degrades; page its owner |
| A customer reports seeing data that is not theirs | Identity not scoped, or redaction policy off on a surface | Which tenant and end user the run executed under | Freeze the surface, revoke the caller credential, preserve the traces |
The last row is the one to rehearse. It is the only symptom where the correct first move is to stop serving traffic, and the only one where deleting logs to "clean up" destroys the evidence you need for the disclosure.
Where this gets easier
Most of the list above is platform work rather than product work, which is why it takes weeks and why nobody demos it. Runtype provides it as defaults: a tenancy strategy per resource with an assurance floor that rejects an under-identified request before execution, secrets resolved server-side through {{secret:NAME}} references the model never sees, per-turn tool-call caps and a wall-clock budget on every run, cost recorded per execution with cached and uncached tokens separated, traces carrying per-step input, output and tool arguments, eval suites whose cases can be promoted from a recorded execution, draft and published versions to roll back between, and approval gates with a timeout for the calls a person should see first. What is left is the behaviour of your agent, which is the part only your team can write.
Frequently asked questions
- How long does it take to productionize an LLM application?
- For a small team taking one agent from a working prototype to a supported feature, four to six engineering weeks is a common range, and almost none of it is prompt work. Identity scoping, budgets and logging tend to take a week each; evals and the release gate take another week; rollback, escalation, alerts and the runbook fill the rest. The estimate grows if the agent writes to systems of record, because every write tool needs an idempotency story.
- What should I close first?
- Identity and data scoping, before anything else. Every later item depends on knowing which tenant and which end user a run belongs to: cost budgets are enforced per tenant, logs are queried by tenant, and an isolation bug found after launch is a disclosure incident rather than a bug. Retrofitting identity into tools that already accept a customer id as a model-supplied argument is the most expensive rework on this list.
- Do I need an eval suite before the first launch?
- You need a small one. Twenty to thirty cases drawn from real failures and real transcripts is enough to catch the regressions that matter, and it is small enough to run on every change. A suite built to look thorough before launch is usually built from cases nobody has seen fail, which is why it stays green while production breaks.