fleet-memory/hindsight-docs/docs/cookbook/support-agent-with-shared-knowledge.md
Nicolò Boschi 040eb33ea6
improve ci and tests (#22)
* improve ci and tests

* add more tests

* fixes

* fix tests

* fix more

* fix

* fix

* fix

* fix

* fix for real

* tests and doc

* fix cp

* fix link pg0

* fix pg0

* fix pg0

* fix pg0

* even better

* more

* fix
2025-12-09 19:16:00 +01:00

7.8 KiB

sidebar_position
3

Support Agent with Shared Knowledge

This pattern shows how to build a support agent that combines per-user memory with shared product knowledge (RAG), giving users personalized support while leveraging a single source of truth for documentation.

The Problem

You're building a support agent that needs to:

  • Remember each user's history, preferences, and past issues
  • Access shared product documentation
  • Keep user data completely isolated from other users

A naive approach would index product docs into each user's memory bank, but this is expensive and wasteful (N copies for N users).

The Solution: Multi-Bank Architecture

Create separate memory banks for different concerns:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   User A Bank   │     │   User B Bank   │     │  Shared Docs    │
│                 │     │                 │     │     Bank        │
│  - Conversations│     │  - Conversations│     │                 │
│  - Preferences  │     │  - Preferences  │     │  - Product docs │
│  - Past issues  │     │  - Past issues  │     │  - FAQs         │
│  - Solutions    │     │  - Solutions    │     │  - Guides       │
└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
         │                       │                       │
         └───────────────────────┴───────────────────────┘
                                 │
                           Agent queries
                           multiple banks

Key benefits:

  • Product docs indexed once, shared by all users
  • User memory is 100% isolated
  • Simple mental model, no complex filtering

Implementation

1. Set Up Memory Banks

Create three types of banks:

from hindsight import HindsightClient

client = HindsightClient()

# Shared knowledge bank (created once)
shared_bank = client.create_bank(
    bank_id="product-docs",
    name="Product Documentation"
)

# Per-user banks (created when user signs up)
def create_user_bank(user_id: str):
    return client.create_bank(
        bank_id=f"user-{user_id}",
        name=f"Memory for {user_id}"
    )

2. Index Product Documentation

Index your product docs into the shared bank (do this once, or on doc updates):

# Index product documentation
client.retain(
    bank_id="product-docs",
    content=[
        {
            "role": "document",
            "content": "# Pricing Tiers\n\nBasic: $10/mo...",
            "metadata": {"source": "pricing.md"}
        },
        {
            "role": "document",
            "content": "# Getting Started\n\nTo set up...",
            "metadata": {"source": "quickstart.md"}
        }
    ]
)

3. Store User Conversations

After each support interaction, retain it in the user's bank:

def save_conversation(user_id: str, messages: list):
    client.retain(
        bank_id=f"user-{user_id}",
        content=messages  # [{"role": "user", "content": "..."}, ...]
    )

4. Query Multiple Banks at Support Time

When handling a user query, retrieve context from both banks:

async def get_support_context(user_id: str, query: str):
    # Get user's personal context
    user_context = await client.recall(
        bank_id=f"user-{user_id}",
        query=query
    )

    # Get relevant product documentation
    docs_context = await client.recall(
        bank_id="product-docs",
        query=query
    )

    return {
        "user_history": user_context.results,
        "documentation": docs_context.results
    }

5. Build the Agent Prompt

Combine both contexts in your agent's prompt:

def build_prompt(query: str, context: dict) -> str:
    return f"""You are a helpful support agent.

## User's History
{format_results(context["user_history"])}

## Product Documentation
{format_results(context["documentation"])}

## Current Question
{query}

Use the user's history to personalize your response and the documentation
for accurate product information. If you find a solution, remember it for
future reference.
"""

Promoting Learnings to Shared Knowledge

When the agent discovers a solution that's not in the docs, you can optionally promote it to a "learnings" bank:

┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│   User A Bank   │     │  Shared Docs    │     │    Learnings    │
│                 │     │     Bank        │     │      Bank       │
│  - Conversations│     │                 │     │                 │
│  - Preferences  │     │  - Product docs │     │  - Verified     │
│  - Past issues  │     │  - FAQs         │     │    solutions    │
│  - Solutions    │     │  - Guides       │     │  - Workarounds  │
└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
         │                       │                       │
         └───────────────────────┴───────────────────────┘
                                 │
                           Agent queries
                           all three banks
# Optional: Create a curated learnings bank
learnings_bank = client.create_bank(
    bank_id="support-learnings",
    name="Curated Support Learnings"
)

# After a successful resolution
def promote_learning(insight: str):
    client.retain(
        bank_id="support-learnings",
        content=[{
            "role": "system",
            "content": insight,
            "metadata": {"type": "verified_solution"}
        }]
    )

Then query three banks: user + docs + learnings.

Complete Example

from hindsight import HindsightClient

client = HindsightClient()

async def handle_support_request(user_id: str, query: str):
    # 1. Recall from user's memory
    user_recall = await client.recall(
        bank_id=f"user-{user_id}",
        query=query
    )

    # 2. Recall from shared docs
    docs_recall = await client.recall(
        bank_id="product-docs",
        query=query
    )

    # 3. Recall from learnings (optional)
    learnings_recall = await client.recall(
        bank_id="support-learnings",
        query=query
    )

    # 4. Build context for LLM
    context = f"""
User History:
{format_results(user_recall.results)}

Product Docs:
{format_results(docs_recall.results)}

Known Solutions:
{format_results(learnings_recall.results)}
"""

    # 5. Generate response with your LLM
    response = await llm.complete(
        system="You are a support agent...",
        context=context,
        query=query
    )

    # 6. Save the conversation to user's memory
    await client.retain(
        bank_id=f"user-{user_id}",
        content=[
            {"role": "user", "content": query},
            {"role": "assistant", "content": response}
        ]
    )

    return response

When to Use This Pattern

Good fit:

  • Support agents with shared documentation
  • Multi-tenant applications with shared reference data
  • Any scenario needing user isolation + shared knowledge

Consider alternatives if:

  • You need cross-user learning (users benefiting from other users' solutions)
  • Entity relationships must span across users and docs