<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Sudhanshu Thakur</title>
    <description>The latest articles on DEV Community by Sudhanshu Thakur (@sudhanshu_thakur_).</description>
    <link>https://dev.to/sudhanshu_thakur_</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4100466%2F96aeff12-9bf4-4561-a099-4b9fe60147f1.png</url>
      <title>DEV Community: Sudhanshu Thakur</title>
      <link>https://dev.to/sudhanshu_thakur_</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sudhanshu_thakur_"/>
    <language>en</language>
    <item>
      <title>Your API Returned 200 OK. Your AI Agent Still Failed.</title>
      <dc:creator>Sudhanshu Thakur</dc:creator>
      <pubDate>Sun, 20 Sep 2026 10:52:01 +0000</pubDate>
      <link>https://dev.to/sudhanshu_thakur_/your-api-returned-200-ok-your-ai-agent-still-failed-147g</link>
      <guid>https://dev.to/sudhanshu_thakur_/your-api-returned-200-ok-your-ai-agent-still-failed-147g</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8tst8wx5mkdi595hhuvf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F8tst8wx5mkdi595hhuvf.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why successful API calls are no longer enough when AI agents can take real-world actions
&lt;/h3&gt;

&lt;p&gt;For most backend systems, &lt;code&gt;200 OK&lt;/code&gt; is comforting.&lt;/p&gt;

&lt;p&gt;It means the request reached the server, passed validation, and completed successfully.&lt;/p&gt;

&lt;p&gt;For an AI agent, however, &lt;code&gt;200 OK&lt;/code&gt; can hide one of the most dangerous failure modes in modern software:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The API did exactly what the agent asked — but the agent asked for the wrong thing.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine an AI-powered banking assistant.&lt;/p&gt;

&lt;p&gt;A customer says:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Refund the duplicate payment from yesterday.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent retrieves several transactions, identifies what it believes is the duplicate, and calls:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="err"&gt;POST /refunds
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request is authenticated.&lt;/p&gt;

&lt;p&gt;The agent is authorised.&lt;/p&gt;

&lt;p&gt;The transaction ID exists.&lt;/p&gt;

&lt;p&gt;The refund API processes the request successfully.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every technical dashboard is green.&lt;/p&gt;

&lt;p&gt;But the agent selected the wrong transaction.&lt;/p&gt;

&lt;p&gt;The API succeeded.&lt;/p&gt;

&lt;p&gt;The business outcome failed.&lt;/p&gt;

&lt;p&gt;As AI systems evolve from chatbots that &lt;strong&gt;recommend&lt;/strong&gt; actions into agents that &lt;strong&gt;execute&lt;/strong&gt; them, backend engineers need to rethink what “success” actually means.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem: We Treat Success as a Single Layer
&lt;/h2&gt;

&lt;p&gt;Traditional systems usually measure success at several technical levels.&lt;/p&gt;

&lt;p&gt;At the network layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Did the request reach the service?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the API layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Did the service return a successful response?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At the database layer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Did the transaction commit?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That works reasonably well when deterministic application code has already decided what operation should happen.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;refundService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;refund&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;transactionId&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The developer has chosen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;which service to call,&lt;/li&gt;
&lt;li&gt;which transaction to target,&lt;/li&gt;
&lt;li&gt;when the call should happen,&lt;/li&gt;
&lt;li&gt;what should happen after it succeeds.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Agentic systems change this relationship.&lt;/p&gt;

&lt;p&gt;An AI agent may be given tools such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;findCustomer()
lookupTransaction()
issueRefund()
cancelOrder()
sendEmail()
disableAccount()
restartService()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model then determines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Which tool should I call?
Which parameters should I use?
Should I retry?
What should I do next?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have introduced probabilistic reasoning &lt;strong&gt;before deterministic side effects&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That means we need another definition of success.&lt;/p&gt;




&lt;h1&gt;
  
  
  Three Levels of Success
&lt;/h1&gt;

&lt;p&gt;I find it useful to separate agent success into three layers.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Transport Success
&lt;/h2&gt;

&lt;p&gt;Did the technical request complete?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Execution Success
&lt;/h2&gt;

&lt;p&gt;Did the backend perform the requested operation?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Refund created successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Intent Success
&lt;/h2&gt;

&lt;p&gt;Did the system perform the &lt;strong&gt;right action&lt;/strong&gt;, on the &lt;strong&gt;right resource&lt;/strong&gt;, for the &lt;strong&gt;right user&lt;/strong&gt;, under the &lt;strong&gt;right conditions&lt;/strong&gt;, exactly as intended?&lt;/p&gt;

&lt;p&gt;For a refund that might mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Correct customer
Correct transaction
Correct amount
Correct reason
Correct approval
Exactly once
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two are familiar engineering problems.&lt;/p&gt;

