<?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: shaik riyan shareef</title>
    <description>The latest articles on DEV Community by shaik riyan shareef (@riyanshareefshaik).</description>
    <link>https://dev.to/riyanshareefshaik</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%2F4064393%2F6a97d0b4-0ac6-40eb-b1b6-f4bc672aee64.jpg</url>
      <title>DEV Community: shaik riyan shareef</title>
      <link>https://dev.to/riyanshareefshaik</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/riyanshareefshaik"/>
    <language>en</language>
    <item>
      <title>Employers count on workers forgetting, so I used Hindsight</title>
      <dc:creator>shaik riyan shareef</dc:creator>
      <pubDate>Mon, 28 Sep 2026 17:00:47 +0000</pubDate>
      <link>https://dev.to/riyanshareefshaik/employers-count-on-workers-forgetting-so-i-used-hindsight-3e0p</link>
      <guid>https://dev.to/riyanshareefshaik/employers-count-on-workers-forgetting-so-i-used-hindsight-3e0p</guid>
      <description>&lt;p&gt;A mason in Hyderabad is promised ₹800 a day. Six days later he's handed ₹3,000 and told "the rest later". There's no contract, no payslip and no record, just his word against the contractor's. By the time he brings it up, he can't say exactly which day was agreed or how much was paid. Nobody has lied outright. Everybody has just &lt;em&gt;forgotten&lt;/em&gt;, and forgetting is cheaper for the person holding the money.&lt;/p&gt;

&lt;p&gt;I built HakDaar (Hindi for "the one who is entitled") to take that advantage away. It's a chat app where daily-wage and migrant workers tell an agent, in Telugu, Hindi or English, by text or voice, what was promised, what they worked and what they were paid. The agent remembers all of it, keeps an exact ledger, and says what is still owed. The most interesting part to build was not the chat. It was deciding &lt;strong&gt;what the agent should remember, where, and what it must never be allowed to calculate.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does and how it hangs together
&lt;/h2&gt;

&lt;p&gt;A worker types or says something like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Rakesh promised me 800 rupees per day for the building work."&lt;br&gt;
"I worked 6 days for him."&lt;br&gt;
"He paid me only 3000 and said the rest later."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The app shows &lt;strong&gt;Earned ₹4,800 · Paid ₹3,000 · Owed ₹1,800&lt;/strong&gt; and replies in the worker's language. When they come back a week later, the agent opens with &lt;em&gt;"Last time, Rakesh still owed you ₹1,800. Did he pay?"&lt;/em&gt;&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%2F4qmjgpo3tgbp85qyks41.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%2F4qmjgpo3tgbp85qyks41.png" alt="HakDaar wallet and wage ledger" width="700" height="468"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The stack is deliberately boring:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;React&lt;/strong&gt; frontend (plus a thin Android wrapper), &lt;strong&gt;FastAPI&lt;/strong&gt; backend, &lt;strong&gt;SQLite&lt;/strong&gt; for the ledger.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Groq&lt;/strong&gt; for language: &lt;code&gt;gpt-oss-120b&lt;/code&gt; extracts facts and writes replies; Whisper handles voice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight agent memory&lt;/a&gt;&lt;/strong&gt;, self-hosted in Docker, for everything the agent needs to &lt;em&gt;remember&lt;/em&gt; rather than &lt;em&gt;count&lt;/em&gt;.&lt;/li&gt;
&lt;/ul&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%2Fdj7azvgcoquc20hyuvp8.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%2Fdj7azvgcoquc20hyuvp8.png" alt="Where Hindsight sits in the stack" width="799" height="434"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every message goes through the same pipeline: extract facts → store them in the ledger → compute exact totals → retain the turn in memory and recall what's relevant → write the reply from the exact numbers.&lt;/p&gt;

&lt;h2&gt;
  
  
  The core decision: memory is not the ledger
&lt;/h2&gt;

&lt;p&gt;My first instinct was to let the agent's memory &lt;em&gt;be&lt;/em&gt; the record. Store everything, recall it, let the model answer "how much am I owed?" That failed in the most dangerous way possible.&lt;/p&gt;

