Architecture

- Ticket isolation: Each support ticket is a separate
group_id - Customer profile: User-level memories persist across tickets
- Cross-ticket search: Find relevant past issues for the same customer
Setup: Support Bot Configuration
Copy
import requests
from datetime import datetime
import uuid
BASE_URL = "https://api.evermind.ai"
headers = {"Content-Type": "application/json"}
class SupportBot:
def __init__(self, bot_id: str = "support_bot"):
self.bot_id = bot_id
def create_ticket(self, ticket_id: str, customer_id: str, customer_name: str, subject: str):
"""Initialize a new support ticket."""
group_id = f"ticket_{ticket_id}"
# Configure as assistant scene for full memory extraction
meta = {
"group_id": group_id,
"group_name": f"Support: {subject}",
"scene": "assistant",
"user_details": [
{"user_id": customer_id, "user_name": customer_name, "role": "user"},
{"user_id": self.bot_id, "user_name": "Support Bot", "role": "assistant"}
]
}
requests.post(f"{BASE_URL}/api/v0/memories/conversation-meta", json=meta, headers=headers)
# Store ticket creation event
self._store_message(
group_id=group_id,
sender_id=self.bot_id,
content=f"New support ticket created. Subject: {subject}. Customer: {customer_name}"
)
return group_id
def _store_message(self, group_id: str, sender_id: str, content: str):
"""Store a message in the ticket."""
message = {
"group_id": group_id,
"group_name": "Support Ticket",
"message_id": str(uuid.uuid4()),
"create_time": datetime.now().isoformat() + "Z",
"sender": sender_id,
"sender_name": "Customer" if sender_id != self.bot_id else "Support Bot",
"content": content
}
return requests.post(f"{BASE_URL}/api/v0/memories", json=message, headers=headers)
Customer Message Handling
When a customer sends a message, store it and retrieve relevant context.Copy
def handle_customer_message(
self,
ticket_id: str,
customer_id: str,
message: str
) -> dict:
"""Process customer message and return context for response generation."""
group_id = f"ticket_{ticket_id}"
# 1. Store the customer message
self._store_message(group_id, customer_id, message)
# 2. Get context from multiple sources
context = self._gather_context(customer_id, message, group_id)
return context
def _gather_context(self, customer_id: str, query: str, current_ticket: str) -> dict:
"""Gather relevant context from EverMemOS."""
# Customer profile (preferences, account info)
profile_memories = self._search_memories(
user_id=customer_id,
query=query,
memory_types=["profile"],
top_k=5
)
# Current ticket history
current_ticket_memories = self._search_memories(
group_ids=[current_ticket],
query=query,
memory_types=["episodic_memory"],
top_k=3
)
# Past tickets (similar issues)
past_ticket_memories = self._search_memories(
user_id=customer_id,
query=query,
memory_types=["episodic_memory"],
top_k=5
)
# Filter out current ticket
past_ticket_memories = [
m for m in past_ticket_memories
if m.get("group_id") != current_ticket
]
return {
"customer_profile": profile_memories,
"current_ticket": current_ticket_memories,
"past_tickets": past_ticket_memories[:3] # Limit to most relevant
}
def _search_memories(self, query: str, memory_types: list, top_k: int,
user_id: str = None, group_ids: list = None) -> list:
"""Search EverMemOS for relevant memories."""
search_params = {
"query": query,
"retrieve_method": "hybrid",
"top_k": top_k,
"memory_types": memory_types
}
if user_id:
search_params["user_id"] = user_id
if group_ids:
search_params["group_ids"] = group_ids
response = requests.get(
f"{BASE_URL}/api/v0/memories/search",
json=search_params,
headers=headers
)
return response.json().get("result", {}).get("memories", [])
Generate Context-Aware Response
Use retrieved context to generate personalized responses.Copy
def generate_response(self, customer_message: str, context: dict) -> str:
"""Generate response using LLM with memory context."""
# Format context for LLM
context_text = self._format_context(context)
prompt = f"""You are a helpful customer support agent. Use the following context to provide personalized support.
CUSTOMER PROFILE:
{context_text['profile']}
CURRENT TICKET CONTEXT:
{context_text['current']}
RELEVANT PAST TICKETS:
{context_text['past']}
CUSTOMER MESSAGE:
{customer_message}
Instructions:
- Address the customer by name if known
- Reference past issues if relevant (e.g., "I see you had a similar issue before...")
- Use customer preferences (e.g., communication style, technical level)
- Don't repeat information the customer already provided
- Be concise but thorough
Response:"""
# Replace with your LLM call
# response = openai.chat.completions.create(...)
return "[LLM response here]"
def _format_context(self, context: dict) -> dict:
"""Format context for LLM prompt."""
profile_text = "\n".join([
f"- {m.get('memory_content', '')}"
for m in context.get("customer_profile", [])
]) or "No profile information available."
current_text = "\n".join([
f"- {m.get('memory_content', '')}"
for m in context.get("current_ticket", [])
]) or "New ticket, no history yet."
past_text = "\n".join([
f"- [{m.get('group_id', 'unknown')}] {m.get('memory_content', '')}"
for m in context.get("past_tickets", [])
]) or "No relevant past tickets."
return {
"profile": profile_text,
"current": current_text,
"past": past_text
}
Complete Support Bot Implementation
Copy
import requests
from datetime import datetime
import uuid
BASE_URL = "https://api.evermind.ai"
headers = {"Content-Type": "application/json"}
class CustomerSupportBot:
def __init__(self):
self.bot_id = "support_bot"
def create_ticket(self, ticket_id: str, customer_id: str, customer_name: str, subject: str) -> str:
"""Create a new support ticket."""
group_id = f"ticket_{ticket_id}"
meta = {
"group_id": group_id,
"group_name": f"Support: {subject}",
"scene": "assistant",
"user_details": [
{"user_id": customer_id, "user_name": customer_name, "role": "user"},
{"user_id": self.bot_id, "user_name": "Support Bot", "role": "assistant"}
]
}
requests.post(f"{BASE_URL}/api/v0/memories/conversation-meta", json=meta, headers=headers)
self._store(group_id, self.bot_id, f"Ticket opened: {subject}")
return group_id
def customer_message(self, ticket_id: str, customer_id: str, message: str) -> str:
"""Handle customer message and generate response."""
group_id = f"ticket_{ticket_id}"
# Store customer message
self._store(group_id, customer_id, message)
# Gather context
context = self._get_context(customer_id, message, group_id)
# Generate response (implement with your LLM)
response = self._generate_response(message, context)
# Store bot response
self._store(group_id, self.bot_id, response)
return response
def escalate_to_agent(self, ticket_id: str, agent_id: str, agent_name: str) -> dict:
"""Generate handoff context for human agent."""
group_id = f"ticket_{ticket_id}"
# Get comprehensive context
summary = self._search(group_ids=[group_id], query="issue summary resolution attempts", top_k=10)
return {
"ticket_id": ticket_id,
"summary": [m.get("memory_content") for m in summary],
"handoff_note": f"Escalated to {agent_name}. See memory context for full history."
}
def _store(self, group_id: str, sender_id: str, content: str):
message = {
"group_id": group_id,
"group_name": "Support",
"message_id": str(uuid.uuid4()),
"create_time": datetime.now().isoformat() + "Z",
"sender": sender_id,
"sender_name": "Support Bot" if sender_id == self.bot_id else "Customer",
"content": content
}
requests.post(f"{BASE_URL}/api/v0/memories", json=message, headers=headers)
def _search(self, query: str, top_k: int = 5, user_id: str = None, group_ids: list = None, memory_types: list = None) -> list:
params = {
"query": query,
"retrieve_method": "hybrid",
"top_k": top_k,
"memory_types": memory_types or ["episodic_memory", "profile"]
}
if user_id:
params["user_id"] = user_id
if group_ids:
params["group_ids"] = group_ids
resp = requests.get(f"{BASE_URL}/api/v0/memories/search", json=params, headers=headers)
return resp.json().get("result", {}).get("memories", [])
def _get_context(self, customer_id: str, query: str, current_group: str) -> dict:
return {
"profile": self._search(user_id=customer_id, query=query, memory_types=["profile"]),
"current": self._search(group_ids=[current_group], query=query, memory_types=["episodic_memory"], top_k=3),
"history": [m for m in self._search(user_id=customer_id, query=query) if m.get("group_id") != current_group][:3]
}
def _generate_response(self, message: str, context: dict) -> str:
# Implement with your LLM
profile_summary = "; ".join([m.get("memory_content", "")[:50] for m in context["profile"]])
return f"[Response using context: {profile_summary}...]"
# Usage Example
bot = CustomerSupportBot()
# Customer opens a ticket
ticket = bot.create_ticket(
ticket_id="T-2024-001",
customer_id="customer_john",
customer_name="John Smith",
subject="Unable to reset password"
)
# Customer sends messages
response1 = bot.customer_message(
ticket_id="T-2024-001",
customer_id="customer_john",
message="I've been trying to reset my password but the email never arrives."
)
print(f"Bot: {response1}")
response2 = bot.customer_message(
ticket_id="T-2024-001",
customer_id="customer_john",
message="I checked spam folder too. My email is john@example.com"
)
print(f"Bot: {response2}")
# Escalate if needed
handoff = bot.escalate_to_agent("T-2024-001", "agent_sarah", "Sarah")
print(f"Handoff context: {handoff}")
Cross-Ticket Intelligence
Search across all of a customer’s tickets to find patterns.Copy
def find_recurring_issues(customer_id: str) -> list:
"""Find patterns across customer's support history."""
search_params = {
"user_id": customer_id,
"query": "issue problem error unable",
"retrieve_method": "agentic", # Use agentic for complex pattern finding
"top_k": 20,
"memory_types": ["episodic_memory"]
}
response = requests.get(f"{BASE_URL}/api/v0/memories/search", json=search_params, headers=headers)
memories = response.json().get("result", {}).get("memories", [])
# Group by ticket
tickets = {}
for mem in memories:
ticket = mem.get("group_id", "unknown")
if ticket not in tickets:
tickets[ticket] = []
tickets[ticket].append(mem.get("memory_content"))
return tickets
# Find if customer has had similar issues before
history = find_recurring_issues("customer_john")
if len(history) > 1:
print(f"Customer has {len(history)} previous tickets")
Best Practices
Ticket Isolation
Ticket Isolation
Always use unique
group_id per ticket to maintain isolation.Copy
# Good: Ticket-based group IDs
group_id = f"ticket_{ticket_id}"
group_id = f"support_{customer_id}_{ticket_number}"
# Bad: Shared group IDs
group_id = "support" # All tickets mixed together
Privacy Considerations
Privacy Considerations
Be mindful of PII when generating LLM prompts.
Copy
# Filter sensitive profile memories before LLM
safe_memories = [
m for m in profile_memories
if not any(term in m.get("memory_content", "").lower()
for term in ["ssn", "credit card", "password"])
]
Agent Handoff
Agent Handoff
Provide structured context for human agents.
Copy
handoff = {
"ticket_id": ticket_id,
"customer_summary": "3-year customer, premium tier",
"issue_summary": "Password reset email not arriving",
"attempted_solutions": ["Checked spam", "Verified email"],
"customer_sentiment": "Frustrated but polite",
"relevant_history": ["Similar issue 6 months ago - spam filter"]
}