cd /news/ai-agents/your-api-returned-200-ok-your-ai-age… · home topics ai-agents article
[ARTICLE · art-135063] src=dev.to ↗ pub= topic=ai-agents verified=true sentiment=· neutral

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.

by read9 min views1 publishedSep 20, 2026

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.

── more in #ai-agents 4 stories · sorted by recency
sponsored brought to you by zahid.host 4,200+ EU-deployed projects
reading about agents? ship yours in a single git push.

Run your AI side-project on zahid.host

EU-based hosting, git-push deploys, automatic HTTPS, no cold starts. Free tier with a custom domain — perfect for shipping the agent you just read about.

$git push zahid main
Live at https://your-agent.zahid.host
Get free account → Pricing
from €0/mo · no card required
LIVE [news/your-api-returned-20…] indexed:0 read:9min 2026-09-20 ·