<?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: Subhamoy Datta</title>
    <description>The latest articles on DEV Community by Subhamoy Datta (@itssubhamoy).</description>
    <link>https://dev.to/itssubhamoy</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%2F4111444%2Fec33dcca-c22c-48f9-b9b9-0c4043577950.jpg</url>
      <title>DEV Community: Subhamoy Datta</title>
      <link>https://dev.to/itssubhamoy</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itssubhamoy"/>
    <language>en</language>
    <item>
      <title>What Giving Interviews Taught Me Beyond Just Getting an Internship</title>
      <dc:creator>Subhamoy Datta</dc:creator>
      <pubDate>Fri, 02 Oct 2026 13:08:44 +0000</pubDate>
      <link>https://dev.to/itssubhamoy/what-giving-interviews-taught-me-beyond-just-getting-an-internship-88</link>
      <guid>https://dev.to/itssubhamoy/what-giving-interviews-taught-me-beyond-just-getting-an-internship-88</guid>
      <description>&lt;p&gt;Over the last month, I’ve given multiple internship interviews and completed several technical assessments as part of internship hiring processes.&lt;/p&gt;

&lt;p&gt;Obviously, the main goal was to get an internship.&lt;/p&gt;

&lt;p&gt;But after going through these interviews and assessments, I realized that the process itself was teaching me a lot.&lt;/p&gt;

&lt;p&gt;It improved the way I communicate, increased my confidence, made me much more comfortable with interviews, and also changed the way I use AI coding agents.&lt;/p&gt;

&lt;p&gt;So I thought I’d share some of the things I learned from the experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Communication Got Better
&lt;/h2&gt;

&lt;p&gt;One of the biggest changes I noticed was in my communication.&lt;/p&gt;

&lt;p&gt;Knowing something and being able to explain it clearly are two different skills.&lt;/p&gt;

&lt;p&gt;During interviews, I had to explain my projects, the technologies I used, why I made certain technical decisions, how different parts of my projects worked, and how I would approach different problems.&lt;/p&gt;

&lt;p&gt;When you build something yourself, a lot of this exists naturally in your head.&lt;/p&gt;

&lt;p&gt;But during an interview, you have to turn those thoughts into a clear explanation that another person can understand.&lt;/p&gt;

&lt;p&gt;After giving multiple interviews, I became much more comfortable doing that.&lt;/p&gt;

&lt;p&gt;I can explain my projects and technical decisions more clearly now, and I’m also more comfortable having technical conversations in general.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Confidence Increased
&lt;/h2&gt;

&lt;p&gt;Another major change was confidence.&lt;/p&gt;

&lt;p&gt;Earlier, interviews naturally came with some fear.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if they ask something I don't know?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if I can't answer a question?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if something goes wrong?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After going through multiple internship interviews, that fear reduced a lot.&lt;/p&gt;

&lt;p&gt;You eventually realize that you don't need to know the answer to every single question.&lt;/p&gt;

&lt;p&gt;Sometimes you know the answer immediately.&lt;/p&gt;

&lt;p&gt;Sometimes you need to think.&lt;/p&gt;

&lt;p&gt;Sometimes you have to reason your way through the problem.&lt;/p&gt;

&lt;p&gt;And sometimes you simply don't know something.&lt;/p&gt;

&lt;p&gt;Going through that experience repeatedly made interviews feel much more normal to me.&lt;/p&gt;

&lt;p&gt;Instead of constantly worrying about what might be asked, I can focus more on the actual conversation and the problem in front of me.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Coding Skills Are Becoming More Relevant
&lt;/h2&gt;

&lt;p&gt;Another interesting thing I noticed during some of these internship interviews and assessments was the importance of AI coding tools.&lt;/p&gt;

&lt;p&gt;I came across questions about tools like Claude Code and Codex and about using AI agents while coding.&lt;/p&gt;

&lt;p&gt;That made one thing very clear to me:&lt;/p&gt;

&lt;p&gt;Knowing how to use AI for coding is becoming a useful development skill.&lt;/p&gt;

&lt;p&gt;But by "using AI," I don't mean just opening an agent and saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build this feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important part is knowing how to actually work with the agent.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Giving it enough context about the codebase&lt;/li&gt;
&lt;li&gt;Clearly explaining what you want to achieve&lt;/li&gt;
&lt;li&gt;Breaking larger problems into manageable tasks&lt;/li&gt;
&lt;li&gt;Understanding the code it generates&lt;/li&gt;
&lt;li&gt;Reviewing its changes instead of blindly accepting them&lt;/li&gt;
&lt;li&gt;Finding issues in AI-generated code&lt;/li&gt;
&lt;li&gt;Recognizing when the agent is going in the wrong direction&lt;/li&gt;
&lt;li&gt;Giving it better direction when it gets stuck&lt;/li&gt;
&lt;li&gt;Testing and verifying the final implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These internship assessments gave me more opportunities to work this way, especially when I had to complete something within a limited amount of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Coding Isn't About Letting AI Do Everything
&lt;/h2&gt;

&lt;p&gt;This is probably one of the most important things I learned from the whole experience.&lt;/p&gt;

&lt;p&gt;Using an AI coding agent doesn't mean giving it a task and accepting whatever it produces.&lt;/p&gt;

&lt;p&gt;AI agents can generate a lot of code quickly.&lt;/p&gt;

&lt;p&gt;But they can also be wrong.&lt;/p&gt;

&lt;p&gt;Sometimes an agent fixes one problem and creates another.&lt;/p&gt;

&lt;p&gt;Sometimes it misunderstands the architecture.&lt;/p&gt;

&lt;p&gt;Sometimes it changes something that didn't need to be changed.&lt;/p&gt;

&lt;p&gt;And sometimes it gets stuck repeating almost the same solution again and again.&lt;/p&gt;

&lt;p&gt;That's where your own technical understanding becomes important.&lt;/p&gt;

&lt;p&gt;You need to understand what the agent changed and why.&lt;/p&gt;

&lt;p&gt;When something doesn't work, you need to inspect the generated code, understand the error, identify where the problem actually is, and then either fix it yourself or give the agent better direction.&lt;/p&gt;

&lt;p&gt;Over the last month, I became much better at recognizing these kinds of issues in AI-generated code.&lt;/p&gt;

&lt;p&gt;I also became better at knowing when to let the agent continue working and when I should take control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Way I Use AI Coding Agents Got Better
&lt;/h2&gt;

&lt;p&gt;Technical assessments usually have one thing that normal personal projects don't always have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A strict deadline.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might have only a few hours or a couple of days to understand the requirements, plan the solution, implement everything, test it, fix issues, and submit it.&lt;/p&gt;

&lt;p&gt;That changes how you use AI.&lt;/p&gt;

&lt;p&gt;You can't spend hours going back and forth with an agent while it keeps trying the wrong approach.&lt;/p&gt;

&lt;p&gt;I learned to be more intentional about how I use coding agents.&lt;/p&gt;

&lt;p&gt;Instead of expecting the agent to handle everything, I use it as part of my development workflow.&lt;/p&gt;

&lt;p&gt;I decide what I want to build.&lt;/p&gt;

&lt;p&gt;I understand the architecture.&lt;/p&gt;

&lt;p&gt;I give the agent the necessary context.&lt;/p&gt;

&lt;p&gt;I review what it produces.&lt;/p&gt;

&lt;p&gt;If the generated code has issues, I identify them.&lt;/p&gt;

&lt;p&gt;If the agent gets stuck, I change the approach or step in myself.&lt;/p&gt;

&lt;p&gt;And before considering something complete, I verify that it actually works.&lt;/p&gt;

&lt;p&gt;For me, becoming better at agentic coding isn't about getting AI to write more code.&lt;/p&gt;

