Skip to main content
EverMemOS supports group chat memory with multi-participant conversations. This guide shows how to build memory for team discussions, meeting notes, and collaborative contexts.

Group Chat vs Assistant Scene

EverMemOS has two scene types with different memory extraction behaviors:
FeatureAssistant SceneGroup Chat Scene
Participants1 user + 1 assistantMultiple users
Episode MemoryIndividual perspectiveGroup + personal perspectives
Profile MemoryUser profilesAll participants’ profiles
Foresight MemorySupportedNot supported
EventLog MemorySupportedNot supported
In group chat scene, EverMemOS generates two types of episodes: group-level summaries (what the team discussed) and personal episodes (what each individual said/learned).

Setup: Configure Group Chat Scene

First, configure the conversation metadata for group chat.
import requests
from datetime import datetime

BASE_URL = "https://api.evermind.ai"
headers = {"Content-Type": "application/json"}

def setup_group_chat(group_id: str, group_name: str, participants: list):
    """Configure metadata for group chat conversations."""
    user_details = [
        {
            "user_id": p["user_id"],
            "user_name": p["name"],
            "role": p.get("role", "user")
        }
        for p in participants
    ]

    meta = {
        "group_id": group_id,
        "group_name": group_name,
        "scene": "group_chat",
        "user_details": user_details
    }

    response = requests.post(
        f"{BASE_URL}/api/v0/memories/conversation-meta",
        json=meta,
        headers=headers
    )
    return response.json()

# Example: Set up a team channel
setup_group_chat(
    group_id="team_engineering",
    group_name="Engineering Team",
    participants=[
        {"user_id": "user_alice", "name": "Alice", "role": "tech_lead"},
        {"user_id": "user_bob", "name": "Bob", "role": "engineer"},
        {"user_id": "user_carol", "name": "Carol", "role": "engineer"},
        {"user_id": "bot_assistant", "name": "Team Bot", "role": "assistant"}
    ]
)

Store Group Messages

Store messages from any participant in the group.
import uuid

def store_group_message(group_id: str, sender_id: str, sender_name: str, content: str):
    """Store a group chat message."""
    message = {
        "group_id": group_id,
        "group_name": "Engineering Team",
        "message_id": str(uuid.uuid4()),
        "create_time": datetime.now().isoformat() + "Z",
        "sender": sender_id,
        "sender_name": sender_name,
        "content": content,
        "refer_list": []  # Can reference other messages
    }

    response = requests.post(
        f"{BASE_URL}/api/v0/memories",
        json=message,
        headers=headers
    )
    return response.json()

# Simulate a team discussion
store_group_message("team_engineering", "user_alice", "Alice",
    "Team, we need to decide on the database for the new project.")

store_group_message("team_engineering", "user_bob", "Bob",
    "I think PostgreSQL would work well. It's what we know best.")

store_group_message("team_engineering", "user_carol", "Carol",
    "I agree with Bob. Plus we already have monitoring set up for Postgres.")

store_group_message("team_engineering", "user_alice", "Alice",
    "Good points. Let's go with PostgreSQL. Bob, can you set up the schema?")

store_group_message("team_engineering", "user_bob", "Bob",
    "Sure, I'll have a draft ready by Friday.")

Message References

Group chats often have replies and references. Use refer_list to capture these relationships.
# Original message
original = store_group_message("team_engineering", "user_alice", "Alice",
    "Should we use microservices or monolith for this project?")
original_id = "msg_original_123"  # Use actual message ID

# Reply referencing the original
reply = {
    "group_id": "team_engineering",
    "group_name": "Engineering Team",
    "message_id": "msg_reply_456",
    "create_time": datetime.now().isoformat() + "Z",
    "sender": "user_bob",
    "sender_name": "Bob",
    "content": "Given our team size, I'd suggest starting with a monolith. We can always split later.",
    "refer_list": [
        {
            "message_id": original_id,
            "content": "Should we use microservices or monolith for this project?"
        }
    ]
}

response = requests.post(f"{BASE_URL}/api/v0/memories", json=reply, headers=headers)

Retrieve Group Memories

Search memories from a specific group or across all groups for a user.
def search_group_memories(group_id: str, query: str, user_id: str = None):
    """Search memories within a group."""
    search_params = {
        "group_ids": [group_id],
        "query": query,
        "retrieve_method": "hybrid",
        "top_k": 10,
        "memory_types": ["episodic_memory", "profile"]
    }

    # Optionally filter by user perspective
    if user_id:
        search_params["user_id"] = user_id

    response = requests.get(
        f"{BASE_URL}/api/v0/memories/search",
        json=search_params,
        headers=headers
    )
    return response.json()

