Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.memorycrystal.ai/llms.txt

Use this file to discover all available pages before exploring further.

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

ParameterTypeRequiredDescription
querystringYesThe search query. Embedded and matched against message content.
limitnumberNoMaximum results to return. Default: 10. Range: 1–20.
channelstringNoScope search to a specific channel. If not provided, searches all accessible channels.
sinceMsnumberNoOnly return messages after this Unix timestamp (in milliseconds). Useful for time-range queries.

Returns

{
  “query”: “authentication strategy”,
  “results”: [
    {
      “_id”: “msg_abc123,
      “role”: “user”,
      “content”: “How should we implement auth in the new API?”,
      “channel”: “engineering”,
      “timestamp”: 1713314400000,
      “score”: 0.89
    },
    {
      “_id”: “msg_def456,
      “role”: “assistant”,
      “content”: “I recommend using OAuth2 with JWT tokens for stateless auth.”,
      “channel”: “engineering”,
      “timestamp”: 1713314460000,
      “score”: 0.85
    }
  ],
  “limit”: 10,
  “channel”: “engineering”,
  “sinceMs”: null
}

Examples

Basic message search:
{
  “query”: “what did we decide about the database?”
}
Search within a specific channel:
{
  “query”: “deploy process”,
  “channel”: “devops”
}
Search recent messages only (last 7 days):
{
  “query”: “API authentication”,
  “sinceMs”: 1712104800000,
  “limit”: 5
}
Search engineering channel since a specific time:
{
  “query”: “performance optimization”,
  “channel”: “engineering”,
  “sinceMs”: 1713000000000,
  “limit”: 15
}

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:
{
  “query”: “project timeline”,
  “channel”: “slack”
}
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):
// Messages from the last 7 days
const sevenDaysAgo = Date.now() - (7 * 24 * 60 * 60 * 1000);

// Messages from a specific date (2026-04-16)
const specificDate = new Date(“2026-04-16”).getTime();

Examples

Messages from today onwards:
{
  “query”: “decisions made”,
  “sinceMs”: 1713004800000
}
Messages from a specific week:
{
  “query”: “deployment issues”,
  “sinceMs”: 1712000000000,
  “channel”: “devops”
}

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

ScenarioTool
Find an exact recent message or phrasingcrystal_search_messages
Get the summary/decision from a topiccrystal_recall
Get context on why a decision was madecrystal_why_did_we
Get all information about a topiccrystal_what_do_i_know
Find the most recent N messages chronologicallycrystal_recent
Query a knowledge basecrystal_query_knowledge_base

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

ErrorCauseResolution
query is requiredNo query parameter was provided.Provide a non-empty search string.
Embedding service unavailableThe embedding backend is unreachable.Retry; check service health.
Memory Crystal recall degradedSame as above.Retry later.
Invalid channelChannel identifier is malformed or inaccessible.Verify the channel name exists.
Invalid sinceMssinceMs is not a valid Unix timestamp.Use Date.now() or a numeric millisecond timestamp.
Empty resultsNo messages matched the query/filters.Try a broader query or remove the channel/time filter.

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