<?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: Nagamuni</title>
    <description>The latest articles on DEV Community by Nagamuni (@nagamuni_13ab32c05fba42c3).</description>
    <link>https://dev.to/nagamuni_13ab32c05fba42c3</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%2F4149287%2F8fb9d8d1-371f-41ee-9eaf-38d3ba775423.jpg</url>
      <title>DEV Community: Nagamuni</title>
      <link>https://dev.to/nagamuni_13ab32c05fba42c3</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/nagamuni_13ab32c05fba42c3"/>
    <language>en</language>
    <item>
      <title>Hindsight Digital Intelligence</title>
      <dc:creator>Nagamuni</dc:creator>
      <pubDate>Tue, 29 Sep 2026 10:06:05 +0000</pubDate>
      <link>https://dev.to/nagamuni_13ab32c05fba42c3/hindsight-digital-intelligence-2a9k</link>
      <guid>https://dev.to/nagamuni_13ab32c05fba42c3/hindsight-digital-intelligence-2a9k</guid>
      <description>&lt;h1&gt;
  
  
  A Sales Playbook That Learns From Objections and Outcomes
&lt;/h1&gt;

&lt;p&gt;A sales briefing can be wrong while every sentence in it is individually true: the CFO’s objection from one account gets attached to another account, and a rep walks into the call with someone else’s pricing history. In this project, one field—&lt;code&gt;deal_id&lt;/code&gt;—is the difference between useful recall and a confident account mix-up.&lt;/p&gt;

&lt;h2&gt;
  
  
  What it does
&lt;/h2&gt;

&lt;p&gt;I built Deal Intelligence Agent as a FastAPI service with three useful API paths. &lt;code&gt;POST /deals/{deal_id}/log&lt;/code&gt; retains a call, email, or meeting note in Hindsight Cloud and appends a local copy. &lt;code&gt;GET /deals/{deal_id}/brief&lt;/code&gt; recalls one deal’s history and asks Groq’s &lt;code&gt;openai/gpt-oss-120b&lt;/code&gt; to produce a structured briefing. &lt;code&gt;GET /patterns&lt;/code&gt; performs a global recall and asks Groq to find one recurring objection-resolution pattern across deals. The web UI is vanilla HTML, CSS, and JavaScript; &lt;code&gt;deals.json&lt;/code&gt; supplies deal names and metadata for local inspection.&lt;/p&gt;

&lt;p&gt;The division of labor matters. Hindsight Cloud is the persistent memory engine, using retain, recall, and its TEMPR retrieval strategy. It is not the final answer generator. The application decides what scope to search, passes the retrieved text to Groq, and returns a response. That makes the application code—not an invisible prompt convention—the place where the most important boundary is expressed.&lt;/p&gt;

&lt;h2&gt;
  
  
  The design decision: learn only from the right outcome
&lt;/h2&gt;

&lt;p&gt;A single shared memory bank is convenient for cross-deal analysis, but dangerous for a deal briefing. The same bank can contain every account’s notes, so every stored item is tagged with its deal identifier. On retain, I put the identifier in three places: in the human-readable content prefix, in the Hindsight tags, and in metadata. Only the tags are used by this implementation to filter recall; the other two carry useful context and traceability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture in one pass
&lt;/h2&gt;

&lt;p&gt;The request path is intentionally boring: the browser calls FastAPI, FastAPI chooses the memory scope, Hindsight Cloud retains or recalls, and Groq turns recalled text into a briefing or playbook rule. The local JSON store only supplies deal metadata and an inspection-friendly copy of logs.&lt;br&gt;
&lt;/p&gt;

&lt;pre data-lang="mermaid"&gt;&lt;code&gt;flowchart TD
    UI["Web UI&amp;lt;br/&amp;gt;(dark mode, vanilla HTML/CSS/JS)"]
    API["FastAPI backend&amp;lt;br/&amp;gt;(app/main.py)"]
    H["Hindsight Cloud&amp;lt;br/&amp;gt;(retain / recall / TEMPR)"]
    B["deal-intel bank"]
    G["Groq&amp;lt;br/&amp;gt;(openai/gpt-oss-120b)"]
    J["deals.json&amp;lt;br/&amp;gt;(metadata and local log copy)"]
    UI --&amp;gt;|log, brief, patterns| API
    API --&amp;gt;|tagged retain / scoped recall| H
    H --&amp;gt; B
    API --&amp;gt;|recalled context| G
    API --&amp;gt; J
    G --&amp;gt;|briefing or playbook rule| API
    API --&amp;gt; UI&lt;/code&gt;&lt;/pre&gt;