# Search team discussions about databases
result = search_group_memories("team_engineering", "database decision")

Group vs Personal Episodes

EverMemOS generates two perspectives for group chats:
# Get group-level summary (what the team discussed)
group_memories = search_group_memories(
    group_id="team_engineering",
    query="project architecture decisions"
)
# Returns: "The engineering team discussed database options and decided
#          to use PostgreSQL. Bob will prepare the schema by Friday."

# Get personal perspective (what Bob specifically contributed/learned)
personal_memories = search_group_memories(
    group_id="team_engineering",
    query="project architecture decisions",
    user_id="user_bob"
)
# Returns: "Bob advocated for PostgreSQL based on team familiarity.
#          He was assigned to create the database schema by Friday."

Use Case: Meeting Memory Bot

Build a bot that joins meetings and provides contextual information.
class MeetingMemoryBot:
    def __init__(self, group_id: str, group_name: str):
        self.group_id = group_id
        self.group_name = group_name
        self.bot_id = "bot_meeting_assistant"

    def setup_meeting(self, participants: list, meeting_topic: str):
        """Initialize meeting with participants."""
        all_participants = participants + [
            {"user_id": self.bot_id, "name": "Meeting Bot", "role": "assistant"}
        ]

        setup_group_chat(self.group_id, self.group_name, all_participants)

        # Store meeting context
        self._store_message(
            f"Meeting started. Topic: {meeting_topic}. "
            f"Participants: {', '.join(p['name'] for p in participants)}"
        )

    def _store_message(self, content: str, sender_id: str = None, sender_name: str = None):
        """Store a message from meeting."""
        message = {
            "group_id": self.group_id,
            "group_name": self.group_name,
            "message_id": str(uuid.uuid4()),
            "create_time": datetime.now().isoformat() + "Z",
            "sender": sender_id or self.bot_id,
            "sender_name": sender_name or "Meeting Bot",
            "content": content
        }
        requests.post(f"{BASE_URL}/api/v0/memories", json=message, headers=headers)

    def record_discussion(self, speaker_id: str, speaker_name: str, content: str):
        """Record a discussion point."""
        self._store_message(content, speaker_id, speaker_name)

    def get_relevant_context(self, topic: str) -> str:
        """Retrieve context relevant to current discussion."""
        # Search across this group's history
        search_params = {
            "group_ids": [self.group_id],
            "query": topic,
            "retrieve_method": "hybrid",
            "top_k": 5,
            "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", [])

        if not memories:
            return "No relevant past discussions found."

        context_parts = ["Relevant past discussions:"]
        for mem in memories:
            context_parts.append(f"- {mem.get('memory_content', '')}")

        return "\n".join(context_parts)

    def generate_summary(self) -> str:
        """Generate meeting summary from recent memories."""
        search_params = {
            "group_ids": [self.group_id],
            "query": "meeting discussion decisions action items",
            "retrieve_method": "hybrid",
            "top_k": 10,
            "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", [])

        # Use LLM to synthesize summary (placeholder)
        return f"Meeting covered {len(memories)} discussion topics. [LLM summary here]"


# Usage
bot = MeetingMemoryBot("meeting_sprint_planning_2024_01", "Sprint Planning")

bot.setup_meeting(
    participants=[
        {"user_id": "user_alice", "name": "Alice"},
        {"user_id": "user_bob", "name": "Bob"},
    ],
    meeting_topic="Q1 Sprint Planning"
)

# During meeting
bot.record_discussion("user_alice", "Alice", "We should prioritize the auth refactor this sprint.")
bot.record_discussion("user_bob", "Bob", "Agreed. I can take the backend portion.")

# Get context when needed
context = bot.get_relevant_context("authentication system")
print(context)  # Shows past discussions about auth

Best Practices

Use meaningful, hierarchical group IDs for better organization.
# Good: Hierarchical naming
group_id = "team_engineering_sprint_2024_01"
group_id = "project_phoenix_standup"
group_id = "meeting_quarterly_review_2024_q1"

# Avoid: Generic names
group_id = "chat_1"  # Not descriptive
Define clear roles for better memory context.
participants = [
    {"user_id": "u1", "name": "Alice", "role": "product_manager"},
    {"user_id": "u2", "name": "Bob", "role": "tech_lead"},
    {"user_id": "u3", "name": "Carol", "role": "designer"},
    {"user_id": "bot", "name": "Assistant", "role": "assistant"}
]
Help EverMemOS detect topic boundaries by structuring discussions.
# Explicit topic markers help memory extraction
store_message("Let's move on to discuss the timeline...")
store_message("To summarize what we decided about databases...")
store_message("New topic: resource allocation...")

Next Steps