DEV Community

Cover image for Why I Built a Cross-Deal Memory Search and What Hindsight Made Possible
Khushi Singh
Khushi Singh

Posted on

Why I Built a Cross-Deal Memory Search and What Hindsight Made Possible

Six months into building sales tooling, I hit a wall that no one warns you about: your agent is only as useful as its worst conversation. Doesn't matter how good the LLM is. If it can't connect what happened in Deal A to what's happening right now in Deal B, it's giving advice that ignores half the available signal.

That's the problem the Autopilot feature in the Deal Intelligence Agent was built to solve — and it only became possible because of how Hindsight stores and retrieves memory across deal boundaries.

The problem with per-deal memory silos

The first version of the agent had great per-deal memory. You could ask about any deal and get accurate, grounded answers about that specific account's history. Objections, stakeholders, pricing discussions — all there, all retrievable.

What it couldn't do was answer questions like: "Has an objection like this ever come up before? What worked?"

That's where the real value lives. An experienced sales rep doesn't just know their current deals — they pattern-match across everything they've ever worked on. They remember that the "we need to check with legal" objection from a manufacturing company last year was actually a stall tactic, and the way to break it was a specific framing around risk reduction, not around speed.

An agent with siloed per-deal memory can't do that. It's smart within a deal and blind across deals.

How Hindsight enabled cross-deal search

The MemoryService wraps Hindsight's persistent memory layer with a semantic_search method that can operate either scoped to one deal or across all deals in the system:

async def semantic_search(
    self,
    query: str,
    deal_id: Optional[str] = None,
    limit: int = 10
) -> List[Dict]:
    """Cross-deal semantic search."""
    if deal_id:
        return await self.get_relevant_memories(deal_id, query, limit)

    # Search across all deals
    all_results = []
    for d_id, memories in _fallback_store.items():
        for mem in memories:
            if query.lower() in mem.get("content", "").lower():
                all_results.append({**mem, "deal_id": d_id})

    return all_results[:limit]
Enter fullscreen mode Exit fullscreen mode

In the Hindsight-connected path, client.memory.search handles the semantic similarity natively across the pipeline. In fallback mode, it iterates the local store. The interface is identical either way.

The Autopilot loop in practice

The Autopilot service uses this cross-deal search to run an autonomous objection resolution pass across every active deal. Here's the sequence:

  1. Pull all active deals from the CRM
  2. For each deal, retrieve unresolved objections from Hindsight
  3. Run semantic_search across all closed-won deals for similar objections
  4. If a match is found from a won deal, surface that resolution strategy
  5. Generate a full playbook: strategy, email draft, SMS, risk reduction estimate
  6. Store the playbook back in Hindsight as an autopilot_action entry
search_query = f"resolved {obj_category} objection {obj_text}"
raw_matches = await self.memory.semantic_search(search_query, limit=5)

resolved_strategy = None
matched_deal_name = None

for match in raw_matches:
    m_deal_id = match.get("deal_id")
    if m_deal_id and m_deal_id != deal_id:
        m_deal = _deals.get(m_deal_id)
        if m_deal and m_deal.get("outcome") == "won":
            resolved_strategy = match.get("content")
            matched_deal_name = m_deal.get("company_name")
            break
Enter fullscreen mode Exit fullscreen mode

The key constraint: only pull strategies from deals with outcome == "won". Pulling from lost deals would be actively harmful — you'd be surfacing exactly what didn't work.

What the live execution looks like

The Autopilot runs as a FastAPI BackgroundTask and streams timestamped logs to a frontend console in real time. The log levels (INFO, PROCESS, RECALL, MATCH, REASON, SUCCESS) tell the story:

[INFO]    Autopilot Agent triggered. Initializing CRM pipeline scan...
[PROCESS] Analyzing account context: 'Meridian Systems'...
[RECALL]  Retrieved 3 unresolved objections from Hindsight for 'Meridian Systems'.
[RECALL]  Primary objection: "Price is 40% above current vendor" [Category: pricing]
[PROCESS] Cross-Deal Search: Querying Hindsight for historical resolution patterns...
[MATCH]   Found historical match in CLOSED-WON deal: 'Apex Corp'.
[REASON]  Recall resolution strategy: "Offered 24-month commit with 20% discount bundled with onboarding..."
[SUCCESS] Objection Resolution Playbook generated for 'Meridian Systems' (Risk reduction: -22%).
Enter fullscreen mode Exit fullscreen mode

When there's no historical match, the agent falls back to synthesizing a strategy via Groq — but it logs that explicitly so reps know they're working with generated advice rather than proven patterns.

What this actually changes for a sales team

The difference between "AI assistant" and "AI that makes you better over time" is whether the system learns from closed deals. Every deal you win or lose adds signal. Without agent memory that persists across sessions and across deals, that signal evaporates the moment the call ends.

With Hindsight storing typed, searchable outcomes, the Autopilot can tell a rep: "This exact objection type — pricing from a mid-market manufacturing company — came up in three deals this year. Two were won. Here's what worked." That's institutional knowledge that doesn't live in anyone's head or get lost when a rep leaves.

Three things I'd tell someone building cross-deal memory:

Don't assume per-deal scoping is sufficient. It feels complete until you need cross-deal reasoning. Design the user_id scoping and the cross-search path from day one.

Filter retrieved matches by outcome before surfacing them. "What worked" and "what happened" are different questions. Only the former is useful for an agent giving action recommendations.

Store every outcome explicitly. Win/loss is obvious, but stage changes, objection resolutions, and competitive outcomes are all learning signal. If you don't write them to memory at event time, they're gone.

GitHub: github.com/chaitanya07-ai/deal-intelligence-agent | Live: deal-intelligence-agent-1.onrender.com

Top comments (0)