&lt;p&gt;Early on, a worker told the agent about 5 days of work and, in a separate message, a rate of 10,000. The ledger hadn't recorded the rate correctly (more on that below), but the model had both facts in its context and confidently replied: &lt;em&gt;"You worked 5 days at ₹10,000 each. That means ₹50,000 is still owed."&lt;/em&gt; The ledger said ₹0. The model did multiplication it had no business doing, on facts nobody had confirmed.&lt;/p&gt;

&lt;p&gt;That's when the architecture split into two stores with two different jobs:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;The ledger (SQLite) owns every rupee.&lt;/strong&gt; Structured events (promise, work_day, payment), summed with Python &lt;code&gt;Decimal&lt;/code&gt;. Only this produces numbers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; owns the story.&lt;/strong&gt; Who said what, when, what the employer promised, what excuse they gave, what happened last time. Context the agent needs to be useful and personal, but never the source of an amount.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The ledger math is small on purpose:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;fixed&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="c1"&gt;# Nothing agreed yet (no daily rate, no fixed total): can't compute honestly.
&lt;/span&gt;    &lt;span class="n"&gt;earned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;owed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;unknown_rate&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;earned_d&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;days&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;rate&lt;/span&gt; &lt;span class="ow"&gt;is&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="bp"&gt;None&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;fixed&lt;/span&gt;
    &lt;span class="n"&gt;earned&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rupees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;earned_d&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;owed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rupees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;earned_d&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;paid&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;_rupees&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;paid&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;earned_d&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Decimal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)))&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;owed&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;owed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="nf"&gt;else &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;advance&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;advance&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;settled&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the reply has a guard: any money-sized number in the model's answer that doesn't appear in the ledger, the facts noted this turn, or the worker's own words, triggers a rewrite. If the rewrite still invents a number, the agent falls back to a plain reply built from the ledger.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;invented_amounts&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;str&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
    &lt;span class="sh"&gt;"""&lt;/span&gt;&lt;span class="s"&gt;Money-sized numbers (&amp;gt;= 100) in the reply that appear nowhere in what we gave the model.&lt;/span&gt;&lt;span class="sh"&gt;"""&lt;/span&gt;
    &lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;set&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;src&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;sources&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;allowed&lt;/span&gt; &lt;span class="o"&gt;|=&lt;/span&gt; &lt;span class="nf"&gt;numbers_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;src&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nf"&gt;numbers_in&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;reply&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;allowed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With that split, memory became something I could lean on heavily, because being wrong about a memory changes the &lt;em&gt;tone&lt;/em&gt; of a reply, never the &lt;em&gt;amount&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Hindsight is wired in
&lt;/h2&gt;

&lt;p&gt;Each worker gets a private memory bank (&lt;code&gt;worker-{id}&lt;/code&gt;). There is also one shared bank, &lt;code&gt;employer-reputation&lt;/code&gt;, that holds only anonymous, fact-derived reports such as &lt;em&gt;"A worker reported a short payment of ₹1,800 from Rakesh Builders."&lt;/em&gt; No names, no phone numbers.&lt;/p&gt;

&lt;p&gt;On every message, the agent &lt;strong&gt;recalls&lt;/strong&gt; from both banks and &lt;strong&gt;retains&lt;/strong&gt; the new turn, all concurrently:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;_retain_all&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;turn_content&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat message from worker&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                        &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;worker_id&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;worker_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;chat&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;employer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;reports&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;retain&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;REPUTATION_BANK&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;summary&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;anonymous wage report (&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;)&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                            &lt;span class="n"&gt;timestamp&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;employer&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;employer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;kind&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="p"&gt;})&lt;/span&gt;