&lt;p&gt;This separation also explains why the project can support both precision recall and cross-deal analysis. &lt;code&gt;/deals/{deal_id}/brief&lt;/code&gt; follows the tagged path. &lt;code&gt;/patterns&lt;/code&gt; intentionally opens the recall scope across the bank, then asks for one evidence-backed pattern instead of a general summary.&lt;/p&gt;

&lt;p&gt;For a local run, I create a Python 3.10+ environment, install &lt;code&gt;requirements.txt&lt;/code&gt;, set &lt;code&gt;GROQ_API_KEY&lt;/code&gt;, &lt;code&gt;HINDSIGHT_API_KEY&lt;/code&gt;, &lt;code&gt;HINDSIGHT_BASE_URL&lt;/code&gt;, &lt;code&gt;HINDSIGHT_BANK_ID=deal-intel&lt;/code&gt;, and &lt;code&gt;GROQ_MODEL&lt;/code&gt;, then seed the synthetic records before starting Uvicorn. The seed step matters: a clean Hindsight bank should produce the cold-start response, while the seeded bank makes the objection-resolution arc inspectable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;python scripts/generate_synthetic_deals.py
uvicorn app.main:app &lt;span class="nt"&gt;--reload&lt;/span&gt; &lt;span class="nt"&gt;--port&lt;/span&gt; 8000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# app/hindsight.py
&lt;/span&gt;&lt;span class="n"&gt;payload&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;items&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&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;content&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;[Deal &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;deal_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;] &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;strip&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&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;tags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;deal_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;metadata&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&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;deal_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;deal_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;source&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;deal-intel-agent&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The recall helper has two modes. For an individual briefing, it requires a deal ID and sends it as the tag filter. For cross-deal pattern detection, it deliberately leaves the filter out. The explicit branch is a useful little piece of policy: a normal query is scoped, and global recall requires the caller to ask for it by name.&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="c1"&gt;# app/hindsight.py
&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;deal_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="nc"&gt;ValueError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deal_id must be provided when scope is &lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;deal&lt;/span&gt;&lt;span class="sh"&gt;'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;deal_id&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;payload&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;tags_match&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;any&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That code is simple, but the simplicity should not be mistaken for a security boundary. It is an application-level retrieval filter over a shared bank. A production deployment with multiple customers would also need authorization around deal IDs, controlled bank access, and tests that prove one customer cannot request another customer’s identifier. The filter reduces accidental cross-deal contamination in the intended flow; it does not authenticate the caller. It also assumes deal identifiers are canonical and consistently attached when records enter the system. Missing or mistyped tags are an ingestion problem that retrieval cannot infer away.&lt;/p&gt;

&lt;p&gt;The briefing endpoint keeps the same pattern visible from the API layer. It asks Hindsight for relevant deal history, extracts text, then hands that context to the language model. The prompt is not expected to repair a bad scope decision downstream.&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="c1"&gt;# app/main.py
&lt;/span&gt;&lt;span class="n"&gt;memories&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;recall_deal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;deal_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;full deal history, objections, stakeholders, competitors&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;scope&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;deal&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;context_texts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&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="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;memories&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)]&lt;/span&gt;
&lt;span class="n"&gt;briefing_text&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generate_briefing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;context_texts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;query&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;Briefing for &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;company_name&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="n"&gt;deal_id&lt;/span&gt;&lt;span class="si"&gt;}&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;There is a deliberate asymmetry in the other direction. Pattern detection needs a wide view, so &lt;code&gt;/patterns&lt;/code&gt; calls recall with &lt;code&gt;scope="all"&lt;/code&gt; and then asks Groq to identify exactly one concrete repeating pattern. The model is given an instruction to cite examples and state when the evidence is too thin. The code also has a basic minimum of two recalled items, although two items alone do not establish a robust statistical correlation. A fluent sentence is a lead for a human to inspect, not a measured causal claim.&lt;/p&gt;