&lt;p&gt;It's about becoming better at &lt;strong&gt;working with AI while still staying in control of the code.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Working Under Time Limits Taught Me a Lot
&lt;/h2&gt;

&lt;p&gt;The assessments also gave me experience building under pressure.&lt;/p&gt;

&lt;p&gt;When you're working on your own project, it's easy to say:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I'll finish this tomorrow."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An assessment doesn't always give you that option.&lt;/p&gt;

&lt;p&gt;There is a deadline.&lt;/p&gt;

&lt;p&gt;That means you have to understand the requirements quickly, decide what actually matters, manage your time, build the solution, test it, and submit it.&lt;/p&gt;

&lt;p&gt;That experience helped me become more comfortable building projects within strict time limits.&lt;/p&gt;

&lt;p&gt;It also forced me to think more carefully about where AI agents could actually save time and where spending time reviewing their output was more important.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Biggest Thing I Got From These Interviews
&lt;/h2&gt;

&lt;p&gt;Not every internship interview turns into an offer.&lt;/p&gt;

&lt;p&gt;Not every technical assessment leads to the next round.&lt;/p&gt;

&lt;p&gt;But I don't think that makes the experience useless.&lt;/p&gt;

&lt;p&gt;Over the last month, these interviews and assessments have given me much more than just opportunities to apply for internships.&lt;/p&gt;

&lt;p&gt;My communication improved.&lt;/p&gt;

&lt;p&gt;My confidence increased.&lt;/p&gt;

&lt;p&gt;My fear of interviews reduced significantly.&lt;/p&gt;

&lt;p&gt;I became better at identifying problems in AI-generated code.&lt;/p&gt;

&lt;p&gt;I became better at using AI coding agents effectively.&lt;/p&gt;

&lt;p&gt;And I became more comfortable building projects under strict deadlines.&lt;/p&gt;

&lt;p&gt;Most importantly, interviews don't feel like some huge scary event anymore.&lt;/p&gt;

&lt;p&gt;They're conversations.&lt;/p&gt;

&lt;p&gt;They're technical discussions.&lt;/p&gt;

&lt;p&gt;They're opportunities to explain what I've built, solve problems, and experience the kind of situations that developers deal with in the real world.&lt;/p&gt;

&lt;p&gt;Of course, I still want the internship at the end of the process.&lt;/p&gt;

&lt;p&gt;But even before getting that final result, the process itself has already taught me a lot.&lt;/p&gt;

</description>
      <category>internship</category>
      <category>interview</category>
      <category>career</category>
    </item>
    <item>
      <title>What Giving Interviews Taught Me Beyond Just Getting an Internship</title>
      <dc:creator>Subhamoy Datta</dc:creator>
      <pubDate>Fri, 02 Oct 2026 12:54:59 +0000</pubDate>
      <link>https://dev.to/itssubhamoy/what-giving-interviews-taught-me-beyond-just-getting-a-job-3j3p</link>
      <guid>https://dev.to/itssubhamoy/what-giving-interviews-taught-me-beyond-just-getting-a-job-3j3p</guid>
      <description>&lt;p&gt;Over the last month, I’ve given multiple internship interviews and completed several technical assessments as part of internship hiring processes.&lt;/p&gt;

&lt;p&gt;Obviously, the main goal was to get an internship.&lt;/p&gt;

&lt;p&gt;But after going through these interviews and assessments, I realized that the process itself was teaching me a lot.&lt;/p&gt;

&lt;p&gt;It improved the way I communicate, increased my confidence, made me much more comfortable with interviews, and also changed the way I use AI coding agents.&lt;/p&gt;

&lt;p&gt;So I thought I’d share some of the things I learned from the experience.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Communication Got Better
&lt;/h2&gt;

&lt;p&gt;One of the biggest changes I noticed was in my communication.&lt;/p&gt;

&lt;p&gt;Knowing something and being able to explain it clearly are two different skills.&lt;/p&gt;

&lt;p&gt;During interviews, I had to explain my projects, the technologies I used, why I made certain technical decisions, how different parts of my projects worked, and how I would approach different problems.&lt;/p&gt;

&lt;p&gt;When you build something yourself, a lot of this exists naturally in your head.&lt;/p&gt;

&lt;p&gt;But during an interview, you have to turn those thoughts into a clear explanation that another person can understand.&lt;/p&gt;

&lt;p&gt;After giving multiple interviews, I became much more comfortable doing that.&lt;/p&gt;

&lt;p&gt;I can explain my projects and technical decisions more clearly now, and I’m also more comfortable having technical conversations in general.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Confidence Increased
&lt;/h2&gt;

&lt;p&gt;Another major change was confidence.&lt;/p&gt;

&lt;p&gt;Earlier, interviews naturally came with some fear.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if they ask something I don't know?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if I can't answer a question?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;What if something goes wrong?&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;After going through multiple internship interviews, that fear reduced a lot.&lt;/p&gt;

&lt;p&gt;You eventually realize that you don't need to know the answer to every single question.&lt;/p&gt;

&lt;p&gt;Sometimes you know the answer immediately.&lt;/p&gt;

&lt;p&gt;Sometimes you need to think.&lt;/p&gt;

&lt;p&gt;Sometimes you have to reason your way through the problem.&lt;/p&gt;

&lt;p&gt;And sometimes you simply don't know something.&lt;/p&gt;

&lt;p&gt;Going through that experience repeatedly made interviews feel much more normal to me.&lt;/p&gt;

&lt;p&gt;Instead of constantly worrying about what might be asked, I can focus more on the actual conversation and the problem in front of me.&lt;/p&gt;

&lt;h2&gt;
  
  
  AI Coding Skills Are Becoming More Relevant
&lt;/h2&gt;

&lt;p&gt;Another interesting thing I noticed during some of these internship interviews and assessments was the importance of AI coding tools.&lt;/p&gt;

&lt;p&gt;I came across questions about tools like Claude Code and Codex and about using AI agents while coding.&lt;/p&gt;

&lt;p&gt;That made one thing very clear to me:&lt;/p&gt;

&lt;p&gt;Knowing how to use AI for coding is becoming a useful development skill.&lt;/p&gt;

&lt;p&gt;But by "using AI," I don't mean just opening an agent and saying:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Build this feature.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The important part is knowing how to actually work with the agent.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Giving it enough context about the codebase&lt;/li&gt;
&lt;li&gt;Clearly explaining what you want to achieve&lt;/li&gt;
&lt;li&gt;Breaking larger problems into manageable tasks&lt;/li&gt;
&lt;li&gt;Understanding the code it generates&lt;/li&gt;
&lt;li&gt;Reviewing its changes instead of blindly accepting them&lt;/li&gt;
&lt;li&gt;Finding issues in AI-generated code&lt;/li&gt;
&lt;li&gt;Recognizing when the agent is going in the wrong direction&lt;/li&gt;
&lt;li&gt;Giving it better direction when it gets stuck&lt;/li&gt;
&lt;li&gt;Testing and verifying the final implementation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These internship assessments gave me more opportunities to work this way, especially when I had to complete something within a limited amount of time.&lt;/p&gt;

&lt;h2&gt;
  
  
  Agentic Coding Isn't About Letting AI Do Everything
&lt;/h2&gt;

&lt;p&gt;This is probably one of the most important things I learned from the whole experience.&lt;/p&gt;

&lt;p&gt;Using an AI coding agent doesn't mean giving it a task and accepting whatever it produces.&lt;/p&gt;

&lt;p&gt;AI agents can generate a lot of code quickly.&lt;/p&gt;

&lt;p&gt;But they can also be wrong.&lt;/p&gt;

&lt;p&gt;Sometimes an agent fixes one problem and creates another.&lt;/p&gt;

&lt;p&gt;Sometimes it misunderstands the architecture.&lt;/p&gt;

