> ## Documentation Index
> Fetch the complete documentation index at: https://docs.evermind.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Team Collaboration & Group Chat

> Build memory for group discussions, meetings, and team collaboration

EverOS supports group chat memory with multi-participant conversations. This guide shows how to build memory for team discussions, meeting notes, and collaborative contexts using the v1 SDK.

## Prerequisites

Install the EverOS SDK:

```bash theme={null}
pip install everos-cloud
```

## Group Chat vs Assistant Scene

EverOS has two scene types with different memory extraction behaviors:

| Feature          | Assistant Scene        | Group Chat Scene              |
| ---------------- | ---------------------- | ----------------------------- |
| Participants     | 1 user + 1 assistant   | Multiple users                |
| Episode Memory   | Individual perspective | Group + personal perspectives |
| Profile Memory   | User profiles          | All participants' profiles    |
| Foresight Memory | Supported              | Not supported                 |
| EventLog Memory  | Supported              | Not supported                 |

<Note>
  In group chat scene, EverOS generates **two types of episodes**: group-level summaries (what the team discussed) and personal episodes (what each individual said/learned).
</Note>

## Setup: Register Group and Senders

First, register the group and each sender so EverOS knows about participants.

```python theme={null}
from everos_cloud import EverOS

client = EverOS()
groups = client.v1.groups
senders = client.v1.senders

# Create the group
groups.create(
    group_id="team_engineering",
    name="Engineering Team",
    description="Engineering team daily collaboration channel"
)

# Register each participant as a sender
senders.create(sender_id="user_alice", name="Alice")
senders.create(sender_id="user_bob", name="Bob")
senders.create(sender_id="user_carol", name="Carol")
senders.create(sender_id="bot_assistant", name="Team Bot")
```

## Store Group Messages

Store messages from any participant in the group using `client.v1.memories.group.add()`. Each message must include `sender_id` and `sender_name`.

```python theme={null}
import time

group_mem = client.v1.memories.group
now_ms = int(time.time() * 1000)

# Store a batch of team discussion messages
resp = group_mem.add(
    group_id="team_engineering",
    messages=[
        {
            "role": "user",
            "sender_id": "user_alice",
            "sender_name": "Alice",
            "timestamp": now_ms,
            "content": "Team, we need to decide on the database for the new project.",
            "message_id": "msg_001",
        },
        {
            "role": "user",
            "sender_id": "user_bob",
            "sender_name": "Bob",
            "timestamp": now_ms + 5000,
            "content": "I think PostgreSQL would work well. It's what we know best.",
            "message_id": "msg_002",
        },
        {
            "role": "user",
            "sender_id": "user_carol",
            "sender_name": "Carol",
            "timestamp": now_ms + 10000,
            "content": "I agree with Bob. Plus we already have monitoring set up for Postgres.",
            "message_id": "msg_003",
        },
        {
            "role": "user",
            "sender_id": "user_alice",
            "sender_name": "Alice",
            "timestamp": now_ms + 15000,
            "content": "Good points. Let's go with PostgreSQL. Bob, can you set up the schema?",
            "message_id": "msg_004",
        },
        {
            "role": "user",
            "sender_id": "user_bob",
            "sender_name": "Bob",
            "timestamp": now_ms + 20000,
            "content": "Sure, I'll have a draft ready by Friday.",
            "message_id": "msg_005",
        },
    ],
)
```

## Flush Group Memory

When a conversation topic reaches a natural boundary, flush to trigger memory extraction.

```python theme={null}
# Trigger memory extraction for the group
group_mem.flush(group_id="team_engineering")
```

## Retrieve Group Memories

Search memories from a specific group.

```python theme={null}
memories = client.v1.memories

def search_group_memories(group_id: str, query: str):
    """Search memories within a group."""
    return memories.search(
        filters={"group_id": group_id},
        query=query,
        method="vector",
        memory_types=["episodic_memory", "profile"],
        top_k=10,
    )

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

### Group vs Personal Episodes

EverOS generates two perspectives for group chats:

```python theme={null}
# Get group-level summary (what the team discussed)
group_memories = memories.search(
    filters={"group_id": "team_engineering"},
    query="project architecture decisions",
    method="vector",
    memory_types=["episodic_memory"],
    top_k=5,
)
# 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 = memories.search(
    filters={"group_id": "team_engineering", "user_id": "user_bob"},
    query="project architecture decisions",
    method="vector",
    memory_types=["episodic_memory"],
    top_k=5,
)
# 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.

