Conversational AI: From RAG Prototypes to Domain-Specific Supervision

Per-Channel vs Per-User: What Memory Model Works for AI Chat

The first version of the Slack bot had no memory. Every message was independent. Someone would ask a question, get an answer, ask a follow-up, and the bot would have no idea what they were following up on.

The fix seemed obvious: store conversation history per user. But Slack isn’t a one-on-one chat - it’s a workspace with channels, threads, and DMs. The memory model needed to match how people use it.

Three interaction patterns

People talk to the bot in three different ways, and each needs different context handling.

Channel mentions. Someone types @Iris what's our returns policy? in a channel. This is a standalone question. The bot gets the current message only - no history. Loading the entire channel history would be noisy and irrelevant. The question stands on its own.

Thread replies. Someone asks a question, gets an answer, and replies in the thread with a follow-up. Now context matters. The bot loads all messages in the thread - every message from every participant. The thread is a coherent conversation, and the bot needs the full picture to answer the follow-up.

Direct messages. Someone opens a DM with the bot for a private conversation. The bot loads today’s messages (up to 50) as context. This provides session continuity without loading weeks of unrelated conversations.

Why per-channel, not per-user

The initial instinct was per-user memory: track what each person has asked and use it as context. But in Slack, conversations are collaborative. Alice asks about a project. Bob adds context. Charlie asks a follow-up that references both.

Per-user memory would give the bot Alice’s questions but not Bob’s context or Charlie’s framing. The bot would see fragments of a conversation, not the conversation itself.

Per-channel memory (specifically per-thread) captures the full collaborative context. Everyone’s contributions are in the thread, and the bot sees them all.

Persistent memory

Beyond immediate conversation context, the bot maintains a persistent memory service backed by Postgres. This tracks:

  • Entities - people, projects, locations mentioned across conversations
  • Decisions - conclusions reached, actions agreed
  • Preferences - how a team likes things done

Memory entries have a configurable expiry - 48 hours by default. This prevents stale context from contaminating current conversations. A decision made two months ago might no longer be relevant, and the bot shouldn’t assume it still applies.

The stateless alternative

The customer-facing chat API took a different approach: fully stateless. The client sends the conversation history with each request. The server processes it and forgets.

This works for customer support where conversations are short, self-contained, and don’t benefit from cross-session context. It keeps the server simple and avoids the complexity of session management on Lambda.

The choice depends on the interaction pattern. Collaborative workspace conversations benefit from server-side memory. Transactional customer queries work fine stateless.