&lt;p&gt;Sometimes it changes something that didn't need to be changed.&lt;/p&gt;

&lt;p&gt;And sometimes it gets stuck repeating almost the same solution again and again.&lt;/p&gt;

&lt;p&gt;That's where your own technical understanding becomes important.&lt;/p&gt;

&lt;p&gt;You need to understand what the agent changed and why.&lt;/p&gt;

&lt;p&gt;When something doesn't work, you need to inspect the generated code, understand the error, identify where the problem actually is, and then either fix it yourself or give the agent better direction.&lt;/p&gt;

&lt;p&gt;Over the last month, I became much better at recognizing these kinds of issues in AI-generated code.&lt;/p&gt;

&lt;p&gt;I also became better at knowing when to let the agent continue working and when I should take control.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Way I Use AI Coding Agents Got Better
&lt;/h2&gt;

&lt;p&gt;Technical assessments usually have one thing that normal personal projects don't always have:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;A strict deadline.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You might have only a few hours or a couple of days to understand the requirements, plan the solution, implement everything, test it, fix issues, and submit it.&lt;/p&gt;

&lt;p&gt;That changes how you use AI.&lt;/p&gt;

&lt;p&gt;You can't spend hours going back and forth with an agent while it keeps trying the wrong approach.&lt;/p&gt;

&lt;p&gt;I learned to be more intentional about how I use coding agents.&lt;/p&gt;

&lt;p&gt;Instead of expecting the agent to handle everything, I use it as part of my development workflow.&lt;/p&gt;

&lt;p&gt;I decide what I want to build.&lt;/p&gt;

&lt;p&gt;I understand the architecture.&lt;/p&gt;

&lt;p&gt;I give the agent the necessary context.&lt;/p&gt;

&lt;p&gt;I review what it produces.&lt;/p&gt;

&lt;p&gt;If the generated code has issues, I identify them.&lt;/p&gt;

&lt;p&gt;If the agent gets stuck, I change the approach or step in myself.&lt;/p&gt;

&lt;p&gt;And before considering something complete, I verify that it actually works.&lt;/p&gt;

&lt;p&gt;For me, becoming better at agentic coding isn't about getting AI to write more code.&lt;/p&gt;

&lt;p&gt;It's about becoming better at &lt;strong&gt;working with AI while still staying in control of the code.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Working Under Time Limits Taught Me a Lot
&lt;/h2&gt;

&lt;p&gt;The assessments also gave me experience building under pressure.&lt;/p&gt;

&lt;p&gt;When you're working on your own project, it's easy to say:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;"I'll finish this tomorrow."&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;An assessment doesn't always give you that option.&lt;/p&gt;

&lt;p&gt;There is a deadline.&lt;/p&gt;

&lt;p&gt;That means you have to understand the requirements quickly, decide what actually matters, manage your time, build the solution, test it, and submit it.&lt;/p&gt;

&lt;p&gt;That experience helped me become more comfortable building projects within strict time limits.&lt;/p&gt;

&lt;p&gt;It also forced me to think more carefully about where AI agents could actually save time and where spending time reviewing their output was more important.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Biggest Thing I Got From These Interviews
&lt;/h2&gt;

&lt;p&gt;Not every internship interview turns into an offer.&lt;/p&gt;

&lt;p&gt;Not every technical assessment leads to the next round.&lt;/p&gt;

&lt;p&gt;But I don't think that makes the experience useless.&lt;/p&gt;

&lt;p&gt;Over the last month, these interviews and assessments have given me much more than just opportunities to apply for internships.&lt;/p&gt;

&lt;p&gt;My communication improved.&lt;/p&gt;

&lt;p&gt;My confidence increased.&lt;/p&gt;

&lt;p&gt;My fear of interviews reduced significantly.&lt;/p&gt;

&lt;p&gt;I became better at identifying problems in AI-generated code.&lt;/p&gt;

&lt;p&gt;I became better at using AI coding agents effectively.&lt;/p&gt;

&lt;p&gt;And I became more comfortable building projects under strict deadlines.&lt;/p&gt;

&lt;p&gt;Most importantly, interviews don't feel like some huge scary event anymore.&lt;/p&gt;

&lt;p&gt;They're conversations.&lt;/p&gt;

&lt;p&gt;They're technical discussions.&lt;/p&gt;

&lt;p&gt;They're opportunities to explain what I've built, solve problems, and experience the kind of situations that developers deal with in the real world.&lt;/p&gt;

&lt;p&gt;Of course, I still want the internship at the end of the process.&lt;/p&gt;

&lt;p&gt;But even before getting that final result, the process itself has already taught me a lot.&lt;/p&gt;

</description>
      <category>interview</category>
      <category>career</category>
      <category>internship</category>
    </item>
    <item>
      <title>How I Implemented Memory in my AI Agent REXA</title>
      <dc:creator>Subhamoy Datta</dc:creator>
      <pubDate>Thu, 17 Sep 2026 18:41:35 +0000</pubDate>
      <link>https://dev.to/itssubhamoy/how-i-implemented-memory-in-my-ai-agent-rexa-4dbh</link>
      <guid>https://dev.to/itssubhamoy/how-i-implemented-memory-in-my-ai-agent-rexa-4dbh</guid>
      <description>&lt;h2&gt;
  
  
  How I Built Memory for REXA Using PostgreSQL and pgvector
&lt;/h2&gt;

&lt;p&gt;One thing I wanted REXA to eventually have was &lt;strong&gt;long-term memory&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The idea is simple: when I explicitly tell REXA something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“Remember that I prefer PostgreSQL for my backend projects.”&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;REXA should be able to save that information so it can be used later.&lt;/p&gt;

&lt;p&gt;The important distinction is that &lt;strong&gt;REXA does not currently retrieve these memories yet&lt;/strong&gt;. Today, the implemented part is the &lt;strong&gt;memory-saving pipeline&lt;/strong&gt;. Retrieval is the next part I plan to build.&lt;/p&gt;

&lt;p&gt;I also didn't put the memory database directly inside the REXA CLI.&lt;/p&gt;

&lt;p&gt;Instead, I built the memory infrastructure behind the &lt;strong&gt;REXA website backend&lt;/strong&gt; and let the CLI communicate with it through an authenticated HTTP API.&lt;/p&gt;

&lt;p&gt;The architecture looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REXA CLI
   │
   │ POST + Bearer Token
   │ { "text": "..." }
   ▼
REXA Website Backend
   │
   ├── Verify Token
   ├── Identify User
   ├── Process Text
   ├── Generate Embeddings
   └── Store Memory
   │
   ▼
PostgreSQL + pgvector
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The CLI Does Not Silently Remember Everything
&lt;/h2&gt;

&lt;p&gt;One important design decision is that REXA does &lt;strong&gt;not&lt;/strong&gt; automatically save every preference or every piece of conversation.&lt;/p&gt;

&lt;p&gt;Instead, the model uses a tool called:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;When the user explicitly asks REXA to remember something, the model calls this tool.&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;User:
Remember that I use Bun for my backend projects.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;REXA can decide that the appropriate action is 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;save_memory(...)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So memory creation is currently &lt;strong&gt;explicit&lt;/strong&gt;, rather than REXA silently storing everything the user says.&lt;/p&gt;




&lt;h2&gt;
  
  
  1. REXA Calls &lt;code&gt;save_memory&lt;/code&gt;
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;save_memory&lt;/code&gt; tool receives the text that the user wants to store.&lt;/p&gt;

&lt;p&gt;Before sending it to the backend, the CLI performs some basic validation.&lt;/p&gt;

&lt;p&gt;The CLI:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;trims the text&lt;/li&gt;
&lt;li&gt;rejects empty input&lt;/li&gt;
&lt;li&gt;limits the text to &lt;strong&gt;8192 characters&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means extremely large documents may never leave the CLI in the first place.&lt;/p&gt;

