AI Services

What AI Agents Get Wrong in Production

What I Learned Letting an AI Agent Build a Production Application

We're in the reckoning phase of AI-assisted development. Faster output without deeper judgment doesn't reduce risk — it compounds it. Most teams just don't know it yet.

I recently built a full-stack SaaS dashboard almost entirely through an AI agent. The demo was impressive. But cracks appeared quickly in production. The frontend was rendering empty states because the API was returning data: null in one endpoint and data: [] in another — both valid, neither consistent. Error handling was worse: some routes returned structured { error: { code, message } } objects, others returned plain strings, and a few returned HTTP 200 with an error buried in the payload. No single failure was catastrophic. Together, they were a slow drain on user trust.

Each piece looked reasonable in isolation and fell apart at the seams. That's the failure profile nobody warns you about.

Ambiguity Doesn't Disappear. It Ships

AI builds exactly what you specify — not what you intend. Leave an edge case undefined and the agent fills it with a plausible assumption. That assumption works in demos. It breaks in production.

This isn't a flaw in the model. It's a fundamental property of how these systems work. GitHub's own research on Copilot found that while AI dramatically accelerates code generation, it also increases the surface area of code that needs human review — because more code, generated faster, means more implicit decisions that go unexamined.

The implication is straightforward: your specification quality now determines your output quality more directly than ever before. Vague prompts produce confident, plausible, wrong implementations.

What to do: Before any significant AI-assisted build session, write an explicit constraint document — not just requirements, but defined edge cases, error states, and behavioral contracts. Treat it like an API contract for the agent.

Context Doesn't Carry Forward. It Has to Be Engineered

Every session with an AI agent starts fresh. The agent has no memory of why a decision was made three sessions ago, what patterns you agreed to follow, or which approaches you already tried and rejected. Without a deliberate decision layer — documented constraints, established patterns, explicit rules — you spend future sessions re-solving problems you already solved.

Tools like Claude Code have begun addressing this through persistent memory and context compaction, allowing decisions and patterns to carry forward across sessions. But even where those features exist, they require intentional design to be reliable. The teams that handle this well treat context management as an architectural problem, not a workflow inconvenience.

The cost of ignoring it compounds quietly. Each session that starts without context produces slightly inconsistent decisions. Those inconsistencies accumulate across the codebase until the system becomes harder to reason about than it needs to be.

What to do: Maintain a living "system decisions" document that travels with every session. Include: key architectural choices and why they were made, naming conventions, patterns to follow and patterns to avoid, and open questions. Treat it the way you'd treat a decision log in a distributed team.

Integration Looks Correct Before It Is

Build backend and frontend in separate sessions and the contracts between them become assumptions. Different response shapes. Missing fields. Mismatched types. No crash — just silent, invisible incorrectness that works fine in isolation and fails in combination.

This is the most underestimated risk in AI-assisted development. LLM output is probabilistic by nature. You can instruct format; you cannot guarantee it. Silent failures — where systems return success codes while passing malformed or incomplete data — produce no immediate error signal. They surface later as "weird behavior," the hardest category of bug to diagnose because there's no clear point of failure to trace back to.

If you're not validating outputs at the boundary, you're distributing inconsistency throughout your system and deferring the cost until it's much more expensive to fix.

What to do: Never let AI-generated API contracts exist only as assumptions. Use schema validation (Zod, Pydantic, JSON Schema) at every integration boundary. Make contract violations loud and early, not silent and late.

Quality Doesn't Break. It Drifts

After several iterations, naming conventions diverge. Error handling patterns fragment. Everything still runs — but the cognitive overhead of working in the codebase quietly doubles.

This is the compound interest problem of AI-assisted development. Individual sessions look fine. Cumulative sessions produce a codebase that is increasingly expensive to reason about. Google's research on code maintainability has consistently found that inconsistency in naming, patterns, and error handling is one of the leading contributors to engineering velocity loss over time — not dramatic failures, but quiet erosion.

Here's the uncomfortable arithmetic: even at 95% accuracy, a production system cannot tolerate a 5% error rate — because that 5% is silent, inconsistent, and compounds across every subsequent decision.

What to do: Schedule deliberate "coherence reviews" every three to five sessions. Not code reviews for correctness — reviews specifically looking for pattern drift, naming inconsistencies, and diverging error handling. This is not overhead; it is the cost of maintaining a system you can actually work in.

The Most Expensive Bugs Don't Announce Themselves

Writes that return 200 but never persist. UI that renders from the wrong field. These pass every test. They show up later as "weird behavior."

This category of failure has a name in reliability engineering: silent corruption. It's distinguished from normal bugs by one property — there is no clear point of failure to trace back to. The system behaved correctly according to every observable signal, and something still went wrong.

AI-generated code is particularly susceptible to this class of failure because the code often looks right — it follows correct patterns, uses correct syntax, handles the happy path correctly. The failure lives in the assumptions underneath.

What to do: Write explicit integration tests that verify state changes, not just return codes. "Did this write actually persist?" should be a test, not an assumption. Build observability into your data layer, not just your API layer.

Security doesn't get assumed. It gets skipped

This is the one that should worry teams most. AI agents optimize for working code. Security is a constraint that has to be explicitly stated — and most of the time, it isn't.

In practice this means AI-generated code ships without authentication on endpoints that should require it, with API keys hardcoded in source files instead of environment variables, and with missing input validation that leaves the door open to injection attacks. These aren't edge cases — they're the default output when security requirements aren't part of the prompt.

Over-permissioned APIs are an equally common pattern. An agent asked to "fetch user data" will often return entire records when only a few fields are needed — because nobody specified otherwise. At scale, that becomes a data exposure risk that's hard to unpick after the fact.

Then there's a newer class of risk: prompt injection. If your application processes user-supplied content through an LLM — summarizing inputs, answering questions, parsing documents — a malicious user can embed instructions in that content designed to hijack the model's behaviour. It's the SQL injection of the AI era, and most teams aren't thinking about it yet.

What to Do: Treat security as a first-class prompt constraint, not an afterthought. Explicitly specify authentication requirements, data exposure limits, and input validation rules before you build. Audit AI-generated code specifically for hardcoded secrets, missing auth checks, and over-broad data access. And if your app passes user content to an LLM, sanitise inputs and constrain outputs the same way you would any untrusted data source.

Key Takeaways

  • Spec quality is now a first-class engineering concern. Ambiguous input produces confident, wrong output. Invest in constraint documents before you start building.
  • Context collapse is an architectural problem, not a workflow inconvenience. Design a decision layer that travels with every session.
  • Validate at every boundary. Silent contract failures are the hardest bugs to diagnose. Make them loud.
  • Schedule coherence reviews. Quality drift is invisible in individual sessions and expensive across a codebase.
  • Test state, not just responses. The most expensive bugs pass every test because nobody thought to write the right test.
  • Security has to be specified, not assumed. AI won't add authentication, limit data exposure, or guard against prompt injection unless you explicitly ask it to.

What's your experience building with AI agents at scale? Where have you found the real failure points?

About the Author

Rakesh Saharan
Dev Manager - Delivery Services
Covalience
Rakesh Kumar Saharan is Development Manager of Delivery Services at Covalience, where he leads software projects from planning through delivery, ensuring they meet business goals and are built for the long term. With over 15 years in the software industry, including more than a decade at Covalience, he has led teams across engineering, practice leadership, and program management. Rakesh brings a disciplined approach to Agile and Scrum delivery, project governance, and the responsible integration of data and AI within software projects.
On this page