Skip to main content

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