&lt;p&gt;For normal memory entries, however, the text can then be sent to the backend.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. The CLI Sends an Authenticated HTTP Request
&lt;/h2&gt;

&lt;p&gt;The REXA CLI does not directly access PostgreSQL or pgvector.&lt;/p&gt;

&lt;p&gt;Instead, it sends a &lt;code&gt;POST&lt;/code&gt; request to the REXA backend:&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 https://rexa-server.onrender.com/api/cli/memory 
Authorization: Bearer &amp;lt;token&amp;gt; 
Content-Type: application/json 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The request body contains only the memory text:&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;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"I prefer PostgreSQL for my backend projects."&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;Notice that there is &lt;strong&gt;no &lt;code&gt;userId&lt;/code&gt; in the request body&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The identity of the user comes from the authentication token.&lt;/p&gt;




&lt;h2&gt;
  
  
  3. Where Does the Token Come From?
&lt;/h2&gt;

&lt;p&gt;The token comes from the REXA CLI login flow.&lt;/p&gt;

&lt;p&gt;The CLI first authenticates through the REXA backend using:&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 /api/cli/verify 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The same Bearer-token mechanism is then used when making authenticated CLI requests.&lt;/p&gt;

&lt;p&gt;This means the CLI doesn't simply tell the backend:&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;"userId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"text"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;Instead, it says, effectively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Here is my authentication token. 
Here is the memory I want to save. 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The backend is responsible for determining who that token belongs to.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. The Backend Verifies the Token
&lt;/h2&gt;

&lt;p&gt;When the memory request reaches:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/api/cli/memory 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the backend first checks the Bearer token.&lt;/p&gt;

&lt;p&gt;If the token is missing, invalid, or expired, the request is rejected.&lt;/p&gt;

&lt;p&gt;The CLI can surface these authentication failures and provide a hint to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;rexa login 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the authentication layer separate from the actual memory-processing logic.&lt;/p&gt;




&lt;h2&gt;
  
  
  5. The Backend Identifies the User
&lt;/h2&gt;

&lt;p&gt;After successful token verification, the backend knows which authenticated user is making the request.&lt;/p&gt;

&lt;p&gt;This is important because memory is &lt;strong&gt;per user&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The CLI doesn't provide the user identity manually.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bearer Token 
      ↓ 
Token Verification 
      ↓ 
Authenticated User 
      ↓ 
Memory belongs to that user 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This prevents the client from simply claiming that a memory belongs to some other user.&lt;/p&gt;




&lt;h2&gt;
  
  
  6. The Backend Processes the Memory
&lt;/h2&gt;

&lt;p&gt;Once authentication succeeds, the backend receives the text.&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;"I prefer PostgreSQL for my backend projects." 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;From here, the rest of the pipeline happens on the backend.&lt;/p&gt;

&lt;p&gt;This is where the database and embedding infrastructure come into play.&lt;/p&gt;

&lt;p&gt;The CLI doesn't need to know how the backend implements this processing.&lt;/p&gt;

&lt;p&gt;Conceptually, the pipeline is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Text 
 ↓ 
Chunking 
 ↓ 
Batch Creation 
 ↓ 
Embedding Generation 
 ↓ 
Vector 
 ↓ 
PostgreSQL + pgvector 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These are backend responsibilities.&lt;/p&gt;




&lt;h2&gt;
  
  
  7. Chunking
&lt;/h2&gt;

&lt;p&gt;The backend can split larger pieces of text into smaller chunks.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Large Text 
   │ 
   ├── Chunk 1 
   ├── Chunk 2 
   ├── Chunk 3 
   └── ... 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a tiny memory 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;"I prefer PostgreSQL." 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;there may not be much to split.&lt;/p&gt;

&lt;p&gt;But chunking becomes useful as the amount of stored information grows.&lt;/p&gt;




&lt;h2&gt;
  
  
  8. Creating Batches
&lt;/h2&gt;

&lt;p&gt;After chunking, the backend can group chunks into batches for embedding.&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;Chunks 
   │ 
   ├── Batch 1 
   │     ├── Chunk 1 
   │     ├── Chunk 2 
   │     └── Chunk 3 
   │ 
   └── Batch 2 
         ├── Chunk 4 
         ├── Chunk 5 
         └── Chunk 6 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These batches are then passed to the embedding stage.&lt;/p&gt;




&lt;h2&gt;
  
  
  9. Turning Text into Embeddings
&lt;/h2&gt;

&lt;p&gt;The text is converted into a numerical vector using an embedding model.&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;"I prefer PostgreSQL for my backend projects." 
                    │ 
                    ▼ 
             Embedding Model 
                    │ 
                    ▼ 
      [0.12, -0.38, 0.74, ...] 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The resulting vector represents the semantic information contained in the text.&lt;/p&gt;

&lt;p&gt;This is what makes vector-based memory possible.&lt;/p&gt;

&lt;p&gt;Instead of treating a memory as only a string of characters, the backend also stores a mathematical representation of its meaning.&lt;/p&gt;




&lt;h2&gt;
  
  
  10. Storing the Memory in PostgreSQL
&lt;/h2&gt;

&lt;p&gt;The generated vector is stored using &lt;strong&gt;pgvector&lt;/strong&gt; alongside the memory data.&lt;/p&gt;

&lt;p&gt;The database layer uses:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;PostgreSQL 
   + 
pgvector 
   + 
Prisma 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A simplified representation might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Memory 
───────────────────────────── 
user_id 
text 
embedding 
created_at 
... 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The exact schema can evolve, but the important part is that the memory is associated with the authenticated user and has a vector representation that can later be used for semantic retrieval.&lt;/p&gt;




&lt;h2&gt;
  
  
  11. The Backend Sends a Response
&lt;/h2&gt;

&lt;p&gt;Once the memory has been successfully processed and stored, the API returns a success response.&lt;/p&gt;

&lt;p&gt;The actual response from the controller is:&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;"success"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; 
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Data saved in memory"&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 CLI can then use that result to tell the user that the memory was saved successfully.&lt;/p&gt;

&lt;p&gt;So the complete flow is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 
 │ 
 │ "Remember this..." 
 ▼ 
REXA model 
 │ 
 │ calls save_memory 
 ▼ 
REXA CLI 
 │ 
 │ validate + trim text 
 │ 
 │ POST /api/cli/memory 
 │ Authorization: Bearer &amp;lt;token&amp;gt; 
 │ { "text": "..." } 
 ▼ 
REXA Backend 
 │ 
 │ verify token 
 │ identify user 
 │ 
 │ process memory 
 │ ├── chunk 
 │ ├── batch 
 │ ├── embed 
 │ └── store vector 
 ▼ 
PostgreSQL + pgvector 
 │ 
 │ success 
 ▼ 
REXA Backend 
 │ 
 │ { "success": true, 
 │   "message": "Data saved in memory" } 
 ▼ 
REXA CLI 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Why I Designed It This Way
&lt;/h2&gt;

&lt;p&gt;The main architectural decision was to keep &lt;strong&gt;REXA itself separate from the memory infrastructure&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The CLI is responsible for interacting with the agent and invoking &lt;code&gt;save_memory&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The backend handles authentication and memory processing.&lt;/p&gt;

&lt;p&gt;PostgreSQL and pgvector provide the persistent storage and vector representation.&lt;/p&gt;

&lt;p&gt;So the responsibilities are roughly separated like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REXA CLI 
→ Agent interaction + save_memory 

Backend 
→ Authentication + memory processing 

PostgreSQL + pgvector 
→ Persistent memory storage 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This also means the CLI doesn't need database credentials or direct database access.&lt;/p&gt;

&lt;p&gt;It only needs an authenticated API connection.&lt;/p&gt;

