<?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: M YASHWANTH REDDY</title>
    <description>The latest articles on DEV Community by M YASHWANTH REDDY (@yashwanthreddy14).</description>
    <link>https://dev.to/yashwanthreddy14</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%2F1435484%2F76853584-74cd-4a25-9c6c-6f38d37f15dd.png</url>
      <title>DEV Community: M YASHWANTH REDDY</title>
      <link>https://dev.to/yashwanthreddy14</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yashwanthreddy14"/>
    <language>en</language>
    <item>
      <title>My AI Sales Rep Learned From Hang-Ups With Hindsight</title>
      <dc:creator>M YASHWANTH REDDY</dc:creator>
      <pubDate>Tue, 29 Sep 2026 17:37:20 +0000</pubDate>
      <link>https://dev.to/yashwanthreddy14/my-ai-sales-rep-learned-from-hang-ups-with-hindsight-3k5o</link>
      <guid>https://dev.to/yashwanthreddy14/my-ai-sales-rep-learned-from-hang-ups-with-hindsight-3k5o</guid>
      <description>&lt;p&gt;The worst call my voice agent ever made went like this: "Hi Imran, Aisha from TableTap. Our billing app starts at just nine hundred ninety nine rupees a month." Imran runs a cloud kitchen. It was one o'clock, he had forty orders on screen, and he hung up after two sentences with a clear instruction: don't call during lunch rush.&lt;/p&gt;

&lt;p&gt;A human sales rep would remember that forever. My agent, like almost every AI calling agent I've seen, forgot it the moment the call ended. The next cloud kitchen owner got the same price-first pitch at the same bad hour.&lt;/p&gt;

&lt;p&gt;So I gave it a memory. Now every call, good or bad, becomes something the agent reads before it dials again.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the system does
&lt;/h2&gt;

&lt;p&gt;Aisha is an outbound voice sales rep for TableTap, a billing app for Indian restaurants, cafes and cloud kitchens. Her only job on a call is to book a twenty-minute demo.&lt;/p&gt;

&lt;p&gt;The stack is small:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Voice:&lt;/strong&gt; &lt;a href="https://github.com/livekit/agents" rel="noopener noreferrer"&gt;LiveKit Agents&lt;/a&gt; with AssemblyAI for speech-to-text, Gemma 4 31B as the LLM, the LiveKit turn detector, and Sarvam's Bulbul v3 for an Indian English voice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Memory:&lt;/strong&gt; &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight&lt;/a&gt;, an open-source agent memory system from Vectorize, holding every past call.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Frontend:&lt;/strong&gt; a Next.js dashboard that shows what the agent remembers about the prospect before the call, the live transcript, and the outcome after.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The flow has three steps. Before the call, &lt;code&gt;recall&lt;/code&gt; fetches what this person told us and &lt;code&gt;reflect&lt;/code&gt; works out what works with people like them. During the call, the LiveKit pipeline talks and a &lt;code&gt;record_call_outcome&lt;/code&gt; tool labels the result. After the call, &lt;code&gt;retain&lt;/code&gt; writes the transcript and outcome back.&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%2Fcoosy24xa35779eg3u52.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%2Fcoosy24xa35779eg3u52.png" alt="Architecture: the LiveKit voice agent reads a brief from the Hindsight memory bank before dialling and retains the call after hang-up" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The core idea: remember the person, learn the persona
&lt;/h2&gt;

&lt;p&gt;When I started, I thought "agent memory" meant one thing: remember what this user said last time. For a sales agent that is only half the value.&lt;/p&gt;

&lt;p&gt;Take Rahul, who owns a cafe in Bengaluru. On the first call he told Aisha his billing software crashes every weekend, he's opening a second outlet in November, his staff "are not tech people", and a competitor quoted him fifteen hundred rupees a month. He asked for a demo video on WhatsApp and a weekday callback after the twenty-fifth. That's &lt;strong&gt;person memory&lt;/strong&gt;, and it makes the callback sound like a follow-up instead of a cold call.&lt;/p&gt;

&lt;p&gt;Now take Sana, who runs a cloud kitchen in Hyderabad. Aisha has never spoken to her, so there is no person memory at all. But Aisha has spoken to Imran, Neha, Abdul and Pooja, all cloud kitchen owners. Imran hung up on a price-first pitch. Abdul hung up on a feature tour ("My customers are Swiggy's customers, not mine. What loyalty program?"). Neha and Pooja booked demos after Aisha asked about missed Swiggy and Zomato orders at rush hour. That's &lt;strong&gt;persona memory&lt;/strong&gt;, and it's what lets a first call go well.&lt;/p&gt;

