<?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: satya-anguluri</title>
    <description>The latest articles on DEV Community by satya-anguluri (@satyaanguluri).</description>
    <link>https://dev.to/satyaanguluri</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%2F4026548%2F2ca41c1a-88eb-43e5-8569-46bfd303f2ae.png</url>
      <title>DEV Community: satya-anguluri</title>
      <link>https://dev.to/satyaanguluri</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/satyaanguluri"/>
    <language>en</language>
    <item>
      <title>The Agent Charged the Customer Twice. The Logs Said Everything Was Fine.</title>
      <dc:creator>satya-anguluri</dc:creator>
      <pubDate>Sun, 13 Sep 2026 21:14:26 +0000</pubDate>
      <link>https://dev.to/satyaanguluri/the-agent-charged-the-customer-twice-the-logs-said-everything-was-fine-3ln6</link>
      <guid>https://dev.to/satyaanguluri/the-agent-charged-the-customer-twice-the-logs-said-everything-was-fine-3ln6</guid>
      <description>&lt;h1&gt;
  
  
  The Agent Charged the Customer Twice. Then Reported Success.
&lt;/h1&gt;

&lt;p&gt;&lt;em&gt;I run &lt;a href="https://engineerprep.io" rel="noopener noreferrer"&gt;EngineerPrep&lt;/a&gt;, where I build executable labs around production AI-agent failure patterns. This lab reproduces a dangerous distributed-systems failure: an agent mistakes a timeout for a failed payment and charges the customer again.&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The setup
&lt;/h2&gt;

&lt;p&gt;An AI agent handles an order workflow.&lt;/p&gt;