&lt;h2&gt;
  
  
  What REXA Has Today vs. What's Next
&lt;/h2&gt;

&lt;p&gt;At the moment, the implemented functionality is the &lt;strong&gt;save side&lt;/strong&gt; of memory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 
  ↓ 
save_memory 
  ↓ 
Authenticated API 
  ↓ 
Embedding 
  ↓ 
Vector storage 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The retrieval side is not implemented in the CLI yet.&lt;/p&gt;

&lt;p&gt;The next step is to build the other half:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Current: 

SAVE 
User 
 ↓ 
save_memory 
 ↓ 
Backend 
 ↓ 
Vector Database 


Future: 

RECALL 
Current Task 
 ↓ 
Memory Search 
 ↓ 
Similarity / Relevance 
 ↓ 
Relevant Memories 
 ↓ 
REXA 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is where things become much more interesting.&lt;/p&gt;

&lt;p&gt;The goal isn't simply to give REXA a database full of memories.&lt;/p&gt;

&lt;p&gt;The real goal is to build a system where REXA can eventually &lt;strong&gt;find the right memory when it is actually useful&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;And that's the part I'm building next.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>agentskills</category>
      <category>buildinpublic</category>
    </item>
    <item>
      <title>Why LLMs Should Never Touch Money Directly: Building an AI Payment Recovery Agent Solo</title>
      <dc:creator>Subhamoy Datta</dc:creator>
      <pubDate>Sat, 05 Sep 2026 17:33:03 +0000</pubDate>
      <link>https://dev.to/itssubhamoy/why-llms-should-never-touch-money-directly-building-an-ai-payment-recovery-agent-solo-493o</link>
      <guid>https://dev.to/itssubhamoy/why-llms-should-never-touch-money-directly-building-an-ai-payment-recovery-agent-solo-493o</guid>
      <description>&lt;p&gt;&lt;em&gt;How I built REVA for Track 3 of the Razorpay AI Buildathon 2026—and why deterministic guardrails matter more than AI autonomy when money is involved.&lt;/em&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  The Problem I Wanted to Solve
&lt;/h2&gt;

&lt;p&gt;Building for &lt;strong&gt;Track 3 of the Razorpay AI Buildathon 2026&lt;/strong&gt; as a solo developer came with one obvious challenge:&lt;/p&gt;

&lt;p&gt;There were a lot of talented engineers building impressive things.&lt;/p&gt;

&lt;p&gt;I didn't want to build another chatbot with an LLM sitting on top of an API.&lt;/p&gt;

&lt;p&gt;I wanted to build something where AI had to make &lt;strong&gt;real decisions&lt;/strong&gt;, while still operating within the constraints of a financial system.&lt;/p&gt;

&lt;p&gt;That led me to a problem I found particularly interesting:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What should happen after a payment fails?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A failed payment doesn't always mean lost revenue.&lt;/p&gt;

&lt;p&gt;Sometimes it's a temporary bank issue. Sometimes the card is expired. Sometimes the customer needs another payment method. And sometimes the payment may have actually succeeded even though the original request didn't return a definitive response.&lt;/p&gt;

&lt;p&gt;The difficult part isn't simply retrying.&lt;/p&gt;

&lt;p&gt;The difficult part is deciding &lt;strong&gt;when to retry, when not to retry, and when to involve a human—without accidentally charging the customer twice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That's what led me to build &lt;strong&gt;REVA — Razorpay Revenue Recovery Agent&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  1. The Problem: A Failed Payment Isn't Always Lost Revenue
&lt;/h1&gt;

&lt;p&gt;Payment failures can leave merchants with potentially recoverable revenue.&lt;/p&gt;

&lt;p&gt;The obvious solution seems simple:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retry the payment.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;But blindly retrying every failed transaction creates another set of problems.&lt;/p&gt;

&lt;p&gt;A recovery system needs to understand &lt;em&gt;why&lt;/em&gt; the payment failed before deciding what to do next.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;A temporary bank failure might justify a retry after a delay.&lt;/li&gt;
&lt;li&gt;An expired card should not be retried.&lt;/li&gt;
&lt;li&gt;A high-value order might deserve human intervention.&lt;/li&gt;
&lt;li&gt;A payment with uncertain settlement status should not be blindly retried.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Most basic recovery systems approach this in one of two ways.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blind Retries
&lt;/h3&gt;

&lt;p&gt;Retry failed payments according to a fixed schedule.&lt;/p&gt;

&lt;p&gt;The system doesn't really understand the failure. It simply assumes that trying again is better than doing nothing.&lt;/p&gt;

&lt;p&gt;That can lead to unnecessary retries and, more importantly, duplicate-charge risks when payment state is uncertain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Static Rules
&lt;/h3&gt;

&lt;p&gt;Build a large collection of &lt;code&gt;if/else&lt;/code&gt; conditions.&lt;/p&gt;

&lt;p&gt;This is more predictable, but eventually becomes difficult to maintain and doesn't handle contextual decisions particularly well.&lt;/p&gt;

&lt;p&gt;I wanted something in between.&lt;/p&gt;

&lt;p&gt;An agent that could &lt;strong&gt;reason about the situation&lt;/strong&gt;, while a deterministic system made sure that the reasoning could never violate critical financial policies.&lt;/p&gt;




&lt;h1&gt;
  
  
  2. The Realization: AI Shouldn't Touch Money Directly
&lt;/h1&gt;

&lt;p&gt;My initial idea was straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Payment fails
      |
      v
Send error to LLM
      |
      v
LLM decides what to do
      |
      v
LLM retries payment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It sounded reasonable.&lt;/p&gt;

&lt;p&gt;Then I started thinking about failure scenarios.&lt;/p&gt;

&lt;p&gt;What happens if the model incorrectly interprets a payment failure?&lt;/p&gt;

&lt;p&gt;What if it decides to retry an expired card?&lt;/p&gt;

&lt;p&gt;What if the payment actually succeeded, but the response was delayed because of a network issue?&lt;/p&gt;

&lt;p&gt;What if the model decides to retry the same transaction twice?&lt;/p&gt;

&lt;p&gt;That's when the core design principle became clear:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;LLMs are probabilistic. Financial invariants cannot be.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A language model can produce a reasonable decision most of the time.&lt;/p&gt;

&lt;p&gt;A payment system cannot accept "most of the time."&lt;/p&gt;

&lt;p&gt;A single incorrect action can potentially result in a duplicate charge, an invalid retry, or a loss of customer trust.&lt;/p&gt;

&lt;p&gt;So instead of giving the AI direct access to payment execution, I separated &lt;strong&gt;reasoning from execution&lt;/strong&gt;.&lt;/p&gt;




&lt;h1&gt;
  
  
  3. The Brain-Gatekeeper Architecture
&lt;/h1&gt;

&lt;p&gt;The architecture became:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    Failed Payment
                          |
                          v
              +------------------------+
              |       THE BRAIN        |
              |       Gemini AI        |
              |                        |
              | Diagnose failure       |
              | Analyze context        |
              | Propose recovery plan  |
              +-----------+------------+
                          |
                   Proposed Action
                          |
                          v
              +------------------------+
              |     THE GATEKEEPER     |
              |     PolicyEngine       |
              |                        |
              | Idempotency checks     |
              | Retry limits           |
              | Card validity checks   |
              | Risk / LTV policies    |
              +-----------+------------+
                          |
                    Approved Action
                          |
                          v
              +------------------------+
              |    PAYMENT EXECUTOR    |
              |      Razorpay API      |
              +------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The separation is intentional.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Brain
&lt;/h2&gt;

