<?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: G haneesh Kumar</title>
    <description>The latest articles on DEV Community by G haneesh Kumar (@g_haneeshkumar_874892a2b).</description>
    <link>https://dev.to/g_haneeshkumar_874892a2b</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%2F4147660%2F977c40d4-74ba-41de-96b1-e74fd1cf45f7.jpg</url>
      <title>DEV Community: G haneesh Kumar</title>
      <link>https://dev.to/g_haneeshkumar_874892a2b</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/g_haneeshkumar_874892a2b"/>
    <language>en</language>
    <item>
      <title>Hindsight Memory Only Helped Once I Fixed Retrieval Scope</title>
      <dc:creator>G haneesh Kumar</dc:creator>
      <pubDate>Mon, 28 Sep 2026 17:16:49 +0000</pubDate>
      <link>https://dev.to/g_haneeshkumar_874892a2b/hindsight-memory-only-helped-once-i-fixed-retrieval-scope-1c33</link>
      <guid>https://dev.to/g_haneeshkumar_874892a2b/hindsight-memory-only-helped-once-i-fixed-retrieval-scope-1c33</guid>
      <description>&lt;p&gt;&lt;strong&gt;Hindsight Memory Only Helped Once I Fixed Retrieval Scope&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Building a deal-briefing agent on Hindsight retain/recall and Groq&lt;/p&gt;

&lt;p&gt;Two deals in my dataset, Crest Financial and BetaTech Solutions, both hit a pricing objection on an early call. BetaTech got a 22% discount; Crest's procurement team pushed for a multi-year one. Ask a memory store about "pricing objections" and both look relevant. Only one belongs in a Crest briefing. Teaching my Deal Intelligence Agent to tell them apart turned out to be the real project.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The problem&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The context already exists: call notes, objections, who was on the line. What's missing is a step that puts the right slice of that history in front of an LLM before the next call. I wanted an agent that retains every interaction and recalls only what matters to the question in front of it.&lt;/p&gt;

&lt;p&gt;I used Hindsight for memory, Groq (openai/gpt-oss-120b) for reasoning, and Streamlit for the interface. Storing notes was the easy part. I realized quickly that retrieval was where the intelligence lived: a store that returns Crest's history plus a lookalike deal's discount produces a confident, wrong briefing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it fits together&lt;/strong&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%2Foeitjqjzgw2lxw0wnws8.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%2Foeitjqjzgw2lxw0wnws8.png" alt=" " width="653" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 1: Notes are retained in Hindsight, relevant context is recalled, Groq turns it into a brief or insight, and each new call loops back into memory.&lt;/p&gt;

&lt;p&gt;The loop is: call notes → retain → recall → Groq → pre-call brief or pattern insight → new call logged → retain again. There is one memory bank (deals-demo-v2), and tags decide scope. The Hindsight docs cover the API; agent memory is the broader idea behind it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retain: what goes in&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Each call becomes one text memory plus tags. This is the call from the Log Deal form:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;hindsight.retain(bank_id=BANK, content=content,&lt;br&gt;
                 tags=[f"company:{company}", f"objection:{ss.get('log_obj')}"])&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;content packs company, deal size, stage, date, stakeholder, note, and objection into one string. The seed loader in rebuild_data.py also adds approach: tags and deal_id/stage metadata. The company: tag matters most, because it makes scoped retrieval possible later.&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%2Fkz69crclp08w9fot4t0h.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%2Fkz69crclp08w9fot4t0h.png" alt=" " width="800" height="386"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 2: Log Deal / Call. Company, size, stage, objection, stakeholder, and note are stored together in Hindsight, and the same form works for a brand-new company or another call on an existing deal.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recall: two scopes, one helper&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every read goes through one function. The important part:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;if tags:&lt;br&gt;
    kwargs["tags"] = tags&lt;br&gt;
    kwargs["tags_match"] = "all_strict"&lt;br&gt;
memories = hindsight.recall(**kwargs)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Company-specific. The pre-call brief passes the company tag, so recalled memories must carry it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;ctx = recall_context(f"{company} deal history, objections, stakeholders",&lt;br&gt;
                     tags=[f"company:{company}"])&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If nothing comes back, the app says "No memories found for this company yet" instead of letting the LLM improvise.&lt;/p&gt;

&lt;p&gt;Cross-deal. Pattern analysis drops the filter and widens the budget:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;python&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;ctx = recall_context("pricing objections, rep approach and deal outcomes across all deals",&lt;br&gt;
                     max_tokens=3500, budget="high")&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Same function, opposite intent. A brief needs precision inside one deal; a pattern needs breadth across many. The New Deal Simulator also recalls without tags, since a company with no history needs similar deals instead. Whatever comes back is placed in the prompt ("Deal history: …") ahead of the instruction to write a brief, and an expander shows the raw recalled text so I can see exactly what the model received.&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%2Fk4l0cglh5g3jcw7zu068.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%2Fk4l0cglh5g3jcw7zu068.png" alt=" " width="800" height="386"&gt;&lt;/a&gt;&lt;br&gt;