&lt;p&gt;The third becomes much more important once AI starts selecting and sequencing actions dynamically.&lt;/p&gt;




&lt;h1&gt;
  
  
  Failure Mode 1: The API Correctly Executes the Wrong Decision
&lt;/h1&gt;

&lt;p&gt;Consider this user request:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Refund the most recent duplicate charge.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The agent receives:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TX-18419"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"merchant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ABC Store"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TX-18491"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"merchant"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ABC Store"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent incorrectly chooses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TX-18491
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and sends:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"transactionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"TX-18491"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"amount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2500&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend validates the request.&lt;/p&gt;

&lt;p&gt;The account has sufficient authority.&lt;/p&gt;

&lt;p&gt;The transaction exists.&lt;/p&gt;

&lt;p&gt;The refund executes.&lt;/p&gt;

&lt;p&gt;Technically, there is no error.&lt;/p&gt;

&lt;p&gt;But the customer wanted another transaction refunded.&lt;/p&gt;

&lt;p&gt;This is an important distinction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;API correctness does not guarantee semantic correctness.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The service knows how to refund a transaction.&lt;/p&gt;

&lt;p&gt;It does not necessarily know whether the AI chose the correct transaction.&lt;/p&gt;




&lt;h1&gt;
  
  
  Failure Mode 2: The Agent Retries Something That Already Worked
&lt;/h1&gt;

&lt;p&gt;Now imagine the refund really is correct.&lt;/p&gt;

&lt;p&gt;The agent calls the service.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent → Refund API
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The refund succeeds.&lt;/p&gt;

&lt;p&gt;But the response is lost.&lt;/p&gt;

&lt;p&gt;The agent sees:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Timeout
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It reasons:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“The refund probably failed. I should retry.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The second call also succeeds.&lt;/p&gt;

&lt;p&gt;Without protection, one user intent may produce multiple real-world side effects.&lt;/p&gt;

&lt;p&gt;This problem is familiar to payment engineers and distributed-systems developers.&lt;/p&gt;

&lt;p&gt;The difference is that with autonomous agents, retries may not come from a predefined retry library.&lt;/p&gt;

&lt;p&gt;The model itself can decide:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Let me try that again.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That makes idempotency even more important.&lt;/p&gt;




&lt;h1&gt;
  
  
  Give Every Important Action an Intent ID
&lt;/h1&gt;

&lt;p&gt;We already use identifiers such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;request_id
trace_id
span_id
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those identify technical execution.&lt;/p&gt;

&lt;p&gt;Agents also need something representing the &lt;strong&gt;business objective&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;intent_id = REFUND_DUPLICATE_CHARGE_8472
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One intent may generate many technical requests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REFUND_DUPLICATE_CHARGE_8472
        |
        +-- lookup transaction
        |
        +-- validate eligibility
        |
        +-- create refund
        |
        +-- update CRM
        |
        +-- notify customer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Suppose the refund API times out.&lt;/p&gt;

&lt;p&gt;Instead of asking:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Should I POST /refunds again?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the system can ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Has REFUND_DUPLICATE_CHARGE_8472
already produced a successful refund?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a much safer abstraction.&lt;/p&gt;




&lt;h2&gt;
  
  
  A Simple Intent Model
&lt;/h2&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;record&lt;/span&gt; &lt;span class="nf"&gt;AgentIntent&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
    &lt;span class="no"&gt;UUID&lt;/span&gt; &lt;span class="n"&gt;intentId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;userId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;resourceId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;IntentStatus&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;String&lt;/span&gt; &lt;span class="n"&gt;resultId&lt;/span&gt;
&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;enum&lt;/span&gt; &lt;span class="nc"&gt;IntentStatus&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="no"&gt;PENDING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;EXECUTING&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;COMPLETED&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;REQUIRES_REVIEW&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="no"&gt;FAILED&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before executing a mutation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nc"&gt;AgentIntent&lt;/span&gt; &lt;span class="n"&gt;intent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;intentRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findById&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intentId&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;orElseThrow&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nc"&gt;IntentStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;COMPLETED&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;previousResult&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;intent&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;resultId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact implementation will vary.&lt;/p&gt;

&lt;p&gt;The principle is what matters:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;A retry should refer to the same business intent instead of silently becoming a new action.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  Failure Mode 3: Every Tool Succeeds, but the Workflow Is Wrong
&lt;/h1&gt;

&lt;p&gt;Imagine an account-closing agent.&lt;/p&gt;

&lt;p&gt;It successfully executes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;✓ Cancel subscription
✓ Revoke API credentials
✓ Delete files
✓ Generate final invoice
✓ Close account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every API returns success.&lt;/p&gt;

&lt;p&gt;But company policy requires:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Export compliance archive
BEFORE
Delete files
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The agent skipped the archive.&lt;/p&gt;