&lt;p&gt;Gemini receives relevant transaction context, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Payment failure information&lt;/li&gt;
&lt;li&gt;Failure codes&lt;/li&gt;
&lt;li&gt;Customer history&lt;/li&gt;
&lt;li&gt;Transaction value&lt;/li&gt;
&lt;li&gt;Previous recovery attempts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It then proposes a recovery strategy.&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;Failure: Temporary bank failure
Attempts: 1
Order value: ₹4,999

Proposed action:
Retry after backoff
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The model is responsible for &lt;strong&gt;reasoning about context&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;But its output is only a proposal.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Gatekeeper
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;PolicyEngine&lt;/code&gt; is deterministic TypeScript code.&lt;/p&gt;

&lt;p&gt;It doesn't care how convincing the AI's reasoning sounds.&lt;/p&gt;

&lt;p&gt;It checks whether the proposed action is actually allowed.&lt;/p&gt;

&lt;p&gt;Here's what an actual REVA transaction decision looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;──────────────────────────────────────────────────────────────────────────────
  TRANSACTION BREAKDOWN:
  ▸ [txn_10005]
    • Diagnosis:     Payment failed: expired_card
    • Strategy:      REQUEST_CUSTOMER_ACTION (Risk: MEDIUM)
    • Policy Guard:  APPROVED (Deterministic invariant check)
    • Settlement:    PENDING_WEBHOOK (₹0 claimed)
──────────────────────────────────────────────────────────────────────────────
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where the architecture becomes concrete.&lt;/p&gt;

&lt;p&gt;The AI identifies the failure as an &lt;code&gt;expired_card&lt;/code&gt; scenario and recommends &lt;code&gt;REQUEST_CUSTOMER_ACTION&lt;/code&gt; instead of blindly retrying the payment.&lt;/p&gt;

&lt;p&gt;The Gatekeeper then independently evaluates that proposed action against deterministic policies and approves it.&lt;/p&gt;

&lt;p&gt;Most importantly, the transaction remains in &lt;code&gt;PENDING_WEBHOOK&lt;/code&gt;, so &lt;strong&gt;₹0 is counted as recovered&lt;/strong&gt; until settlement is actually verified.&lt;/p&gt;

&lt;p&gt;This is the Brain-Gatekeeper principle in practice:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The AI reasons. The policy engine verifies. The payment system executes.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If any critical invariant fails:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         |
         v

       BLOCKED
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;The AI can propose an action, but it cannot override the Gatekeeper.&lt;/p&gt;




&lt;h1&gt;
  
  
  4. Why This Architecture Matters
&lt;/h1&gt;

&lt;p&gt;This isn't simply about adding another validation layer.&lt;/p&gt;

&lt;p&gt;It's about separating two fundamentally different responsibilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  AI is good at:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Understanding unstructured information&lt;/li&gt;
&lt;li&gt;Reasoning over multiple signals&lt;/li&gt;
&lt;li&gt;Classifying failure scenarios&lt;/li&gt;
&lt;li&gt;Generating contextual recovery strategies&lt;/li&gt;
&lt;li&gt;Explaining why an action was proposed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Deterministic code is good at:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Enforcing hard constraints&lt;/li&gt;
&lt;li&gt;Checking idempotency&lt;/li&gt;
&lt;li&gt;Enforcing retry limits&lt;/li&gt;
&lt;li&gt;Validating state transitions&lt;/li&gt;
&lt;li&gt;Blocking unsafe actions&lt;/li&gt;
&lt;li&gt;Guaranteeing predictable behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Trying to make one system do both creates unnecessary risk.&lt;/p&gt;

&lt;p&gt;So REVA treats the LLM as a &lt;strong&gt;reasoning engine&lt;/strong&gt;, not as the final authority.&lt;/p&gt;




&lt;h1&gt;
  
  
  5. The Engineering Battles
&lt;/h1&gt;

&lt;p&gt;Building the architecture was only the beginning.&lt;/p&gt;

&lt;p&gt;The real work started when I had to make the system behave correctly under failure conditions.&lt;/p&gt;

&lt;p&gt;Building solo meant there was nobody to pass the hard bugs to.&lt;/p&gt;

&lt;p&gt;Three challenges stood out.&lt;/p&gt;




&lt;h2&gt;
  
  
  Challenge 1: Making the Audit Ledger Resumable
&lt;/h2&gt;

&lt;p&gt;Financial workflows need reliable audit trails.&lt;/p&gt;

&lt;p&gt;I implemented an append-only audit ledger using JSONL records with a &lt;strong&gt;SHA-256 parent-hash chain&lt;/strong&gt;.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Record 1
   |
   +-- hash₁
         |
         v
Record 2
   |
   +-- parentHash = hash₁
   +-- hash₂
         |
         v
Record 3
   |
   +-- parentHash = hash₂
   +-- hash₃
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every record references the hash of the previous record.&lt;/p&gt;

&lt;p&gt;That gives us a tamper-evident chain.&lt;/p&gt;

&lt;p&gt;But during the early runs, I ran into a subtle problem.&lt;/p&gt;

&lt;p&gt;Whenever a new process started appending to an existing audit file, the hash chain broke.&lt;/p&gt;

&lt;p&gt;The new &lt;code&gt;AuditLogger&lt;/code&gt; instance was resetting to the genesis hash instead of continuing from the previous record.&lt;/p&gt;

&lt;p&gt;That meant the next entry couldn't correctly reference the existing chain.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Fix
&lt;/h3&gt;

&lt;p&gt;I updated the &lt;code&gt;AuditLogger&lt;/code&gt; constructor to inspect the existing ledger.&lt;/p&gt;

&lt;p&gt;If the file already exists, it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reads the existing JSONL file.&lt;/li&gt;
&lt;li&gt;Locates the final JSON record.&lt;/li&gt;
&lt;li&gt;Extracts its &lt;code&gt;currentHash&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Uses that hash as the parent for the next record.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So the chain can resume correctly across process restarts.&lt;/p&gt;

&lt;p&gt;This taught me an important lesson:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cryptographic integrity isn't only about hashing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You also need reliable state recovery.&lt;/p&gt;




&lt;h1&gt;
  
  
  Challenge 2: Eliminating "Phantom Revenue"
&lt;/h1&gt;

&lt;p&gt;This became one of the most important design decisions in REVA.&lt;/p&gt;

&lt;p&gt;Many recovery systems are tempted to treat an API success response as recovered revenue.&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;API returns HTTP 200
        |
        v
₹5,000 recovered
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But that's not necessarily true.&lt;/p&gt;

&lt;p&gt;Payment state can change after the initial request.&lt;/p&gt;

&lt;p&gt;A transaction can still be pending, fail later, or require confirmation through a webhook.&lt;/p&gt;

&lt;p&gt;So I introduced a &lt;strong&gt;Zero-Assumption Settlement&lt;/strong&gt; state machine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RECOVERY_ACTION
       |
       v
PENDING_WEBHOOK
       |
       |  ₹0 claimed
       |
       v
Verified Razorpay Webhook
       |
       v
SETTLED
       |
       v
Revenue Counted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;An attempted recovery is not recovered revenue.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;When an action is executed, the transaction moves to:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;At this point:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Recovered Revenue = ₹0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Revenue is only counted after an inbound Razorpay webhook arrives and its &lt;strong&gt;HMAC-SHA256 signature&lt;/strong&gt; is successfully verified.&lt;/p&gt;

&lt;p&gt;Only then can the transaction move to the settlement state.&lt;/p&gt;

&lt;p&gt;This may make the benchmark look less impressive than simply counting API successes.&lt;/p&gt;

&lt;p&gt;But it makes the metric much more honest.&lt;/p&gt;




&lt;h1&gt;
  
  
  Challenge 3: Taming API Rate Limits
&lt;/h1&gt;

&lt;p&gt;There was another practical problem.&lt;/p&gt;

&lt;p&gt;I wanted to evaluate REVA against a meaningful number of payment scenarios.&lt;/p&gt;