&lt;p&gt;This is where &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt; fits the project: the external memory service provides retain and recall over a bank, while the application decides how to tag and scope account records. The &lt;a href="https://docs.hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight documentation&lt;/a&gt; describes its memory API and retrieval operations. Vectorize’s &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;agent-memory overview&lt;/a&gt; gives useful context for the broader idea of persistent agent memory; this repository uses a narrower slice of that design, centered on deal-tagged recall and synthesis.&lt;/p&gt;

&lt;h2&gt;
  
  
  Before and after five interactions
&lt;/h2&gt;

&lt;p&gt;Take the seeded ApexLogistics account. Before history exists, &lt;code&gt;generate_briefing&lt;/code&gt; does not ask the model to improvise. It returns a deterministic cold-start briefing: no objections, stakeholders, or competitors are recorded, and the next move is a discovery call. That is a modest but important fallback. Empty memory should be represented as empty memory, not filled with generic confidence.&lt;/p&gt;

&lt;p&gt;After five interactions, the repository’s sample account has a much more useful sequence: Elena likes the route-optimization product but reports that LegacyFreight is 25% cheaper; a technical evaluation goes well; Marcus, the CFO, objects to the $6,000 monthly price while the quarter’s budget is constrained; the rep offers annual prepayment at 15% off and waives implementation fees; Marcus then approves the budget and signs. A deal-scoped recall can turn that sequence into a playbook entry: identify the champion, involve the economic veto early, treat price and budget timing as the real obstacle, and test annual prepayment when the customer’s accounting treatment rewards it. The outcome is part of the lesson; without the signed agreement, the discount would be just another attempted concession.&lt;/p&gt;

&lt;p&gt;The global path turns that single history into a testable playbook hypothesis. With ApexLogistics and CloudScale Systems in the bank, &lt;code&gt;/patterns&lt;/code&gt; can surface a pattern such as: when a CFO or procurement team objects to price or cites a cheaper competitor, annual prepaid billing, a 15% discount, and waived onboarding can move a stalled opportunity toward Closed-Won. That is more useful than “discount when the buyer pushes back” because it preserves the objection, the response, and the observed outcome together. It is also still a hypothesis; the endpoint is not a causal inference system.&lt;/p&gt;

&lt;p&gt;That before-and-after is grounded in the checked-in synthetic deal record, not a measured user study. The separate Hindsight bank only contains those interactions if the seed script has actually been run against a configured service. And a specific briefing depends on what recall returns: retrieval can omit a relevant note, or rank an old note above a newer one. The application exposes a recalled count, but it does not yet provide a source-by-source audit trail in the response.&lt;/p&gt;

&lt;h2&gt;
  
  
  Lessons learned
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Make scope a code path.&lt;/strong&gt; Deal identity belongs in the retain schema and the recall request. Relying on a model prompt to “ignore other accounts” is a weaker control.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep cold starts explicit.&lt;/strong&gt; Returning a deterministic no-history answer is safer than asking a model to infer facts from an empty context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Treat patterns as hypotheses.&lt;/strong&gt; Two similar outcomes may justify a playbook experiment; they do not prove that a discount caused a close. The current pattern endpoint has no statistical test or human approval workflow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Keep the source of truth clear.&lt;/strong&gt; Hindsight is used for semantic memory; &lt;code&gt;deals.json&lt;/code&gt; stores account metadata and a local log copy. They are separate writes, so a failure between them can leave them out of sync. The API currently retains remotely before saving locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Name the operational gaps honestly.&lt;/strong&gt; The service uses wildcard CORS, a flat JSON file, and a shared bank ID configured by environment. Those choices keep the integration small, but before a multi-user deployment I would add authenticated access, tenant isolation, durable transactional storage, and observability for recall quality and failure rates.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The central lesson is not that an agent can remember everything. It is that memory only helps when the application can state whose history it is retrieving, expose enough provenance to check the answer, and admit when the evidence is too thin. In Deal Intelligence Agent, &lt;code&gt;deal_id&lt;/code&gt; is the beginning of that contract—and the remaining production work is making the contract enforceable end to end.&lt;/p&gt;

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