&lt;span class="c1"&gt;# recall first (so we don't see our own un-processed message), retain in parallel.
&lt;/span&gt;&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;asyncio&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gather&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;memory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;recall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;bank&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recall_query&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nf"&gt;_recall_rep&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nf"&gt;_retain_all&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                               &lt;span class="n"&gt;return_exceptions&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Three details made this work well in practice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Retain is asynchronous.&lt;/strong&gt; I call &lt;code&gt;aretain&lt;/code&gt; with &lt;code&gt;retain_async=True&lt;/code&gt;, so Hindsight extracts facts, entities and time in the background and the chat never waits for it. The wallet updates as soon as the ledger is saved; memory catches up a moment later.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The recall query is enriched with the employers in focus.&lt;/strong&gt; A bare "he paid me 3000" becomes "he paid me 3000 (employers: Rakesh Builders)", which pulls back the right history.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory failures degrade, they don't break.&lt;/strong&gt; &lt;code&gt;return_exceptions=True&lt;/code&gt; means if Hindsight is down, the wages are still recorded and the worker sees "memory is offline" instead of an error.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the shared bank I use &lt;strong&gt;reflect&lt;/strong&gt; rather than raw recall. When a worker taps &lt;em&gt;"What have workers reported?"&lt;/em&gt;, Hindsight reasons over every anonymous report about that employer and returns two or three sentences. I explicitly ask it to state counts, mention anyone who was paid in full, and never call the employer dishonest. &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;Agent memory&lt;/a&gt; that summarizes many people's experiences needs to be fair by construction, not just accurate.&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%2Fqd7osxf7qqcor3ht37hf.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%2Fqd7osxf7qqcor3ht37hf.png" alt="The anonymous warning a second worker sees about the same employer" width="800" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What it looks like, before and after
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Without memory&lt;/strong&gt; (what a stateless chat model does in a new session):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Worker:&lt;/strong&gt; Did Rakesh pay me what he owes?&lt;br&gt;
&lt;strong&gt;Agent:&lt;/strong&gt; I don't have information about Rakesh or your payments. Could you tell me more?&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;With Hindsight and the ledger&lt;/strong&gt; (a week later, same worker):&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Agent:&lt;/strong&gt; Last time you told me Rakesh still owes you ₹1,800. Did he pay you?&lt;br&gt;
&lt;strong&gt;Worker:&lt;/strong&gt; He gave 1000 today.&lt;br&gt;
&lt;strong&gt;Agent:&lt;/strong&gt; Noted: ₹1,000 received from Rakesh Builders. He still owes you ₹800. Ask him politely for&lt;br&gt;
the rest, with the dates you worked.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;And across workers: when a second worker says &lt;em&gt;"Rakesh has offered me work at 700 a day"&lt;/em&gt;, they see &lt;em&gt;"1 other worker reported short payment from Rakesh Builders. This is a single, unverified report, so check with others before deciding."&lt;/em&gt; It only becomes a real warning when two or more different workers report the same employer. One angry (or fake) account can't brand anybody.&lt;/p&gt;

&lt;h2&gt;
  
  
  The messy parts nobody warns you about
&lt;/h2&gt;

&lt;p&gt;Real workers don't talk in clean JSON-shaped sentences, and most of my debugging time went here:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bare answers.&lt;/strong&gt; HakDaar asks "What daily rate did Rakesh promise?" and the worker replies "10000". On its own, that message has no type and no employer. I now read short answers against the question the agent just asked: a bare number after a rate question is a promise.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Facts before names.&lt;/strong&gt; "I worked 5 days" often comes before the employer is mentioned. Instead of dropping it, the fact is kept under "Employer (name not given)" and moved onto the real employer the moment the worker names one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Models returning nulls.&lt;/strong&gt; Fields like &lt;code&gt;"is_total": null&lt;/code&gt; made strict validation silently drop real events, which is exactly how the ₹50,000 reply above happened. I now normalize model output before validating it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Overpayment.&lt;/strong&gt; Being paid ₹1,800 for ₹1,000 of work used to read as "fully paid". Now the wallet says &lt;em&gt;Paid extra ₹800&lt;/em&gt;, and the agent says it too.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Lessons I'd reuse
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Split what an agent remembers from what it computes.&lt;/strong&gt; Hindsight is excellent at holding a messy, evolving story. A ledger is excellent at arithmetic. Don't ask either to do the other's job.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Recall before you retain.&lt;/strong&gt; Running recall concurrently with retain, rather than after it, keeps the agent from "remembering" the message it is currently answering.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat shared memory as a publishing decision.&lt;/strong&gt; The moment one user's memory can affect another's, you need anonymity, thresholds and a fair summarizer. &lt;code&gt;reflect&lt;/code&gt; gave me the summarizer; the thresholds had to be my own code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Guard the output, not just the input.&lt;/strong&gt; Validating the model's JSON wasn't enough. Checking the final reply for numbers that exist nowhere in the ledger caught the failures that mattered most.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Design for the least literate user first.&lt;/strong&gt; Voice input, amounts read aloud as words in Telugu and Hindi ("one thousand eight hundred rupees", not "one-eight-zero-zero"), and big buttons made the product better for everyone, not just the users I designed them for.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If you're building anything where a user's history &lt;em&gt;is&lt;/em&gt; the evidence (wages, rent, loans, medical follow-ups), give the agent a real memory. Start with the &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight documentation&lt;/a&gt; and the &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;open-source Hindsight repository&lt;/a&gt;. Keep the numbers somewhere the model can't touch.&lt;/p&gt;