&lt;p&gt;But making an external LLM request for every transaction quickly runs into API rate limits.&lt;/p&gt;

&lt;p&gt;So I designed REVA with two execution modes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interactive LLM Mode
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--mode&lt;/span&gt; llm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is designed for live operation and demonstrations.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Real LLM reasoning&lt;/li&gt;
&lt;li&gt;Contextual recovery decisions&lt;/li&gt;
&lt;li&gt;Explainable AI output&lt;/li&gt;
&lt;li&gt;Interactive transaction analysis&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Deterministic Simulation Mode
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nt"&gt;--mode&lt;/span&gt; deterministic
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is designed for large-scale evaluation.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Reproducible simulations&lt;/li&gt;
&lt;li&gt;Seeded transaction generation&lt;/li&gt;
&lt;li&gt;Large-scale benchmarking&lt;/li&gt;
&lt;li&gt;No dependency on external LLM calls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The benchmark uses a deterministic seed so the same scenarios can be reproduced.&lt;/p&gt;

&lt;p&gt;This distinction was important to me.&lt;/p&gt;

&lt;p&gt;I didn't want to claim that I had made 1,000 live LLM calls when I hadn't.&lt;/p&gt;

&lt;p&gt;The benchmark and the live AI mode are deliberately separated.&lt;/p&gt;




&lt;h1&gt;
  
  
  6. The Benchmark: 1,000 Failed Payment Scenarios
&lt;/h1&gt;

&lt;p&gt;At this point, I had the architecture.&lt;/p&gt;

&lt;p&gt;But I still needed to answer the most important question:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Does it actually work better?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So I evaluated REVA against an empirical benchmark of &lt;strong&gt;1,000 simulated failed-payment scenarios&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The scenarios were modeled across &lt;strong&gt;9 real-world Indian payment failure categories&lt;/strong&gt;, using:&lt;br&gt;
&lt;/p&gt;

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

&lt;/div&gt;



&lt;p&gt;Together, these scenarios represented approximately:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;₹24.85 Lakhs of at-risk revenue.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I compared three approaches:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A naive blind retry bot&lt;/li&gt;
&lt;li&gt;Static &lt;code&gt;if/else&lt;/code&gt; rules&lt;/li&gt;
&lt;li&gt;REVA's autonomous recovery agent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The results were:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Strategy&lt;/th&gt;
&lt;th&gt;Recovery Rate&lt;/th&gt;
&lt;th&gt;Duplicate Charge Warnings&lt;/th&gt;
&lt;th&gt;Human Escalations&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Naive Blind Retry Bot&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;27.4%&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Static If/Else Rules&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;41.2%&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;REVA&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;68.3%&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;14&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The difference was significant.&lt;/p&gt;

&lt;h3&gt;
  
  
  Blind Retry Bot
&lt;/h3&gt;

&lt;p&gt;The naive retry system recovered only:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;27.4%&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It also generated:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;19 duplicate-charge warnings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The system was essentially following one rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Payment failed → try again.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That isn't enough for a financial recovery system.&lt;/p&gt;




&lt;h3&gt;
  
  
  Static Rules
&lt;/h3&gt;

&lt;p&gt;The static rules improved recovery to:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;41.2%&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;And importantly:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;0 duplicate-charge warnings&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This showed that deterministic safety rules work.&lt;/p&gt;

&lt;p&gt;But they still lacked the contextual reasoning needed to choose better recovery strategies.&lt;/p&gt;




&lt;h3&gt;
  
  
  REVA
&lt;/h3&gt;

&lt;p&gt;REVA reached:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;68.3% recovery&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;with:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;0 duplicate-charge warnings&lt;/strong&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;14 intentional human escalations&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The recovery improvement was:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;+40.9 percentage points&lt;/strong&gt; over blind retries.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;+27.1 percentage points&lt;/strong&gt; over static rules.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the 14 human escalations weren't treated as failures.&lt;/p&gt;

&lt;p&gt;They were part of the design.&lt;/p&gt;

&lt;p&gt;For certain high-value or high-risk transactions, the safest action isn't another autonomous attempt.&lt;/p&gt;

&lt;p&gt;It's:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Stop and ask a human.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  7. Why the Benchmark Is Important
&lt;/h1&gt;

&lt;p&gt;The recovery percentage is obviously interesting.&lt;/p&gt;

&lt;p&gt;But I think the methodology is more important.&lt;/p&gt;

&lt;p&gt;It would have been easy to make the benchmark look better.&lt;/p&gt;

&lt;p&gt;For example, I could have counted an HTTP success as recovered revenue.&lt;/p&gt;

&lt;p&gt;I didn't.&lt;/p&gt;

&lt;p&gt;I could have mixed live LLM calls with deterministic simulation and presented the entire thing as one benchmark.&lt;/p&gt;

&lt;p&gt;I didn't.&lt;/p&gt;

&lt;p&gt;I could have ignored duplicate-charge risks because the recovery percentage looked good.&lt;/p&gt;

&lt;p&gt;I didn't.&lt;/p&gt;

&lt;p&gt;Instead, REVA uses explicit states and deterministic simulation so that the results are reproducible and the definition of "recovered revenue" is clear.&lt;/p&gt;

&lt;p&gt;That matters when the system you're evaluating is dealing with money.&lt;/p&gt;




&lt;h1&gt;
  
  
  8. What Building REVA Solo Taught Me
&lt;/h1&gt;

&lt;h2&gt;
  
  
  1. Guardrails Matter More Than Prompts
&lt;/h2&gt;

&lt;p&gt;It's easy to spend hours optimizing prompts.&lt;/p&gt;

&lt;p&gt;But in a financial agent, the more important question is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;What happens when the model is wrong?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The answer shouldn't be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Hopefully nothing."&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Deterministic code blocks the unsafe action.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The best prompt in the world can't guarantee that an LLM will never produce an incorrect output.&lt;/p&gt;

&lt;p&gt;A policy engine can guarantee that certain outputs will never be executed.&lt;/p&gt;

&lt;p&gt;That distinction matters.&lt;/p&gt;




&lt;h2&gt;
  
  
  2. Autonomy Doesn't Mean Unlimited Authority
&lt;/h2&gt;

&lt;p&gt;Before building REVA, I associated agentic AI with giving an agent more tools and more freedom.&lt;/p&gt;

&lt;p&gt;This project changed that perspective.&lt;/p&gt;

&lt;p&gt;A useful agent doesn't necessarily need unlimited authority.&lt;/p&gt;

&lt;p&gt;REVA can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Diagnose failures&lt;/li&gt;
&lt;li&gt;Reason about transaction context&lt;/li&gt;
&lt;li&gt;Recommend strategies&lt;/li&gt;
&lt;li&gt;Prioritize recovery actions&lt;/li&gt;
&lt;li&gt;Decide when human intervention may be appropriate&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it cannot simply override financial policies.&lt;/p&gt;

&lt;p&gt;That's a much more useful definition of autonomy for high-stakes systems:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;The agent can reason independently without being given unlimited execution authority.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  3. Honest Metrics Are More Valuable Than Impressive Metrics
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;PENDING_WEBHOOK&lt;/code&gt; state was probably one of the most important decisions in the project.&lt;/p&gt;

&lt;p&gt;It would have been much easier to claim revenue as soon as a recovery API returned successfully.&lt;/p&gt;

&lt;p&gt;But that would create a misleading benchmark.&lt;/p&gt;

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

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Action executed
      |
      v
PENDING_WEBHOOK
      |
      v
Verified settlement
      |
      v
Revenue counted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That makes the numbers more conservative.&lt;/p&gt;

&lt;p&gt;But it also makes them defensible.&lt;/p&gt;

&lt;p&gt;I'd rather have a smaller number that I can explain than a bigger number that depends on assumptions.&lt;/p&gt;