&lt;p&gt;To complete an order, it calls a payment tool:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;capture_payment(
    order_id,
    amount,
    idempotency_key
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tool calls a payment processor through a Spring Boot service.&lt;/p&gt;

&lt;p&gt;The agent is allowed to retry when a tool call fails. That sounds reasonable—until the tool performs an irreversible side effect.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agent saw
&lt;/h2&gt;

&lt;p&gt;For order &lt;code&gt;ORD-1001&lt;/code&gt;, the execution trace showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENT  action=capture_payment
       order=ORD-1001
       amount=4999
       idempotency_key=pay-0001

TOOL   result=TIMEOUT
       message="No response received within 2000ms"

AGENT  decision="Payment attempt failed. Retrying capture."

AGENT  action=capture_payment
       order=ORD-1001
       amount=4999
       idempotency_key=pay-0002

TOOL   result=SUCCESS
       receipt=rcpt-pay-0002

AGENT  final="Payment completed successfully."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From the agent’s perspective, the first attempt failed and the second succeeded.&lt;/p&gt;

&lt;p&gt;The workflow ended successfully. The order was confirmed. No application error remained open.&lt;/p&gt;

&lt;p&gt;But the customer was charged twice.&lt;/p&gt;

&lt;h2&gt;
  
  
  What actually happened
&lt;/h2&gt;

&lt;p&gt;The payment processor’s ledger showed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CAPTURED  ORD-1001  4999  key=pay-0001
CAPTURED  ORD-1001  4999  key=pay-0002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first payment did not fail.&lt;/p&gt;

&lt;p&gt;The processor captured &lt;code&gt;$49.99&lt;/code&gt;, but the network connection reset while returning the response. The agent received a timeout even though the financial side effect had already happened.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No response received = payment failed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But the correct interpretation was:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;No response received = payment outcome unknown
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That difference cost the customer another &lt;code&gt;$49.99&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The agent’s mistake
&lt;/h2&gt;

&lt;p&gt;The agent made two unsafe decisions.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. It classified &lt;code&gt;TIMEOUT&lt;/code&gt; as &lt;code&gt;FAILED&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;A timeout describes what the caller observed. It does not establish what happened inside the payment processor.&lt;/p&gt;

&lt;p&gt;The payment could have:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Failed before reaching the processor&lt;/li&gt;
&lt;li&gt;Reached the processor but failed&lt;/li&gt;
&lt;li&gt;Completed successfully while its response was lost&lt;/li&gt;
&lt;li&gt;Still been processing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent had insufficient evidence to call the operation a failure.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. It created a new identity for the retry
&lt;/h3&gt;

&lt;p&gt;The first call used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;idempotency_key=pay-0001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The retry used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;idempotency_key=pay-0002
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To the processor, those were two different payment operations. It therefore captured both.&lt;/p&gt;

&lt;p&gt;The agent believed it was retrying the same action. The processor saw a new purchase.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this is an agent failure
&lt;/h2&gt;

&lt;p&gt;The payment service did not independently initiate the second charge.&lt;/p&gt;

&lt;p&gt;The agent did.&lt;/p&gt;

&lt;p&gt;It examined an ambiguous tool result, concluded that the payment had failed, constructed another tool call with a new operation identity, and executed it.&lt;/p&gt;

&lt;p&gt;Each local decision looked plausible:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The tool timed out&lt;/li&gt;
&lt;li&gt;The workflow still needed payment&lt;/li&gt;
&lt;li&gt;Retrying transient failures was allowed&lt;/li&gt;
&lt;li&gt;A new request object received a new identifier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The failure appeared only when those decisions were composed around a side-effecting tool.&lt;/p&gt;

&lt;p&gt;That is exactly what makes agent failures dangerous.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the agent should have done
&lt;/h2&gt;

&lt;p&gt;A timeout on a side-effecting operation should move the workflow into an &lt;code&gt;UNKNOWN&lt;/code&gt; state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TIMEOUT
   ↓
Mark payment outcome UNKNOWN
   ↓
Query payment status using pay-0001
   ↓
CAPTURED → continue without another charge
NOT_FOUND → retry using pay-0001
UNKNOWN → wait or request human review
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If a retry is appropriate, it must reuse the original idempotency key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AGENT  action=capture_payment
       order=ORD-1001
       amount=4999
       idempotency_key=pay-0001
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The processor can then recognize the duplicate request and return the original result instead of charging the customer again.&lt;/p&gt;

&lt;h2&gt;
  
  
  But prompting the agent correctly is not enough
&lt;/h2&gt;

&lt;p&gt;We should not rely on an LLM to remember this rule every time.&lt;/p&gt;

&lt;p&gt;The payment tool must enforce it deterministically.&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;String&lt;/span&gt; &lt;span class="n"&gt;idempotencyKey&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
    &lt;span class="n"&gt;paymentOperationRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrCreateKey&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

&lt;span class="n"&gt;processor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;capture&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;order&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;idempotencyKey&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key must be persisted for the logical payment operation and reused across:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Agent retries&lt;/li&gt;
&lt;li&gt;Service retries&lt;/li&gt;
&lt;li&gt;Process crashes&lt;/li&gt;
&lt;li&gt;Queue redelivery&lt;/li&gt;
&lt;li&gt;Workflow restarts&lt;/li&gt;
&lt;li&gt;A second application instance&lt;/li&gt;
&lt;li&gt;Replanned tool calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The agent may request another capture, but the application must prevent that request from becoming another charge.&lt;/p&gt;

&lt;h2&gt;
  
  
  The production lesson
&lt;/h2&gt;

&lt;p&gt;The agent caused the unsafe retry.&lt;/p&gt;

&lt;p&gt;The system allowed the agent’s incorrect inference to become a duplicated financial side effect.&lt;/p&gt;

&lt;p&gt;Both matter.&lt;/p&gt;

&lt;p&gt;“Improve the prompt” is not an adequate safeguard for payments, refunds, emails, infrastructure changes, database writes, or any other action that cannot be safely repeated.&lt;/p&gt;

&lt;p&gt;Agentic systems need deterministic boundaries around nondeterministic reasoning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stable operation identities&lt;/li&gt;
&lt;li&gt;Provider-side idempotency&lt;/li&gt;
&lt;li&gt;Explicit &lt;code&gt;UNKNOWN&lt;/code&gt; states&lt;/li&gt;
&lt;li&gt;Outcome reconciliation&lt;/li&gt;
&lt;li&gt;Restricted retry policies&lt;/li&gt;
&lt;li&gt;Side-effect ledgers&lt;/li&gt;
&lt;li&gt;Human escalation when the outcome cannot be established&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The rule I took from this
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A timeout is not a failure. It is an unknown outcome.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Before an agent repeats a side-effecting tool call, the system must answer:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If the first operation succeeded but its response was lost, what prevents this next call from performing the side effect again?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If the answer is “the agent should realize that,” the system is not safe.&lt;/p&gt;

&lt;p&gt;You can reproduce the incident, inspect the agent trace and payment ledger, and test the remediation in the free interactive lab:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://engineerprep.io/failure-labs/agent-charged-twice" rel="noopener noreferrer"&gt;engineerprep.io/failure-labs/agent-charged-twice&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It’s one of three production incident labs currently available on EngineerPrep.&lt;/p&gt;

&lt;h1&gt;
  
  
  aiagents #java #springboot #distributedsystems
&lt;/h1&gt;

</description>
      <category>architecture</category>
      <category>backend</category>
      <category>java</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>I built an AI engineering course where every lesson is a runnable Spring Boot project (Ollama, no API key)</title>
      <dc:creator>satya-anguluri</dc:creator>
      <pubDate>Thu, 27 Aug 2026 19:19:03 +0000</pubDate>
      <link>https://dev.to/satyaanguluri/i-built-an-ai-engineering-course-where-every-lesson-is-a-runnable-spring-boot-project-ollama-no-5h0h</link>
      <guid>https://dev.to/satyaanguluri/i-built-an-ai-engineering-course-where-every-lesson-is-a-runnable-spring-boot-project-ollama-no-5h0h</guid>
      <description>&lt;p&gt;Hi everyone — I’m a Java/Spring Boot engineer with 17+ years of experience, and I’ve spent the past several months building EngineerPrep.&lt;/p&gt;

&lt;p&gt;I kept running into the same problem while learning AI engineering: many courses either stay at the conceptual level or demonstrate everything inside notebooks. They explain what tokens, embeddings, RAG and agents are, but not how these pieces behave inside a production application.&lt;/p&gt;

&lt;p&gt;So I built the kind of learning path I wanted:&lt;/p&gt;

&lt;p&gt;73 focused AI engineering lessons&lt;/p&gt;

&lt;p&gt;Short chapters instead of long video lectures&lt;/p&gt;

&lt;p&gt;Visual walkthroughs of what happens inside the system&lt;/p&gt;

&lt;p&gt;Production incidents and failure scenarios&lt;/p&gt;

&lt;p&gt;Hands-on implementation labs&lt;/p&gt;

&lt;p&gt;Runnable Maven projects with local Ollama support&lt;/p&gt;

&lt;p&gt;Optional OpenAI and Amazon Bedrock configurations&lt;/p&gt;

&lt;p&gt;An AI mentor that answers within the context of the current lesson&lt;/p&gt;

&lt;p&gt;The curriculum progresses through:&lt;/p&gt;

&lt;p&gt;LLM Foundations&lt;/p&gt;

&lt;p&gt;Prompt Engineering&lt;/p&gt;

&lt;p&gt;Structured Output and Validation&lt;/p&gt;

&lt;p&gt;RAG and Embeddings&lt;/p&gt;

&lt;p&gt;AI Memory&lt;/p&gt;

&lt;p&gt;Agents and Tool Calling&lt;/p&gt;

&lt;p&gt;Model Evaluation&lt;/p&gt;

&lt;p&gt;AI Security&lt;/p&gt;

&lt;p&gt;Production AI Systems&lt;/p&gt;

&lt;p&gt;The complete LLM Foundations module is free: 15 lessons, hands-on labs and a starter project that runs locally with Ollama. No paid AI API or credit card is required.&lt;/p&gt;

&lt;p&gt;EngineerPrep is intentionally focused: one structured path for working software engineers who want to understand how AI systems are designed, implemented and debugged in production—especially with Java and Spring Boot.&lt;/p&gt;

&lt;p&gt;You can try it here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://engineerprep.io" rel="noopener noreferrer"&gt;https://engineerprep.io&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I would genuinely appreciate feedback on three things:&lt;/p&gt;

&lt;p&gt;Does the first lesson make the value clear quickly?&lt;/p&gt;

&lt;p&gt;Is the lesson → incident → project structure useful?&lt;/p&gt;

&lt;p&gt;What would prevent you from completing the free module?&lt;/p&gt;

&lt;p&gt;I built this independently, so direct criticism is welcome. It will help me decide what to improve next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>java</category>
      <category>springboot</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Hi everyone. This is Satya , java developer from the past 18 years. Interested very much in AI stuff.</title>
      <dc:creator>satya-anguluri</dc:creator>
      <pubDate>Tue, 14 Jul 2026 21:27:39 +0000</pubDate>
      <link>https://dev.to/satyaanguluri/hi-everyone-this-is-satya-java-developer-from-the-past-18-years-interested-very-much-in-ai-n7j</link>
      <guid>https://dev.to/satyaanguluri/hi-everyone-this-is-satya-java-developer-from-the-past-18-years-interested-very-much-in-ai-n7j</guid>
      <description></description>
    </item>
    <item>
      <title>Capstead</title>
      <dc:creator>satya-anguluri</dc:creator>
      <pubDate>Mon, 13 Jul 2026 16:36:02 +0000</pubDate>
      <link>https://dev.to/satyaanguluri/i-built-capstead-a-governance-observability-layer-for-ai-capabilities-in-spring-boot-333l</link>
      <guid>https://dev.to/satyaanguluri/i-built-capstead-a-governance-observability-layer-for-ai-capabilities-in-spring-boot-333l</guid>
      <description>&lt;h1&gt;
  
  
  I built Capstead: A Governance &amp;amp; Observability Layer for AI Capabilities in Spring Boot
&lt;/h1&gt;

&lt;p&gt;As more teams integrate AI into their Spring Boot applications, I kept running into the same questions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which AI capabilities does our application expose?&lt;/li&gt;
&lt;li&gt;Who owns each capability?&lt;/li&gt;
&lt;li&gt;How much does each capability cost?&lt;/li&gt;
&lt;li&gt;Which capabilities are failing or exceeding latency budgets?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Frameworks like Spring AI provide excellent model integrations and metrics, but I wanted visibility at the &lt;strong&gt;business capability&lt;/strong&gt; level rather than just individual model calls.&lt;/p&gt;

&lt;p&gt;That's why I built &lt;strong&gt;Capstead&lt;/strong&gt;, an open-source governance and observability control plane for AI capabilities in Spring Boot.&lt;/p&gt;

&lt;p&gt;With a simple &lt;code&gt;@Capability&lt;/code&gt; annotation (or a bodyless &lt;code&gt;@CapabilityClient&lt;/code&gt; interface), Capstead provides:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;📋 Live capability catalog&lt;/li&gt;
&lt;li&gt;💰 Per-capability cost attribution, token usage, latency, and success rate&lt;/li&gt;
&lt;li&gt;🎯 Daily budget enforcement&lt;/li&gt;
&lt;li&gt;🌳 Durable execution history with parent/child execution trees&lt;/li&gt;
&lt;li&gt;🤖 MCP export so capabilities can be exposed as agent tools&lt;/li&gt;
&lt;li&gt;🔌 Provider-neutral support (Spring AI, LangChain4j, custom SDKs, or any HTTP client)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is to provide a governance layer on top of existing AI integrations without changing how developers build AI applications.&lt;/p&gt;

&lt;p&gt;I'd love feedback from engineers building AI-enabled systems:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is this a problem you've encountered?&lt;/li&gt;
&lt;li&gt;What governance or observability features are you missing today?&lt;/li&gt;
&lt;li&gt;What integrations would you like to see next?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;GitHub: &lt;a href="https://github.com/satya-anguluri/capstead" rel="noopener noreferrer"&gt;https://github.com/satya-anguluri/capstead&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'd really appreciate your thoughts and suggestions!&lt;/p&gt;

&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%2F16rhz4zsrunjmbzz1ygf.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%2F16rhz4zsrunjmbzz1ygf.png" alt=" " width="800" height="473"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