&lt;p&gt;I did not want two storage systems for this. The trick that made it simple was one Hindsight bank and tags.&lt;/p&gt;

&lt;h2&gt;
  
  
  One bank, scoped by tags
&lt;/h2&gt;

&lt;p&gt;Every call is saved with three tags:&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;prospect_tags&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;dict&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;list&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="k"&gt;return&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;prospect:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;persona:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;persona&lt;/span&gt;&lt;span class="sh"&gt;'&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="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;industry:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;industry&lt;/span&gt;&lt;span class="sh"&gt;'&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="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Before a call, the agent asks two different questions of the same bank. For the person, it uses Hindsight's &lt;code&gt;recall&lt;/code&gt;, filtered strictly to that prospect's tag:&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="n"&gt;response&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;arecall&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bank_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BANK_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="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;What happened in past calls with &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;name&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt; at &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;company&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;: pains, objections, competitors, promises &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;and agreed follow-ups?&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&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;prospect:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;id&lt;/span&gt;&lt;span class="sh"&gt;'&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="n"&gt;tags_match&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_strict&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;max_tokens&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;types&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;world&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;experience&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;observation&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="n"&gt;prefer_observations&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;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For the persona, it uses &lt;code&gt;reflect&lt;/code&gt;, filtered to the persona tag. &lt;code&gt;reflect&lt;/code&gt; doesn't just return matching facts; it reasons over them and writes an answer:&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="n"&gt;response&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;client&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;areflect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;bank_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;BANK_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="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;Across our past calls with a &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s"&gt;, which opening angle and value &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;points led to booked meetings, which objections came up and what &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;answer worked, and what must the rep avoid? Reply as at most six &lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
        &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;short, direct coaching bullets.&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;tags&lt;/span&gt;&lt;span class="o"&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;persona:&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;persona&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="n"&gt;tags_match&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_strict&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;budget&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;low&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;any_strict&lt;/code&gt; matters. Without it, untagged memories can leak into the result, and Rahul's cafe history would show up in a cloud kitchen playbook. With it, one bank behaves like many narrow ones, and I can add a new axis (city, deal size) by adding a tag instead of a new bank.&lt;/p&gt;

&lt;p&gt;The bank is configured with missions that tell Hindsight what to extract from each transcript and how to reason. My favourite line in the codebase is the reflect mission: &lt;em&gt;"You are a blunt sales coach reviewing past calls. Base every point on evidence from calls, prefer what led to booked meetings, and call out approaches that got prospects to hang up."&lt;/em&gt; The &lt;a href="https://hindsight.vectorize.io/" rel="noopener noreferrer"&gt;Hindsight docs&lt;/a&gt; cover these bank-level missions, and they did more for output quality than any prompt tweak I made on the agent side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Memory must never block the phone
&lt;/h2&gt;

&lt;p&gt;The rule I care most about: memory makes a call better, but it must never stop a call from happening. Recall and reflect run in parallel, each with a timeout, and any failure falls back to an empty brief:&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;guarded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;return&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;wait_for&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coro&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;except&lt;/span&gt; &lt;span class="nb"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;memory lookup failed, continuing without it&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;default&lt;/span&gt;

&lt;span class="n"&gt;history&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;playbook&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="nf"&gt;guarded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;recall_prospect_history&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="p"&gt;[]),&lt;/span&gt;
    &lt;span class="nf"&gt;guarded&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;reflect_persona_playbook&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;prospect&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;persona&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="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The brief is appended to the system prompt as two sections, "What you remember about Rahul" and "Playbook learned from past calls with a Cafe Owner". The agent is told never to reveal it has a memory, because "According to my notes…" is a terrible thing to hear on a sales call.&lt;/p&gt;

&lt;p&gt;A small script, &lt;code&gt;show_brief.py&lt;/code&gt;, prints exactly what the agent reads before it dials. This is Rahul's brief, straight from Hindsight:&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%2Fcleedw6yseuhuoo7gw9t.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%2Fcleedw6yseuhuoo7gw9t.png" alt="Terminal output of show_brief.py for Rahul: recalled facts and the learned cafe owner playbook" width="800" height="693"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing the loop: retain after every call
&lt;/h2&gt;

&lt;p&gt;During the call, the LLM calls a &lt;code&gt;record_call_outcome&lt;/code&gt; tool as soon as the result is clear: &lt;code&gt;meeting_booked&lt;/code&gt;, &lt;code&gt;follow_up&lt;/code&gt;, &lt;code&gt;callback_requested&lt;/code&gt; or &lt;code&gt;not_interested&lt;/code&gt;, plus its opening angle and the objections it heard. When the call ends, a shutdown hook saves the transcript and outcome into Hindsight with &lt;code&gt;retain&lt;/code&gt;, under the same three tags.&lt;/p&gt;