&lt;p&gt;HakDaar's code is on GitHub: &lt;a href="https://github.com/riyanshareefshaik/HakDaar" rel="noopener noreferrer"&gt;github.com/riyanshareefshaik/HakDaar&lt;/a&gt;.&lt;br&gt;
"Thanks to Code.in and the Hindsight team at Vectorize."&lt;/p&gt;

</description>
      <category>ai</category>
      <category>llm</category>
      <category>python</category>
      <category>agents</category>
    </item>
    <item>
      <title>"Yonaka — A Midnight Ramen Counter"</title>
      <dc:creator>shaik riyan shareef</dc:creator>
      <pubDate>Sat, 15 Aug 2026 06:09:27 +0000</pubDate>
      <link>https://dev.to/riyanshareefshaik/yonaka-a-midnight-ramen-counter-3nko</link>
      <guid>https://dev.to/riyanshareefshaik/yonaka-a-midnight-ramen-counter-3nko</guid>
      <description>&lt;h2&gt;
  
  
  What I Built
&lt;/h2&gt;

&lt;p&gt;Yonaka is a landing page for a midnight ramen counter — an imaginary 12-seat spot that opens after dark. The whole page is built around one idea: a fixed background video that scrubs frame-by-frame as you scroll, so a bowl of ramen assembles itself (empty bowl → noodles → broth → chashu → egg → finished bowl) in perfect sync with how far down the page you are — the video finishes exactly as you hit the bottom.&lt;/p&gt;

&lt;p&gt;Beyond the hero, it's got a build breakdown (the four steps that go into the bowl, in order), a photo gallery pulled from stills of the same footage, a four-item menu styled like a paper ticket, fictional reviews, and hours/location info. Built with vanilla HTML/CSS/JS — no frameworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo
&lt;/h2&gt;


&lt;div class="ltag-netlify"&gt;
  &lt;iframe src="https://yonakasramen.netlify.app/" title="Netlify embed"&gt;
  &lt;/iframe&gt;
&lt;/div&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%2Fi6xxffy50b40op5oys1g.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%2Fi6xxffy50b40op5oys1g.png" alt=" " width="800" height="496"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Journey
&lt;/h2&gt;

&lt;p&gt;The trickiest part was getting the scroll-scrubbing to feel smooth in both directions. My first pass used a source video with only a single keyframe, which meant seeking backward (scrolling up) had nowhere to go but back to frame zero — a jarring snap every time. Re-encoding with a keyframe every 6 frames fixed it completely, since the browser could now seek precisely to nearby frames instead of re-decoding from the start.&lt;/p&gt;

&lt;p&gt;I'm proud of how the whole page ties motion to intent instead of using motion for its own sake — every animation (the video scrub, the reveal-on-scroll steps, the header that only shows at the top) is driven by what the user is actually doing, not on a timer.&lt;/p&gt;

&lt;p&gt;Next, I'd like to add a lightweight "order" flow and experiment with WebCodecs for even smoother frame seeking on lower-end devices.&lt;/p&gt;

&lt;p&gt;can feel free to ask in comments ❤️&lt;/p&gt;

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