Your API Returned 200 OK. Your AI Agent Still Failed. A developer argues that HTTP 200 responses are an insufficient success metric for AI agents that execute real-world actions, since an agent can call an API correctly while choosing the wrong resource or duplicating side effects. The writeup proposes splitting agent success into three layers — technical request completion, backend operation execution, and semantic correctness of the action on the right resource for the right user — and warns that model-driven retries after timeouts can produce multiple real-world effects from a single user intent. For most backend systems, 200 OK is comforting. It means the request reached the server, passed validation, and completed successfully. For an AI agent, however, 200 OK can hide one of the most dangerous failure modes in modern software: The API did exactly what the agent asked — but the agent asked for the wrong thing. Imagine an AI-powered banking assistant. A customer says: “Refund the duplicate payment from yesterday.” The agent retrieves several transactions, identifies what it believes is the duplicate, and calls: POST /refunds The request is authenticated. The agent is authorised. The transaction ID exists. The refund API processes the request successfully. HTTP/1.1 200 OK Every technical dashboard is green. But the agent selected the wrong transaction. The API succeeded. The business outcome failed. As AI systems evolve from chatbots that recommend actions into agents that execute them, backend engineers need to rethink what “success” actually means. Traditional systems usually measure success at several technical levels. At the network layer: Did the request reach the service? At the API layer: Did the service return a successful response? At the database layer: Did the transaction commit? That works reasonably well when deterministic application code has already decided what operation should happen. For example: refundService.refund transactionId ; The developer has chosen: Agentic systems change this relationship. An AI agent may be given tools such as: findCustomer lookupTransaction issueRefund cancelOrder sendEmail disableAccount restartService The model then determines: Which tool should I call? Which parameters should I use? Should I retry? What should I do next? We have introduced probabilistic reasoning before deterministic side effects . That means we need another definition of success. I find it useful to separate agent success into three layers. Did the technical request complete? HTTP/1.1 200 OK Did the backend perform the requested operation? Refund created successfully. Did the system perform the right action , on the right resource , for the right user , under the right conditions , exactly as intended? For a refund that might mean: Correct customer Correct transaction Correct amount Correct reason Correct approval Exactly once The first two are familiar engineering problems. The third becomes much more important once AI starts selecting and sequencing actions dynamically. Consider this user request: “Refund the most recent duplicate charge.” The agent receives: { "id": "TX-18419", "amount": 2500, "merchant": "ABC Store" }, { "id": "TX-18491", "amount": 2500, "merchant": "ABC Store" } The agent incorrectly chooses: TX-18491 and sends: { "transactionId": "TX-18491", "amount": 2500 } The backend validates the request. The account has sufficient authority. The transaction exists. The refund executes. Technically, there is no error. But the customer wanted another transaction refunded. This is an important distinction: API correctness does not guarantee semantic correctness. The service knows how to refund a transaction. It does not necessarily know whether the AI chose the correct transaction. Now imagine the refund really is correct. The agent calls the service. Agent → Refund API The refund succeeds. But the response is lost. The agent sees: Timeout It reasons: “The refund probably failed. I should retry.” The second call also succeeds. Without protection, one user intent may produce multiple real-world side effects. This problem is familiar to payment engineers and distributed-systems developers. The difference is that with autonomous agents, retries may not come from a predefined retry library. The model itself can decide: “Let me try that again.” That makes idempotency even more important. We already use identifiers such as: request id trace id span id Those identify technical execution. Agents also need something representing the business objective . intent id = REFUND DUPLICATE CHARGE 8472 One intent may generate many technical requests: REFUND DUPLICATE CHARGE 8472 | +-- lookup transaction | +-- validate eligibility | +-- create refund | +-- update CRM | +-- notify customer Suppose the refund API times out. Instead of asking: Should I POST /refunds again? the system can ask: Has REFUND DUPLICATE CHARGE 8472 already produced a successful refund? That is a much safer abstraction. Conceptually: public record AgentIntent UUID intentId, String userId, String action, String resourceId, IntentStatus status, String resultId {} With: public enum IntentStatus { PENDING, EXECUTING, COMPLETED, REQUIRES REVIEW, FAILED } Before executing a mutation: AgentIntent intent = intentRepository.findById intentId .orElseThrow ; if intent.status == IntentStatus.COMPLETED { return previousResult intent.resultId ; } The exact implementation will vary. The principle is what matters: A retry should refer to the same business intent instead of silently becoming a new action. Imagine an account-closing agent. It successfully executes: ✓ Cancel subscription ✓ Revoke API credentials ✓ Delete files ✓ Generate final invoice ✓ Close account Every API returns success. But company policy requires: Export compliance archive BEFORE Delete files The agent skipped the archive. Five green tool calls. One invalid business process. This is why agent observability cannot stop at: Tool call succeeded We need to ask: Was the workflow itself valid? For read-only operations, directly exposing tools may be reasonable. For high-impact actions, I prefer an architecture like: User Goal ↓ AI Agent ↓ Intent + Policy Gate ↓ Tool Gateway ↓ Business API ↓ Outcome Verification Before issuing a refund, deterministic code can verify: transaction belongs to authenticated user AND transaction is refundable AND amount <= remaining refundable amount AND approval threshold is satisfied AND intent has not already completed The model proposes. The system verifies. The API executes. The system verifies again. That separation is important. Security controls still matter enormously. But authorisation alone does not solve every agent problem. Suppose an agent legitimately has permission to call: restartProductionService The credentials are valid. The operator has the correct role. But should the service restart now? Perhaps: a deployment is currently running or: an incident is already active traffic is at its daily peak another restart happened 30 seconds ago Authentication answers: Who are you? Authorisation answers: Are you allowed to perform this operation? Agentic systems also need: Is this action appropriate in the current context? That requires policy, state, and sometimes human judgement. Many tools are described approximately like this: name: issue refund description: Refund a customer transaction That tells the model what the tool does. It does not define the conditions that make using it safe. A stronger contract might be: tool: issue refund preconditions: - transaction belongs to authenticated customer - transaction is refundable - amount <= remaining refundable balance execution: idempotency required: true postconditions: - refund record exists - refund references expected transaction - refund amount matches approved amount - ledger state reconciles approval: required above: 5000 Now success is not simply: function returned successfully It becomes: preconditions satisfied + action executed + postconditions verified A tempting pattern is: Agent performs action ↓ Agent asks itself: "Did that work?" ↓ Agent continues For low-risk workflows, this may be sufficient. For important actions, it is fragile. If the model misunderstood the original request, asking the same model whether its interpretation was correct may reproduce the same mistake. High-impact actions should be verified against external evidence: database state payment receipt ledger state policy engine independent validator sensor state human approval The model can reason about these signals. It should not invent them. Imagine this dashboard: refund-api availability: 99.99% tool-call success rate: 98.9% average API latency: 310 ms Everything appears healthy. But you are not measuring: wrong-target actions duplicate mutations policy violations unverified outcomes human reversals Agentic systems need higher-level metrics. verified outcome rate duplicate action rate postcondition failure rate human override rate ambiguous outcome rate intent reconciliation rate A meaningful future SLO might look like: 99.95% of high-impact agent intents complete with a verified business outcome and no duplicate side effect. That tells us far more than API availability. Suppose a user tells an AI commerce agent: “Cancel my duplicate order and refund it.” Instead of immediately executing actions, the workflow could be: 1. Create intent CANCEL DUPLICATE ORDER 9821 2. Retrieve candidate orders 3. Deterministically verify: - same customer - duplicate item - matching amount - cancellable state 4. Generate action preview: Cancel Order A1842 Refund £74.99 5. Request human confirmation if required 6. Cancel order using intent ID 7. Issue refund using same intent context 8. Verify: order == CANCELLED refund == CONFIRMED refund amount == £74.99 9. Mark intent COMPLETED 10. Tell user: "Done" Step 10 is the important part. The agent does not say “done” because it received 200 OK . It says “done” because the system verified the intended business outcome. For any agent capable of moving money, modifying production systems, changing permissions, deleting information, or performing irreversible actions: Persist the actual business objective. Expose only capabilities required for the task. Keep critical business rules outside the model. Design retries so repeating a request does not repeat the side effect. Verify the resulting state using trusted systems. Connect: user intent → agent decision → policy result → tool call → API response → verified business state That gives us: Intent ↓ Policy ↓ Action ↓ Receipt ↓ Verification ↓ Outcome instead of: Prompt ↓ Tool ↓ 200 OK ↓ "Done " Traditional APIs mainly answer: What operation can I call? What arguments are required? What response will I receive? AI-agent-facing capabilities may need to expose more: What risk level does this action carry? Is the operation reversible? Does it require approval? Can it be retried safely? What preconditions must hold? What proves successful completion? That turns the API from a simple interface into something closer to a capability contract . The AI supplies flexible reasoning. The surrounding system supplies deterministic guarantees. We are investing enormous effort in making AI agents smarter. Better models. More context. More tools. Longer workflows. Greater autonomy. But once an agent can modify the real world, the hardest production question may not be: Can the model determine what to do? It may be: How do we prove that what it just did was actually what the user intended? The most dangerous failure may never generate an exception. It may not trigger PagerDuty. It may not appear in the error logs. Every service may remain healthy. All you may see is: HTTP/1.1 200 OK The AI agent completed its task. And the business still lost. That is why production Agentic AI needs more than successful tool calls. It needs verified outcomes .