```python theme={null}
import time
from everos_cloud import EverOS


class MeetingMemoryBot:
    def __init__(self, group_id: str, group_name: str):
        self.client = EverOS()
        self.group_id = group_id
        self.group_name = group_name
        self.bot_id = "bot_meeting_assistant"
        self.group_mem = self.client.v1.memories.group
        self.memories = self.client.v1.memories
        self.msg_counter = 0

    def setup_meeting(self, participants: list, meeting_topic: str):
        """Initialize meeting with group and senders."""
        groups = self.client.v1.groups
        senders = self.client.v1.senders

        # Register group
        groups.create(
            group_id=self.group_id,
            name=self.group_name,
            description=f"Meeting: {meeting_topic}"
        )

        # Register all participants and the bot as senders
        for p in participants:
            senders.create(sender_id=p["user_id"], name=p["name"])
        senders.create(sender_id=self.bot_id, name="Meeting Bot")

        # Store meeting context as the first message
        self._next_msg_id()
        now_ms = int(time.time() * 1000)
        self.group_mem.add(
            group_id=self.group_id,
            messages=[
                {
                    "role": "assistant",
                    "sender_id": self.bot_id,
                    "sender_name": "Meeting Bot",
                    "timestamp": now_ms,
                    "content": (
                        f"Meeting started. Topic: {meeting_topic}. "
                        f"Participants: {', '.join(p['name'] for p in participants)}"
                    ),
                    "message_id": self._next_msg_id(),
                }
            ],
        )

    def _next_msg_id(self) -> str:
        self.msg_counter += 1
        return f"meeting_msg_{self.msg_counter:04d}"

    def record_discussion(self, speaker_id: str, speaker_name: str, content: str):
        """Record a discussion point."""
        now_ms = int(time.time() * 1000)
        self.group_mem.add(
            group_id=self.group_id,
            messages=[
                {
                    "role": "user",
                    "sender_id": speaker_id,
                    "sender_name": speaker_name,
                    "timestamp": now_ms,
                    "content": content,
                    "message_id": self._next_msg_id(),
                }
            ],
        )

    def get_relevant_context(self, topic: str) -> str:
        """Retrieve context relevant to current discussion."""
        resp = self.memories.search(
            filters={"group_id": self.group_id},
            query=topic,
            method="vector",
            memory_types=["episodic_memory"],
            top_k=5,
        )

        results = resp.get("result", {}).get("memories", [])
        if not results:
            return "No relevant past discussions found."

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

        return "\n".join(context_parts)

    def end_meeting(self):
        """Flush group memory to trigger extraction."""
        self.group_mem.flush(group_id=self.group_id)


# 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

# End meeting and trigger memory extraction
bot.end_meeting()
```

## Best Practices

<AccordionGroup>
  <Accordion title="Group ID Strategy">
    Use meaningful, hierarchical group IDs for better organization.

    ```python theme={null}
    # 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
    ```
  </Accordion>

  <Accordion title="Message Format">
    Every group message must include `sender_id` and `sender_name`. Use millisecond timestamps.

    ```python theme={null}
    import time

    message = {
        "role": "user",
        "sender_id": "user_alice",
        "sender_name": "Alice",
        "timestamp": int(time.time() * 1000),
        "content": "The message text here.",
        "message_id": "unique_msg_id",
    }
    ```
  </Accordion>

  <Accordion title="Flush at Topic Boundaries">
    Call `flush()` when a topic naturally ends to help EverOS extract clean memory boundaries.

    ```python theme={null}
    group_mem = client.v1.memories.group

    # After a discussion topic wraps up
    group_mem.flush(group_id="team_engineering")
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Customer Support" icon="headset" href="/cookbook/customer-support">
    Apply group memory to support ticket contexts
  </Card>

  <Card title="Batch Processing" icon="layer-group" href="/cookbook/batch-processing">
    Import existing chat history at scale
  </Card>
</CardGroup>
