<?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: Sreekar KVK</title>
    <description>The latest articles on DEV Community by Sreekar KVK (@kvksreekar).</description>
    <link>https://dev.to/kvksreekar</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%2F4148714%2F5676adf5-da3e-4997-8e4e-c4ecf9f974ba.png</url>
      <title>DEV Community: Sreekar KVK</title>
      <link>https://dev.to/kvksreekar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kvksreekar"/>
    <language>en</language>
    <item>
      <title>She Never Worked Those Ten Deals. Her Agent Remembered All of Them.</title>
      <dc:creator>Sreekar KVK</dc:creator>
      <pubDate>Tue, 29 Sep 2026 06:08:49 +0000</pubDate>
      <link>https://dev.to/kvksreekar/she-never-worked-those-ten-deals-her-agent-remembered-all-of-them-5mg</link>
      <guid>https://dev.to/kvksreekar/she-never-worked-those-ten-deals-her-agent-remembered-all-of-them-5mg</guid>
      <description>&lt;p&gt;A sales agent on one shared Hindsight memory bank, with one rule that keeps it honest: the model writes the words, code does the math.&lt;br&gt;
Week three. A prospect says finance has frozen new vendor spend. The new rep hasn't said a word yet, but the agent beside her already knows something useful: of the ten past deals that hit the same objection at the same stage, six were lost. It drafts a follow-up based on the four that survived.&lt;br&gt;
She has never worked a single one of those ten deals.&lt;br&gt;
Most teams get hindsight in the post-mortem, after the deal is already dead. I wanted it mid-call. Hindsight, Vectorize's open-source agent memory system, gave me the memory layer to build it.&lt;br&gt;
Sales teams forget how they lose&lt;br&gt;
Sales teams repeatedly lose deals to the same handful of causes: budget freezes, champions changing roles, competitor discounts, missing executive sponsors.&lt;br&gt;
The knowledge exists, but it's scattered across CRM notes, call recordings, Slack threads, and senior reps' heads. When a senior rep leaves, their hard-earned lessons leave too.&lt;br&gt;
Call-intelligence tools can analyze a call or deal. I wanted something different: compare the live deal against the team's entire loss history and produce a specific, evidence-backed warning.&lt;br&gt;
Seven steps, no new workflow for the rep&lt;br&gt;
The agent reads existing calls, emails, and CRM notes. Every event follows:&lt;br&gt;
retain → extract → recall → reflect → score → explain → draft&lt;br&gt;
Retain: closed deals go into one shared memory bank.&lt;br&gt;
Extract: signals such as objections and competitors come from the prospect's turns.&lt;br&gt;
Recall: similar deals are fetched by objection, stage, and deal size.&lt;br&gt;
Reflect: code computes patterns such as "6 of 10 lost at this stage."&lt;br&gt;
Score: a running belief updates as new evidence arrives.&lt;br&gt;
Explain: every change gets a one-line reason tied to the counts.&lt;br&gt;
Draft: when a pattern is sufficiently risky, the agent drafts a follow-up based on deals that survived the same objection.&lt;br&gt;
Hindsight's documentation describes the core operations as retain, recall, and reflect; the rest of the pipeline sits around them.&lt;br&gt;
One shared bank, not one per rep&lt;br&gt;
The most important architectural decision was using one memory bank for the whole team.&lt;br&gt;
A separate bank per rep would give every new hire an empty memory. A shared bank lets them inherit the team's accumulated experience.&lt;br&gt;
I retain structured facts rather than raw transcripts:&lt;br&gt;
BANK_ID = "sales-team-shared"&lt;/p&gt;

&lt;p&gt;client.retain_batch(&lt;br&gt;
    bank_id=BANK_ID,&lt;br&gt;
    items=[&lt;br&gt;
        {&lt;br&gt;
            "content": render_deal(d),&lt;br&gt;
            "context": f"{d.outcome} deal, {d.objection_stage} stage",&lt;br&gt;
            "tags": [&lt;br&gt;
                f"objection:{d.objection}",&lt;br&gt;
                f"stage:{d.objection_stage}",&lt;br&gt;
                f"outcome:{d.outcome}",&lt;br&gt;
                f"rep:{d.rep}",&lt;br&gt;
            ],&lt;br&gt;
        }&lt;br&gt;
        for d in deals&lt;br&gt;
    ],&lt;br&gt;
)&lt;/p&gt;

&lt;p&gt;The structured representation makes recall about the shape of a deal, rather than the exact wording of a transcript.&lt;br&gt;
Tags are important too. Semantic retrieval is great for finding similar memories, but statistics need hard boundaries. Tags let me ask for exactly "budget freeze, Evaluation, lost" instead of relying on similarity to define the dataset.&lt;br&gt;
The model never does the arithmetic&lt;br&gt;
This was the rule that made me trust the system.&lt;br&gt;
An early version let the model describe the pattern. It was fluent, but wrong often enough that I stopped trusting it.&lt;br&gt;
So I took the arithmetic away from the model.&lt;br&gt;
def reflect_pattern(deals, objection, stage):&lt;br&gt;
    scoped = [&lt;br&gt;
        d for d in deals&lt;br&gt;
        if d.objection == objection&lt;br&gt;
        and d.objection_stage == stage&lt;br&gt;
    ]&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;lost = sum(d.outcome == "lost" for d in scoped)

