Spooky season is officially here. Between the sugar crashes and the constant fear of watching your autonomous systems run wild at midnight, I figured it was time for a proper ghost story.
Forget vampires and haunted houses, nothing quite matches the chill of logging into production on Halloween morning and watching an un-idempotent agent cheerfully execute a refund loop 120 times. Grab your spiced pumpkin tea and a blanket, because we are diving straight into the five real-world agent ghosts that only show up after go-live.
Every agent demo I saw this year had this same pattern - the agent calls a tool, reads the result, decides what to do next, and everyone in the room just relaxes because it actually works.
Only problem is, nobody in that room is thinking about the midnight horror.
At 3 am (eewwww), the downstream API is fully sleeping or flaky. The person asking the question is having the wrong entitlements altogether. The memory store is holding onto some random fact that stopped being true back in July, and the tool schema completely changed in Tuesday’s deployment. The model is still the same one that impressed everybody in the demo room, but everything around it is totally different.
See, we all know how to reason about model quality and all that. But the failures that actually hurt you in production come from what we wire the model into, things like state, tools, permissions, memory, retries, and actions that carry real-life consequences.
Here are five of them. Each one is a design problem you can easily solve before go-live, which honestly makes them the least frightening thing in this whole issue.
1. The agent that would not stop running
Picture an operations agent that resolves failed orders. Its loop is sensible: detect the failure, diagnose it, call the recovery tool, verify, retry if needed.
One night the recovery API starts timing out. The agent calls it and gets a timeout, so it assumes the call failed and tries again. The first call had gone through. So does the second. Then the verification endpoint times out as well, and the agent runs the whole sequence again.
By the time someone opens the dashboard, the same recovery operation has run dozens of times against the same orders.
Strip away the LLM and you have a textbook distributed systems failure: an at-least-once call with no idempotency. People were writing postmortems about this long before agents existed. Agents make it worse because a workflow engine retries the way you configured it, whereas an LLM can decide to retry, rephrase the request, or reach for a different tool that does the same thing. Your retry logic now lives inside a probabilistic component.
What was missing: idempotency, retry budgets, tracked action state, execution receipts, duplicate detection, and a defined point at which the agent gives up.
What to build: give every consequential tool call an execution identity, something like action_id = hash(session, task, operation, target), and check it before anything executes. Have tools return explicit states (REQUESTED → ACCEPTED → EXECUTING → SUCCEEDED | FAILED) so the agent reads a status instead of interpreting a timeout. Enforce the retry budget outside the model. Retry twice, then escalate to a human.
Whether a payment, a refund or a stock movement runs twice is a decision for your infrastructure. The model should never be the component making it.
2. The agent that had too much power
An internal employee agent can search the knowledge base, read the HR system, raise IT tickets, read CRM records and update a few systems. It authenticates with a service account that has broad access, because per-user permissions felt like a phase-two problem.
A team lead asks: “Show me the compensation history for everyone in my team.”
The agent finds an HR tool that can answer, the request succeeds, and the data comes back.
There was no prompt injection and no jailbreak. The model did what it was built to do. Security was bypassed at design time, weeks before anyone typed the question.
The HR system saw Agent-Service-Account. It never saw the agent, acting for this team lead, who has no entitlement to salary data. Identity stopped at the agent boundary.
Teams usually ask which tools the agent can access. The question that matters in a regulated firm is narrower: what can this agent access on behalf of this user, for this task, under these conditions?
What to build: delegated identity carried end to end, User → Agent → Tool → Resource. On-behalf-of token flows exist for exactly this. Evaluate every action against the initiating user, the agent’s identity, the operation, the target resource, the data classification and the policy context. For high-impact actions, split the decision: the agent proposes, a policy engine evaluates, a human approves, the tool executes.
The model can decide what it wants to do. Whether it is allowed to do it belongs to your policy layer.
3. The memory that became a ghost
A sales assistant keeps long-term memory to personalise its help. On a call in March, a customer says: “We’re probably cancelling the expansion project.”
The agent stores it.
By June the project is back on. Memory didn’t update.
A salesperson asks the agent to prepare them for tomorrow’s meeting. The agent replies, with full confidence, that the customer has cancelled the expansion and upsell should be avoided.
The agent didn’t hallucinate. It recalled, accurately, a fact that had expired. That is harder to catch than a hallucination, because every retrieval check passes: the source exists, the citation is real, the quote is verbatim.
Long-term memory gives truth a lifecycle. This is Data Debt turning up somewhere new. Memory is data, and most teams build memory stores with none of the governance they would insist on for a customer table.
What to build: treat each memory as a governed record with provenance, a timestamp, a confidence level, an expiry, a scope (private to one user or shared across the organisation) and superseding relationships. Customer considering cancelling expansion should be able to become SUPERSEDED BY: Customer approved expansion (CRM, 14 June). Before anything is written to memory, you should know who created it, where it came from, when it was last verified, and whether newer evidence can override it.
We worry about agents that forget. In a sales meeting, the one that remembers too well and for too long does more damage.
4. The tool that changed face underneath the agent
For six months your agent has called create_support_ticket() without a problem. Then the API team ships v3. A field that used to be optional becomes mandatory, and priority = "high" becomes severity = 1.
A traditional integration fails loudly. An agent reads the error and improvises. It might retry, guess at a new payload, call a different tool, or route around the problem through an email workflow. Your production behaviour now depends on how a model interprets an error message that was never written for a model to read.
The API team did nothing wrong by their own standards. They versioned the API and updated the docs. They had no idea three agents depended on that field, because nothing recorded the dependency.
Tools are contracts, owned by teams who have never seen your agent. With MCP servers multiplying, a single agent can depend on dozens of tools owned by different teams, and every schema change is a potential behaviour change.
What to build: versioned tool schemas, backward-compatibility windows, capability metadata and a deprecation policy. Contract tests in the tool’s own CI that exercise known agent usage. Agent regression suites that run when a tool releases, not only when the agent does. Before Tool v3 ships, someone should be able to say which agents depend on v2 and which of their behaviours will change.
API management covers the interface. Most estates have nothing for agent-tool dependency management: knowing who breaks when the interface moves.
5. The agent escaped the graveyard test
This is the one that frightens me most.
A customer support agent clears its evaluation suite. Answer accuracy, policy adherence, tool selection and hallucination rate are all green. It launches.
A month later, customers have found that if they push back on an answer five or six times, the agent reverses its recommendation. Another user uploads a PDF with instructions buried in it, and the agent follows them. Starting two workflows at once leaks state from one into the other.
None of this was in the benchmark. The test set was written by people imagining how customers would behave. Production is customers actually behaving.
This is Evaluation Debt. The team treated evaluation as a gate (TEST → PASS → DEPLOY) when it needs to be a loop: OBSERVE → FIND FAILURE → WRITE TEST → EVALUATE → IMPROVE. Production traces feed the evaluation system continuously, and every new failure becomes a permanent test case. Over time the suite becomes a record of everything the system learned the hard way.
What to build: evaluation at four layers.
Model: was the response accurate?
Agent: did it choose the right tool and reasoning path?
Workflow: did the task actually complete?
System: did retries, permissions, latency, state and downstream dependencies behave?
The best evaluation dataset you will ever own is the one built from your own incidents.
What the five have in common
A better model fixes none of them. Duplicate execution, borrowed identity, stale memory, drifting tool contracts and missing production tests all live in the architecture around the model.
That is why building production agents looks less like prompt engineering every month and more like distributed systems engineering with a probabilistic component in the middle. The work is in identity, state, memory, tool contracts, policy, retries, observability, evaluation and human approval. The LLM is one component inside that system.
The scariest diagram this Halloween
One mistake to note is relaxing the system around an agent because the agent behaves intelligently. It should run the other way. Every bit of autonomy you hand the model needs a matching deterministic control around it.
Your agent can reason probabilistically. Your permissions, financial transactions, audit trail, retry policy and identity model cannot.
So the architecture diagram that should frighten you this year has no monsters on it. It has one box labelled AI Agent, with an arrow from that box to every system in the enterprise.
Go and check what your agents did last night.
Happy Halloween. 🎃
Share your perspective
Take the Reader Survey to shape upcoming deep dives on production agent architectures.
Subscribe to AgentBuild for engineering blueprints delivered weekly.
Share agentbuild.ai with your technical peers.
P.S. If you’re new here - welcome 🎉. AgentBuild is a community of practitioners working through the real challenges of getting AI into production inside large organisations. Every week I share practical, grounded thinking from the people doing this work at the sharp end. The goal is never theory - it’s always: what can you use Monday morning.
Ask your friends to join.
More valuable content coming your way.