&lt;p&gt;That tool is the quiet hero. A raw transcript tells Hindsight what was said. The outcome label tells it whether it worked. Without the label, &lt;code&gt;reflect&lt;/code&gt; can describe what cloud kitchen owners talk about; with it, &lt;code&gt;reflect&lt;/code&gt; can say which openers get meetings and which get hang-ups.&lt;/p&gt;

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

&lt;p&gt;Here is the same callback to Rahul with memory off and on. The dashboard has a switch for exactly this.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory off.&lt;/strong&gt; Aisha opens with the generic pitch about faster billing and daily sales on WhatsApp, then asks how he bills today. Rahul: "You called me three weeks ago. I told you all this already." She apologises and starts discovery again. A real owner hangs up here.&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%2Feg046zezmnbm50tuk35r.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%2Feg046zezmnbm50tuk35r.png" alt="Dashboard with Hindsight memory switched off: the memory panels are greyed out and Aisha calls like a stateless agent" width="800" height="837"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memory on.&lt;/strong&gt; The pre-call panel shows everything Hindsight recalled from the first call. Aisha calls on a weekday, asks whether the video helped, and brings up the new outlet. When Rahul raises his staff again, she offers on-site setup and ten-minute training, the answer that won over another cafe owner who had the same worry. He books a demo.&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%2Fsqf024slhhgfycxrba30.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%2Fsqf024slhhgfycxrba30.png" alt="Dashboard with memory on: what Aisha remembers about Rahul from Hindsight recall, and the cafe owner playbook from reflect" width="800" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For Sana, a first call, the cloud kitchen playbook says: open with missed Swiggy and Zomato orders at rush hour, never lead with price or features, never call during lunch rush, and answer "Swiggy's tablet is free" with the cost of juggling two tablets. Each point traces back to a specific earlier call. Nobody wrote that script. It was learned from what worked and what didn't.&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%2Fkqs32mr3ohfk5e2o2iq5.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%2Fkqs32mr3ohfk5e2o2iq5.png" alt="First call to Sana: no personal history yet, but a cloud kitchen playbook learned from other owners' calls" width="800" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;1. Split memory into "this person" and "people like this".&lt;/strong&gt; Per-user recall is the obvious feature. Per-segment reflection is where the agent actually improves. Tags in one bank gave me both.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Label outcomes at the source.&lt;/strong&gt; Have the agent record the result with a tool call while the call is still happening. Inferring "did this work?" from transcripts later is much weaker than an explicit label.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Treat memory as optional at runtime.&lt;/strong&gt; Timeouts plus empty defaults mean a slow memory lookup costs you personalisation, not a call. In a voice product, a phone that doesn't ring is worse than a generic pitch.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Expect duplicates and clean them.&lt;/strong&gt; The same fact ("don't call on weekends") can come back from more than one call. &lt;code&gt;prefer_observations=True&lt;/code&gt; lets Hindsight return its consolidated observations instead of every raw fact, and I still dedupe the text before it goes into the prompt.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;5. Small samples produce confident advice.&lt;/strong&gt; This is the honest limitation. With a handful of calls per persona, &lt;code&gt;reflect&lt;/code&gt; will turn two data points into a rule. The evidence-first mission helps, but the playbook is only as good as the calls behind it, and a brand-new persona gets no playbook at all.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where this goes next
&lt;/h2&gt;

&lt;p&gt;The part that surprised me most is how little sales logic I wrote. I wrote down what happened on each call, labelled whether it worked, and &lt;a href="https://vectorize.io/what-is-agent-memory" rel="noopener noreferrer"&gt;Hindsight's agent memory&lt;/a&gt; turned that into two kinds of knowledge: what this person told us, and what works with people like them. Call one is generic. Call five is personal. By call fifty, its playbook comes from its own market instead of the script I started with.&lt;/p&gt;

&lt;p&gt;If you're building any agent that talks to the same people more than once, or to many people of the same kind, try giving it memory before you give it a longer prompt. The &lt;a href="https://github.com/vectorize-io/hindsight" rel="noopener noreferrer"&gt;Hindsight repository on GitHub&lt;/a&gt; is a good place to start.&lt;/p&gt;

&lt;p&gt;The full code for this agent, including the Hindsight memory module and the dashboard, is on GitHub: &lt;a href="https://github.com/yashwanth1403/tabletap-sdr-hindsight" rel="noopener noreferrer"&gt;tabletap-sdr-hindsight&lt;/a&gt;.&lt;/p&gt;

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