&lt;p&gt;Five green tool calls.&lt;/p&gt;

&lt;p&gt;One invalid business process.&lt;/p&gt;

&lt;p&gt;This is why agent observability cannot stop at:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Tool call succeeded
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Was the workflow itself valid?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Put a Deterministic Gate Between Reasoning and Mutation
&lt;/h1&gt;

&lt;p&gt;For read-only operations, directly exposing tools may be reasonable.&lt;/p&gt;

&lt;p&gt;For high-impact actions, I prefer an architecture like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User Goal
   ↓
AI Agent
   ↓
Intent + Policy Gate
   ↓
Tool Gateway
   ↓
Business API
   ↓
Outcome Verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before issuing a refund, deterministic code can verify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;transaction belongs to authenticated user
AND transaction is refundable
AND amount &amp;lt;= remaining refundable amount
AND approval threshold is satisfied
AND intent has not already completed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model proposes.&lt;/p&gt;

&lt;p&gt;The system verifies.&lt;/p&gt;

&lt;p&gt;The API executes.&lt;/p&gt;

&lt;p&gt;The system verifies again.&lt;/p&gt;

&lt;p&gt;That separation is important.&lt;/p&gt;




&lt;h1&gt;
  
  
  Authorised Does Not Mean Appropriate
&lt;/h1&gt;

&lt;p&gt;Security controls still matter enormously.&lt;/p&gt;

&lt;p&gt;But authorisation alone does not solve every agent problem.&lt;/p&gt;

&lt;p&gt;Suppose an agent legitimately has permission to call:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;restartProductionService()
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The credentials are valid.&lt;/p&gt;

&lt;p&gt;The operator has the correct role.&lt;/p&gt;

&lt;p&gt;But should the service restart now?&lt;/p&gt;

&lt;p&gt;Perhaps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a deployment is currently running
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;an incident is already active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;traffic is at its daily peak
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;another restart happened 30 seconds ago
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Authentication answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Who are you?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Authorisation answers:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Are you allowed to perform this operation?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Agentic systems also need:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Is this action appropriate in the current context?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That requires policy, state, and sometimes human judgement.&lt;/p&gt;




&lt;h1&gt;
  
  
  Define Preconditions and Postconditions
&lt;/h1&gt;

&lt;p&gt;Many tools are described approximately like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;issue_refund&lt;/span&gt;
&lt;span class="na"&gt;description&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Refund a customer transaction&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That tells the model what the tool does.&lt;/p&gt;

&lt;p&gt;It does not define the conditions that make using it safe.&lt;/p&gt;

&lt;p&gt;A stronger contract might be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;tool&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;issue_refund&lt;/span&gt;

&lt;span class="na"&gt;preconditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;transaction belongs to authenticated customer&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;transaction is refundable&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;amount &amp;lt;= remaining refundable balance&lt;/span&gt;

&lt;span class="na"&gt;execution&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;idempotency_required&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

&lt;span class="na"&gt;postconditions&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;refund record exists&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;refund references expected transaction&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;refund amount matches approved amount&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ledger state reconciles&lt;/span&gt;

&lt;span class="na"&gt;approval&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;required_above&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;5000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now success is not simply:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;function returned successfully
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It becomes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;preconditions satisfied
+
action executed
+
postconditions verified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Don’t Let the Agent Grade Its Own Homework
&lt;/h1&gt;

&lt;p&gt;A tempting pattern is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Agent performs action
↓
Agent asks itself:
"Did that work?"
↓
Agent continues
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For low-risk workflows, this may be sufficient.&lt;/p&gt;

&lt;p&gt;For important actions, it is fragile.&lt;/p&gt;

&lt;p&gt;If the model misunderstood the original request, asking the same model whether its interpretation was correct may reproduce the same mistake.&lt;/p&gt;

&lt;p&gt;High-impact actions should be verified against external evidence:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;database state
payment receipt
ledger state
policy engine
independent validator
sensor state
human approval
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model can reason about these signals.&lt;/p&gt;

&lt;p&gt;It should not invent them.&lt;/p&gt;




&lt;h1&gt;
  
  
  Observability Needs to Move Above HTTP
&lt;/h1&gt;

&lt;p&gt;Imagine this dashboard:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;refund-api availability:       99.99%
tool-call success rate:        98.9%
average API latency:           310 ms
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Everything appears healthy.&lt;/p&gt;

&lt;p&gt;But you are not measuring:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wrong-target actions
duplicate mutations
policy violations
unverified outcomes
human reversals
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Agentic systems need higher-level metrics.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;verified_outcome_rate
duplicate_action_rate
postcondition_failure_rate
human_override_rate
ambiguous_outcome_rate
intent_reconciliation_rate
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A meaningful future SLO might look like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;99.95% of high-impact agent intents complete with a verified business outcome and no duplicate side effect.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That tells us far more than API availability.&lt;/p&gt;