&lt;h2&gt;
  
  
  4. Building Solo Forces You to Understand the Whole System
&lt;/h2&gt;

&lt;p&gt;There was nobody else to hand the difficult parts to.&lt;/p&gt;

&lt;p&gt;I had to work through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Architecture&lt;/li&gt;
&lt;li&gt;TypeScript&lt;/li&gt;
&lt;li&gt;Payment workflows&lt;/li&gt;
&lt;li&gt;Agent reasoning&lt;/li&gt;
&lt;li&gt;Policy enforcement&lt;/li&gt;
&lt;li&gt;Security&lt;/li&gt;
&lt;li&gt;Audit logging&lt;/li&gt;
&lt;li&gt;State machines&lt;/li&gt;
&lt;li&gt;CLI design&lt;/li&gt;
&lt;li&gt;Testing&lt;/li&gt;
&lt;li&gt;Benchmarking&lt;/li&gt;
&lt;li&gt;API integration&lt;/li&gt;
&lt;li&gt;Failure handling&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It was exhausting.&lt;/p&gt;

&lt;p&gt;But it also meant that I couldn't hide behind abstractions.&lt;/p&gt;

&lt;p&gt;When something broke, I had to understand why.&lt;/p&gt;

&lt;p&gt;And that gave me a much deeper understanding of the system I was building.&lt;/p&gt;




&lt;h1&gt;
  
  
  9. Testing the System
&lt;/h1&gt;

&lt;p&gt;I also wanted the safety layer to be testable independently of the LLM.&lt;/p&gt;

&lt;p&gt;The integration suite currently has:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;17/17 passing tests on Bun.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This matters because the most important safety guarantees shouldn't depend on whether the LLM happens to produce the expected output during a test run.&lt;/p&gt;

&lt;p&gt;The deterministic components need deterministic tests.&lt;/p&gt;

&lt;p&gt;The goal isn't to test whether the model is always right.&lt;/p&gt;

&lt;p&gt;The goal is to test whether the system behaves safely &lt;strong&gt;even when the model isn't right&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;That's the boundary I wanted REVA to enforce.&lt;/p&gt;




&lt;h1&gt;
  
  
  10. The Final Architecture
&lt;/h1&gt;

&lt;p&gt;By the end, REVA became less about:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Put an LLM on payments."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And more about:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;"Build a safe boundary around an LLM that reasons about payments."&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The final flow looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;                    AI
                     |
                   Reason
                     |
                     v
              Proposed Action
                     |
                     v
          Deterministic Policies
                     |
              +------+------+
              |             |
           BLOCKED       APPROVED
                            |
                            v
                      Payment API
                            |
                            v
                         Webhook
                            |
                            v
                         SETTLED
                            |
                            v
                    Revenue Counted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The LLM doesn't get to decide whether money moves.&lt;/p&gt;

&lt;p&gt;It gets to &lt;strong&gt;suggest what should happen next&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The deterministic layer decides whether that suggestion is safe.&lt;/p&gt;

&lt;p&gt;And the settlement system determines whether the money was actually recovered.&lt;/p&gt;




&lt;h1&gt;
  
  
  11. The Bigger Lesson
&lt;/h1&gt;

&lt;p&gt;The most interesting thing I learned from this project wasn't a specific Gemini technique.&lt;/p&gt;

&lt;p&gt;It wasn't a particular prompt.&lt;/p&gt;

&lt;p&gt;It wasn't even the recovery rate.&lt;/p&gt;

&lt;p&gt;It was the realization that &lt;strong&gt;AI autonomy and system authority don't have to be the same thing.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;An AI agent can be highly autonomous in its reasoning while still operating inside strict boundaries.&lt;/p&gt;

&lt;p&gt;That gives us a useful design pattern for high-stakes AI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;LLM
 |
 | Reason
 v
Proposed Action
 |
 | Validate
 v
Deterministic Policy
 |
 +---- BLOCK ----&amp;gt; Stop
 |
 +---- APPROVE --&amp;gt; Execute
                       |
                       v
                   Verify State
                       |
                       v
                  Count Outcome
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This pattern can extend beyond payments.&lt;/p&gt;

&lt;p&gt;The same principle applies anywhere an AI system can make decisions with real-world consequences:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Financial operations&lt;/li&gt;
&lt;li&gt;Infrastructure changes&lt;/li&gt;
&lt;li&gt;Security systems&lt;/li&gt;
&lt;li&gt;Healthcare workflows&lt;/li&gt;
&lt;li&gt;Customer account actions&lt;/li&gt;
&lt;li&gt;Automated commerce&lt;/li&gt;
&lt;li&gt;Production deployments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The model can be the reasoning layer.&lt;/p&gt;

&lt;p&gt;But the system around it needs to control what that reasoning is allowed to do.&lt;/p&gt;




&lt;h1&gt;
  
  
  12. What's Next?
&lt;/h1&gt;

&lt;p&gt;REVA is currently a buildathon project, but there are several directions I'd like to explore further.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Failure Classification
&lt;/h3&gt;

&lt;p&gt;Use richer transaction and historical signals to distinguish between temporary, recoverable, and fundamentally unrecoverable failures.&lt;/p&gt;

&lt;h3&gt;
  
  
  Smarter Recovery Policies
&lt;/h3&gt;

&lt;p&gt;Instead of simply choosing between a small set of strategies, optimize recovery decisions based on historical outcomes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Better Risk Modeling
&lt;/h3&gt;

&lt;p&gt;Introduce stronger fraud and transaction-risk signals into the policy layer.&lt;/p&gt;

&lt;h3&gt;
  
  
  More Granular Human-in-the-Loop Decisions
&lt;/h3&gt;

&lt;p&gt;Instead of a simple escalation path, determine exactly when human intervention creates the most value.&lt;/p&gt;

&lt;h3&gt;
  
  
  Production-Grade Event Processing
&lt;/h3&gt;

&lt;p&gt;Move toward a more robust event-driven architecture for handling payment state changes and webhooks at scale.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deeper Observability
&lt;/h3&gt;

&lt;p&gt;Make every AI proposal, policy decision, state transition, and settlement event observable and explainable.&lt;/p&gt;

&lt;p&gt;The interesting problem isn't simply making the AI smarter.&lt;/p&gt;

&lt;p&gt;It's figuring out:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;How much authority should an AI agent have—and how can we safely increase that authority over time?&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h1&gt;
  
  
  13. Final Takeaway
&lt;/h1&gt;

&lt;p&gt;Building REVA changed the way I think about AI agents.&lt;/p&gt;

&lt;p&gt;I started with a simple idea:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Let an LLM recover failed payments."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I ended up with a very different architecture:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Let the LLM reason about recovery, but never let it bypass deterministic financial invariants.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

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

&lt;p&gt;The payment system executes.&lt;/p&gt;

&lt;p&gt;The webhook confirms.&lt;/p&gt;

&lt;p&gt;Only then do we count the money.&lt;/p&gt;

&lt;p&gt;And that's probably the biggest lesson I took away from building REVA:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;In high-stakes AI systems, the goal shouldn't be to make the model all-powerful.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The goal should be to make the model useful while making the consequences of being wrong controllable.&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Tech Stack
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;TypeScript&lt;/code&gt; · &lt;code&gt;Bun&lt;/code&gt; · &lt;code&gt;Docker&lt;/code&gt; · &lt;code&gt;Google Gemini&lt;/code&gt; · &lt;code&gt;Razorpay APIs&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;Built for &lt;strong&gt;Track 3 of the Razorpay AI Buildathon 2026&lt;/strong&gt;.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you're building AI agents for payments, finance, or other high-stakes domains, I'd love to hear how you're handling the boundary between model reasoning and deterministic execution.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>hackathon</category>
    </item>
  </channel>
</rss>