Figure 3: Pre-Call Brief. In this capture, Acme Manufacturing returned "No memories found for this company yet." The strict scope leaves the gap empty instead of filling it from other companies. I haven't diagnosed why this run was empty, which is exactly the kind of case a retrieval test should explain.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before and after&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Before&lt;/strong&gt;: Crest Financial is a $175,000 deal in negotiation with four calls between December and January: pricing first, then a security review, then procurement pushing a multi-year discount, then a follow-up with no decision. Preparing for the next call meant reopening those notes and rebuilding the story, ideally without importing BetaTech's.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;After&lt;/strong&gt;: The brief is generated from memories tagged company:Crest Financial. Any call I log afterward is retained under that tag, so the next brief includes it.&lt;/p&gt;

&lt;p&gt;The cross-deal side works the same way. In the New Deal Simulator I pasted a note: the CFO says the price is 20% over budget, a competitor is involved, and a decision is due by quarter-end.&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%2F95qrrosnwc4h6764893l.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%2F95qrrosnwc4h6764893l.png" alt=" " width="799" height="378"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 4: New Deal Simulator. A fresh call note is used as the recall query against past deals, and can then be saved back to memory.&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%2Ftxiux3s3jb3hiriffhi7.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%2Ftxiux3s3jb3hiriffhi7.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 5: The recommended next move, built from recalled past deals. It refers to a "Helix Robotics deal" as a past win, which is also the company name I typed into the form. I can't tell from this screenshot whether that is an earlier saved call or the model blurring things together, so the recalled-memory expander is where I'd check.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the synthetic numbers say, and don't&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Win-Rate tab is plain pandas over deals_data.json. No LLM and no Hindsight are involved. It compares how the pricing objection was handled with the deal outcome.&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%2F0nlkzkh61070mo6cd2cp.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%2F0nlkzkh61070mo6cd2cp.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 6: Win-Rate Data. In this capture, discount-only shows 0 of 10 won and ROI framing 11 of 11. That is a larger local dataset (the sidebar reported 36 seed deals) than the generator described below.&lt;/p&gt;

&lt;p&gt;The generator in the repo, rebuild_data.py, builds 36 synthetic deals: six ROI framing and six discount-only. ROI framing wins four of six; discount-only wins none. Two deals in each group are still in negotiation, and the tab counts those as not won.&lt;/p&gt;

&lt;p&gt;I need to be blunt about this: I chose those outcomes. A BATCHES list hardcodes each deal's final stage, and an LLM writes notes to match. The pattern is planted by construction. What it shows is that the pipeline can retrieve a pattern spread across deals. It says nothing about real sales, and it is not evidence that ROI framing causes wins.&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%2Ftlpqzjjks56iubd2s5g8.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%2Ftlpqzjjks56iubd2s5g8.png" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figure 7: Pattern Insight. The agent cites specific deals as won or lost. Dollar amounts render as math here because Streamlit parses $ pairs, a cosmetic quirk in the capture.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;State and reproducibility&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Persistent memory means state outlives the code. rebuild_data.py asks Groq for deals, writes deals_data.json, then retains every call with tags and metadata. It never clears the bank, so a clean slate means a new bank name. The generated notes also differ between runs; only the stage and approach design is fixed. And the deals_data.json committed in the repo is the larger set behind my screenshots, which the generator overwrites. Two versions of "the data" is precisely the reproducibility problem I'd warn others about.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What I learned&lt;/em&gt;&lt;/strong&gt;&lt;br&gt;
Memory is an application-design problem. Tags chosen at write time decide what can be retrieved at read time.&lt;br&gt;
Retrieval is part of the intelligence. The same LLM gives a different answer depending on what recall hands it.&lt;br&gt;
A briefing is not a summary. The prompt asks for objections, stakeholders, and one piece of advice for the next call, not a recap.&lt;br&gt;
Stateful systems need reproducible data. If I can't rebuild the memory, I can't trust a test against it.&lt;br&gt;
Small datasets need careful reading. Twelve planted deals test plumbing, not strategy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;What I'd test next&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The obvious gap is retrieval evaluation. For each company, does the recalled context contain only that company's tagged memories? If I inject a lookalike deal with a similar objection, does anything leak into the brief? Does cross-deal recall cover several distinct deals, not just one? Are irrelevant memories left out? Negative tests like these matter most, since a briefing that quietly borrows another deal's history looks perfectly plausible.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;Conclusion&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The agent retains notes, recalls scoped context, and turns it into briefings and pattern insights. It is a prototype on synthetic data, and I'd say so to anyone who asks. The main thing I'd carry into the next project is that memory earns its keep at retrieval time, not at storage time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Code&lt;/strong&gt;: &lt;a href="//github.com/ghaneeshkumar83-lab/deal-intelligence-agent"&gt;Click Here&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>agents</category>
      <category>opensource</category>
      <category>hindsight</category>
    </item>
  </channel>
</rss>
