Skip to main content
Search tools help the AI find the right memory without looking in the wrong places. All searches respect channel, client, and knowledge-base isolation boundaries.

What this means in practice

This includes:
  • semantic search over recent messages (STM)
  • scoped message visibility by channel
  • time-range filtering for recent continuity
  • knowledge-base-aware query behavior
  • client/channel isolation rules (enforced server-side)
Search short-term memory (recent messages) by semantic similarity. Complements crystal_recall (which searches long-term memories).

Parameters

Returns

Examples

Basic message search:
Search within a specific channel:
Search recent messages only (last 7 days):
Search engineering channel since a specific time:

Channel filtering

What channels do

  • Isolate conversations — messages in one channel are not visible to queries scoped to another channel
  • Enable cross-client scenarios — the same user can have separate channels for different integrations (e.g., Slack vs Telegram)
  • Preserve context boundaries — memory recall respects channel scope by default

Using channels

If you omit channel, searches return results from all channels the user has access to. To narrow results:
  1. Provide the channel name — Pass the channel identifier (e.g., ”slack”, ”telegram”, ”claude-code”)
  2. Verify visibility — Server-side rules enforce that you only see messages within accessible channels
  3. Combine with sinceMs — Time range + channel gives fine-grained control

Example: Multi-channel scenario

A user interacts with Memory Crystal via both Slack and Telegram. Each has its own channel. To search only Slack messages:
To search both, omit the channel parameter (or make two calls with different channels).

Time-range filtering with sinceMs

Use sinceMs to retrieve messages after a specific Unix timestamp (milliseconds):

Examples

Messages from today onwards:
Messages from a specific week:

When to use vs alternatives

crystal_search_messages (recent, exact context)

Use when: You need to find recent messages by semantic meaning, preserving context and timestamps. Best for: Session continuity, recent decision tracking, finding exact phrasing from recent conversations. Example: “What did we just discuss about authentication?”

crystal_recall (long-term, high-confidence memories)

Use when: You want to find durable, extracted facts and decisions. Better for understanding patterns and history. Best for: Getting the gist of a topic without reading full conversation history. Example: “What have we decided about authentication?”

Decision guide

Scoping and isolation

Memory Crystal enforces isolation at multiple levels:
  1. User-level isolation — Users never see each other’s messages or memories (enforced by userId)
  2. Channel-level isolation — Messages in one channel don’t appear in queries scoped to another (enforced by channel filtering)
  3. Knowledge-base isolation — KB queries only return chunks from the specified knowledge base
  4. Age-based visibility — Archived memories and expired STM messages are hidden by default
Server-side guarantee: All filtering is enforced server-side. Client code cannot bypass isolation rules.

Error handling

How it actually works

Key repo surfaces:
  • mcp-server/src/tools/search-messages.ts — tool definition and HTTP handler
  • convex/crystal/messages.ts — message storage and search logic
  • convex/crystal/mcp.ts — API endpoint routing
  • convex/crystal/recall.ts — scoping and filtering rules
The flow:
  1. Tool validates query, limit, channel, and sinceMs parameters
  2. Query is embedded using OpenAI’s text-embedding-3-small
  3. ConvexClient POSTs to /api/mcp/search-messages with embedding
  4. Backend applies channel and time filters
  5. Vector search retrieves top-K matching messages
  6. Results are returned with scores and timestamps
Channel and user isolation is enforced at the database level, not in the tool code.

Common mistakes

  • Treating search and recall as if they are identical (they’re designed for different purposes)
  • Forgetting that scoped channels affect results (all searches are channel-aware)
  • Not using sinceMs for time-range queries (just relying on default recency)
  • Assuming cross-channel visibility when channels are set (isolation is enforced)
  • Using crystal_search_messages for long-term patterns (use crystal_recall instead)

Source of truth

Primary files behind this page:
  • mcp-server/src/tools/search-messages.ts — tool definition
  • convex/crystal/messages.ts — backend logic and filtering
  • convex/crystal/recall.ts — scoping rules
  • convex/crystal/knowledgeBases.ts — KB visibility logic
  • convex/crystal/mcp.ts — HTTP endpoint routing