&lt;h1&gt;
  
  
  A Safer End-to-End Example
&lt;/h1&gt;

&lt;p&gt;Suppose a user tells an AI commerce agent:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Cancel my duplicate order and refund it.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Instead of immediately executing actions, the workflow could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 10 is the important part.&lt;/p&gt;

&lt;p&gt;The agent does not say “done” because it received &lt;code&gt;200 OK&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;It says “done” because the system verified the intended business outcome.&lt;/p&gt;




&lt;h1&gt;
  
  
  Six Controls I’d Use for High-Impact Agent Actions
&lt;/h1&gt;

&lt;p&gt;For any agent capable of moving money, modifying production systems, changing permissions, deleting information, or performing irreversible actions:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Explicit intent
&lt;/h2&gt;

&lt;p&gt;Persist the actual business objective.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Least-privilege tools
&lt;/h2&gt;

&lt;p&gt;Expose only capabilities required for the task.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Deterministic preconditions
&lt;/h2&gt;

&lt;p&gt;Keep critical business rules outside the model.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Idempotent mutations
&lt;/h2&gt;

&lt;p&gt;Design retries so repeating a request does not repeat the side effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Independent postcondition verification
&lt;/h2&gt;

&lt;p&gt;Verify the resulting state using trusted systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Outcome-level auditability
&lt;/h2&gt;

&lt;p&gt;Connect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;user intent
→ agent decision
→ policy result
→ tool call
→ API response
→ verified business state
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Intent
  ↓
Policy
  ↓
Action
  ↓
Receipt
  ↓
Verification
  ↓
Outcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Prompt
  ↓
Tool
  ↓
200 OK
  ↓
"Done!"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Agent-Facing APIs May Need Richer Contracts
&lt;/h1&gt;

&lt;p&gt;Traditional APIs mainly answer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What operation can I call?
What arguments are required?
What response will I receive?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AI-agent-facing capabilities may need to expose more:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That turns the API from a simple interface into something closer to a &lt;strong&gt;capability contract&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The AI supplies flexible reasoning.&lt;/p&gt;

&lt;p&gt;The surrounding system supplies deterministic guarantees.&lt;/p&gt;




&lt;h1&gt;
  
  
  Final Thought
&lt;/h1&gt;

&lt;p&gt;We are investing enormous effort in making AI agents smarter.&lt;/p&gt;

&lt;p&gt;Better models.&lt;/p&gt;

&lt;p&gt;More context.&lt;/p&gt;

&lt;p&gt;More tools.&lt;/p&gt;

&lt;p&gt;Longer workflows.&lt;/p&gt;

&lt;p&gt;Greater autonomy.&lt;/p&gt;

&lt;p&gt;But once an agent can modify the real world, the hardest production question may not be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Can the model determine what to do?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It may be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How do we prove that what it just did was actually what the user intended?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The most dangerous failure may never generate an exception.&lt;/p&gt;

&lt;p&gt;It may not trigger PagerDuty.&lt;/p&gt;

&lt;p&gt;It may not appear in the error logs.&lt;/p&gt;

&lt;p&gt;Every service may remain healthy.&lt;/p&gt;

&lt;p&gt;All you may see is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight http"&gt;&lt;code&gt;&lt;span class="k"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="m"&gt;1.1&lt;/span&gt; &lt;span class="m"&gt;200&lt;/span&gt; &lt;span class="ne"&gt;OK&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API succeeded.&lt;/p&gt;

&lt;p&gt;The AI agent completed its task.&lt;/p&gt;

&lt;p&gt;And the business still lost.&lt;/p&gt;

&lt;p&gt;That is why production Agentic AI needs more than successful tool calls.&lt;/p&gt;

&lt;p&gt;It needs &lt;strong&gt;verified outcomes&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  References and Further Reading
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;OWASP — LLM06: Excessive Agency:&lt;/strong&gt; guidance on risks caused by excessive functionality, permissions, and autonomy in LLM applications.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;OWASP — Agentic AI Security:&lt;/strong&gt; emerging guidance for autonomous AI applications and tool-enabled agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;NIST — AI Agent Identity and Authorization:&lt;/strong&gt; work examining how established identity and authorisation practices apply to software and AI agents.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Well-Architected Framework — Idempotent Mutating Operations:&lt;/strong&gt; guidance for making retries safe in distributed systems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stripe API Documentation — Idempotent Requests:&lt;/strong&gt; a practical example of retry-safe financial API mutations.&lt;/li&gt;
&lt;/ul&gt;




</description>
      <category>ai</category>
      <category>webdev</category>
      <category>programming</category>
      <category>productivity</category>
    </item>
  </channel>
</rss>