return Pattern(
    key=f"objection:{objection}@{stage}",
    total=len(scoped),
    lost=lost,
    won=len(scoped) - lost,
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Code computes the numbers. The model only explains them.&lt;br&gt;
Every generated reason must contain the exact lost / total figures. If validation fails, the system retries and eventually falls back to a template.&lt;br&gt;
Hindsight's reflection output can still be shown, but if it disagrees with the computed counts, the counts win.&lt;br&gt;
The score is a belief, not a recalculation&lt;br&gt;
Instead of recomputing a win probability from scratch after every message, I treat it as a running belief.&lt;br&gt;
Evidence changes the score in log-odds space, with confidence increasing as more historical deals support a pattern.&lt;br&gt;
A signal backed by two deals therefore moves the score less than one backed by ten.&lt;br&gt;
I also hit a real bug here: one competitor had five losses and zero wins. A loss ratio of exactly 1.0 sends logit() to infinity.&lt;br&gt;
Clamping the ratio fixed it. The exact clamp range is a documented engineering choice, not something I claim is mathematically fundamental.&lt;br&gt;
One deal, blow by blow&lt;br&gt;
Here's what the system looks like during a live evaluation-stage deal.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Competitor mentioned.
The competitor appeared in seven historical deals, six of which were lost. The score dips slightly because a mention alone is weak evidence.&lt;/li&gt;
&lt;li&gt;Finance freezes spend.
The score drops significantly:
"Dropped 15 pts: budget freeze mentioned, and 6 of 10 past budget_freeze deals at Evaluation were lost."&lt;/li&gt;
&lt;li&gt;A follow-up is drafted.
The pattern crosses our threshold, so the agent pulls responses from the four deals that survived the same objection and drafts a follow-up offering approaches that worked historically.&lt;/li&gt;
&lt;li&gt;The champion wobbles.
Another risk signal appears, but because the wording is uncertain, it receives lower weight. The existing draft isn't discarded; the agent adds a heads-up.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The prospect responds positively.&lt;br&gt;
The score recovers. The historical exception remains visible rather than being filtered out.&lt;br&gt;
Nothing changed but the memory&lt;br&gt;
This is probably my favorite behavior.&lt;br&gt;
Add one more lost budget-freeze deal and the next run changes from:&lt;br&gt;
6 of 10&lt;br&gt;
to:&lt;br&gt;
7 of 11&lt;br&gt;
No prompt edit. No retraining.&lt;br&gt;
The memory changed, so the agent's behavior changed.&lt;br&gt;
Never count what you only partly recalled&lt;br&gt;
There is one dangerous trap: using a truncated retrieval result as the basis for a statistic.&lt;br&gt;
Recall is designed to return the best matching memories within a context budget. That's perfect for giving an LLM useful context, but terrible for calculating "6 of 10".&lt;br&gt;
So the system separately reconstructs the complete deal dataset and verifies the totals against known ground truth.&lt;br&gt;
def integrity_check(client, expected):&lt;br&gt;
recalled = fetch_all_deals(client, bank_id=BANK_ID)&lt;br&gt;
got = tally(recalled)&lt;/p&gt;

&lt;p&gt;return "COUNTS VERIFIED" if got == expected else "COUNT MISMATCH"&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If Hindsight isn't reachable, the system falls back to a local store and explicitly says so. It never pretends to be using a memory backend that isn't available.&lt;br&gt;
Five things I'd tell anyone building on agent memory&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Retain facts, not transcripts. Structured records make recall about deal shape rather than vocabulary.&lt;/li&gt;
&lt;li&gt;Let code count and the model talk. Numbers users act on should trace back to records.&lt;/li&gt;
&lt;li&gt;Choose memory scope based on what you want to transfer. A shared bank lets new hires inherit the team's experience.&lt;/li&gt;
&lt;li&gt;Verify recall before trusting aggregates. Retrieval is fine for context and dangerous for statistics.&lt;/li&gt;
&lt;li&gt;Don't confuse correlation with causation. "6 of 10 lost" is a pattern in one team's history, not proof that the objection caused the losses.
What I like about keeping the memory in Hindsight is that the model can stay small and stateless. The memory does the remembering, so every newly closed deal becomes another piece of experience available to the next call.
Which brings me back to week three.
A rep is about to hear that finance has frozen spend, and she doesn't need to have worked those ten deals to know what they taught.
Whatever happens on her call, it goes into the bank too.
Nobody on the team should have to lose the same deal twice.
Code: &lt;a href="https://github.com/ANIKETHSAI9813/lost_agent.git" rel="noopener noreferrer"&gt;https://github.com/ANIKETHSAI9813/lost_agent.git&lt;/a&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%2F6p1bjlsso2s2fat92kqy.png" alt=" " width="800" height="731"&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%2Fzi3fv8bg5nhgeki6h1j1.jpeg" alt=" " width="800" height="386"&gt;
&lt;/li&gt;
&lt;/ol&gt;

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