# Context Engine

> Performs hybrid semantic/lexical search with neural reranking for codebase retrieval. Use for finding implementations, Q&A grounded in source code, and cross-session persistent memory.

- Skill: `context-engine-ai/context-engine` (Agent Skill)
- Install (CLI): `npx skillmds@latest add context-engine-ai/context-engine`
- Raw SKILL.md: https://api.skillmd.com/api/skills/context-engine-ai/context-engine/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: context-engine-ai (https://skillmd.com/u/context-engine-ai)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/context-engine-ai/context-engine

---


# Context-Engine

Search and retrieve code context from any codebase using hybrid vector search (semantic + lexical) with neural reranking.

Client- or provider-specific wrapper files should stay thin and defer to this document for shared MCP tool-selection and search guidance.

## Quickstart

1. Start with `search` for most codebase questions.
2. Use `symbol_graph` first for direct symbol relationships such as callers, definitions, importers, subclasses, and base classes.
3. Use `graph_query` only if that tool is available and you need transitive impact, dependency, or cycle analysis; otherwise combine `symbol_graph` with targeted search.
4. Prefer MCP tools for exploration. Narrow grep/file-open use is still fine for exact literal confirmation, exact file/path confirmation, or opening a file you already identified for editing.
5. Use `cross_repo_search` for multi-repo questions. For public V1 `context_search`, treat `include_memories=true` as compatibility-only: it preserves response shape but keeps results code-only and may add `memory_note`.

## Decision Tree: Choosing the Right Tool

```
What do you need?
    |
    +-- UNSURE or GENERAL QUERY --> search (RECOMMENDED DEFAULT)
    |       |
    |       +-- Auto-detects intent and routes to the best tool
    |       +-- Handles: code search, Q&A, tests, config, symbols, imports
    |       +-- Use this when you don't know which specialized tool to pick
    |
    +-- Find code locations/implementations
    |       |
    |       +-- Unsure what tool to use → search (DEFAULT - routes to repo_search if needed)
    |       +-- Speed-critical or complex filters → repo_search (skip routing overhead)
    |       +-- Want LLM explanation → context_answer
    |
    +-- Understand how something works
    |       |
    |       +-- Want LLM explanation --> search OR context_answer
    |       +-- Just code snippets --> search OR repo_search with include_snippet=true
    |
    +-- Find similar code patterns (retry loops, error handling, etc.)
    |       |
    |       +-- Have code example --> pattern_search with code snippet (if enabled)
    |       +-- Describe pattern --> pattern_search with natural language (if enabled)
    |
    +-- Find specific file types
    |       |
    |       +-- Test files --> search OR search_tests_for
    |       +-- Config files --> search OR search_config_for
    |
    +-- Find relationships
    |       |
    |       +-- Direct callers/defs/importers/inheritance --> search OR symbol_graph
    |       +-- Multi-hop callers --> symbol_graph (depth=2+)
    |       +-- Deep impact/dependencies/cycles --> graph_query (if available) OR symbol_graph + targeted search
    |
    +-- Git history
    |       |
    |       +-- Find commits --> search_commits_for
    |       +-- Predict co-changing files --> search_commits_for with predict_related=true
    |
    +-- Store/recall knowledge --> memory_store, memory_find
    |
    +-- Preserve public search shape while accepting memory flags --> context_search with include_memories=true (compatibility-only in V1)
    |
    +-- Multiple independent searches at once
            |
            +-- batch_search (runs N repo_search calls in one invocation, ~75% token savings)
```

## Standard Parameters Reference

All SaaS-exposed tools organize parameters into families with consistent naming and behavior.

### Family 1: Code Search Tools
**Applies to:** `search`, `repo_search`, `code_search`, `batch_search`, `info_request`, `context_search`

**Standard Parameters:**

| Parameter | Type | Required? | Default | Purpose |
|-----------|------|-----------|---------|---------|
| `query` | string or string[] | YES | — | Single query OR array of queries for fusion |
| `language` | string | optional | (auto-detect) | Filter by language: "python", "typescript", "go", etc. |
| `under` | string | optional | (root) | Path prefix filter, e.g., "src/api/" or "tests/" |
| `path_glob` | string[] | optional | (all) | Include patterns: `["**/*.ts", "lib/**"]` |
| `not_glob` | string[] | optional | (none) | Exclude patterns: `["**/test_*", "**/*_test.*"]` |
| `symbol` | string | optional | (all) | Filter by symbol name (function, class, variable) |
| `kind` | string | optional | (all) | AST node type: "function", "class", "method", "variable" |
| `ext` | string | optional | (all) | File extension: "py", "ts", "go" (alias for language) |
| `repo` | string or string[] | optional | (default) | Repository filter: single repo OR list OR "*" for all |
| `limit` | int | optional | 10 | Max results to return (1-100) |
| `include_snippet` | bool | optional | true | Include code snippets in results |
| `compact` | bool | optional | false | Strip verbose fields from response |
| `output_format` | string | optional | "json" | "json" (structured) OR "toon" (token-efficient) |
| `rerank_enabled` | bool | optional | true | Enable neural reranking (default ON) |
| `case` | string | optional | (insensitive) | "sensitive" for case-sensitive matching |
| `context_lines` | int | optional | 2 | Lines of context around matches |
| `per_path` | int | optional | 2 | Max results per file |

**Standard Constraints:**
- `limit` max 100 (higher values slow queries)
- `query` max 400 characters / 50 words
- `language` must be valid code language or auto-detection will fail silently
- `path_glob` / `not_glob` support glob patterns (*, **, ?)
- Multiple `query` terms are fused via Reciprocal Rank Fusion (RRF) for better recall

### Family 2: Symbol Graph Tools
**Applies to:** `symbol_graph`, `batch_symbol_graph`, `graph_query`, `batch_graph_query`

**Standard Parameters:**

| Parameter | Type | Required? | Default | Purpose |
|-----------|------|-----------|---------|---------|
| `symbol` | string | YES | — | Symbol name to analyze (e.g., "authenticate", "UserService.get_user") |
| `query_type` | string | optional | "callers" | "callers", "callees", "definition", "importers", "subclasses", "base_classes", "impact", "cycles", "transitive_callers", "transitive_callees", "dependencies" |
| `depth` | int | optional | 1 | Traversal depth: 1=direct, 2=callers of callers, etc. (symbol_graph: max 3, graph_query: max 5+) |
| `language` | string | optional | (auto) | Filter by language for multi-language codebases |
| `under` | string | optional | (all) | Path prefix filter |
| `limit` | int | optional | 20 | Max results to return |
| `include_paths` | bool | optional | false | Include full traversal paths (graph_query only) |
| `output_format` | string | optional | "json" | "json" or "toon" |
| `repo` | string | optional | (default) | Repository filter |
| `collection` | string | optional | (session) | Target collection (use session defaults) |

**Standard Constraints:**
- `symbol` must be exact match or use fuzzy fallback
- `query_type` is case-sensitive
- `depth > 3` may be slow on large graphs
- Results are auto-hydrated with code snippets

### Family 3: Specialized Search Tools
**Applies to:** `search_tests_for`, `search_config_for`, `search_callers_for`, `search_importers_for`, `search_commits_for`

**Standard Parameters:**

| Parameter | Type | Required? | Default | Purpose |
|-----------|------|-----------|---------|---------|
| `query` | string | YES | — | Natural language or symbol name |
| `limit` | int | optional | 10 | Max results to return |
| `language` | string | optional | (auto) | Filter by language |
| `under` | string | optional | (all) | Path prefix filter |

**Additional Parameters:**

| Tool | Extra Parameters |
|------|------------------|
| `search_commits_for` | `path` (optional), `predict_related` (bool, default false) |
| All others | (inherit code search family) |

### Family 4: Memory Tools
**Applies to:** `memory_store`, `memory_find`

**Standard Parameters:**

| Parameter | Type | Required? | Default | Purpose |
|-----------|------|-----------|---------|---------|
| `information` | string | YES (store) | — | Knowledge to persist (clear, self-contained) |
| `query` | string | YES (find) | — | Search for stored knowledge by similarity |
| `metadata` | dict | optional (store) | {} | Structured metadata: kind, topic, priority (1-5), tags, author |
| `kind` | string | optional (find) | (all) | Filter by kind: "memory", "note", "decision", "convention", "gotcha", "policy" |
| `topic` | string | optional (find) | (all) | Filter by topic: "auth", "database", "api", "caching", etc. |
| `tags` | string or string[] | optional (find) | (all) | Filter by tags: ["security", "sql", ...] |
| `priority_min` | int | optional (find) | 1 | Minimum priority threshold (1-5) |
| `limit` | int | optional | 10 | Max results to return |

### Family 5: Batch Tools
**Applies to:** `batch_search`, `batch_symbol_graph`, `batch_graph_query`

**Standard Parameters (Shared across all queries):**

| Parameter | Type | Purpose |
|-----------|------|---------|
| `searches` / `queries` | array | Array of individual search/query specs (max 10 items) |
| `collection` | string | Shared default collection for all queries |
| `language` | string | Shared default language filter |
| `under` | string | Shared default path prefix |
| `limit` | int | Shared default result limit |
| `output_format` | string | "json" or "toon" for all results |

**Per-Search Overrides:**
Each item in `searches` / `queries` can override ANY shared parameter.

Example: `searches[0]` has different `limit` than `searches[1]`

### Family 6: Cross-Repo & Admin Tools
**Applies to:** `cross_repo_search`, `qdrant_status`, `qdrant_list`, `set_session_defaults`

**Standard Parameters:**

| Tool | Parameters |
|------|------------|
| `cross_repo_search` | `query`, `collection`, `target_repos`, `discover`, `trace_boundary`, `boundary_key` |
| `qdrant_status` / `qdrant_list` | (no parameters) |
| `set_session_defaults` | `collection`, `language`, `under`, `output_format`, `limit` |

---

## Unified Search: search (RECOMMENDED DEFAULT)

**Use `search` as your PRIMARY tool.** It auto-detects query intent and routes to the best specialized tool. No need to choose between 15+ tools.

```json
{
  "query": "authentication middleware"
}
```

Returns:
```json
{
  "ok": true,
  "intent": "search",
  "confidence": 0.92,
  "tool": "repo_search",
  "result": {
    "results": [...],
    "total": 8
  },
  "plan": ["detect_intent", "dispatch_repo_search"],
  "execution_time_ms": 245
}
```

**What it handles automatically:**
- Code search ("find auth middleware") -> routes to `repo_search`
- Q&A ("how does caching work?") -> routes to `context_answer`
- Test discovery ("tests for payment") -> routes to `search_tests_for`
- Config lookup ("database settings") -> routes to `search_config_for`
- Symbol queries ("who calls authenticate") -> routes to `symbol_graph`
- Import tracing ("what imports CacheManager") -> routes to `search_importers_for`

**Override parameters** (all optional):
```json
{
  "query": "error handling patterns",
  "limit": 5,
  "language": "python",
  "under": "src/api/",
  "include_snippet": true
}
```

**When to use `search`:**
- You're unsure which specialized tool to use
- You want intent auto-detection (routing to repo_search, context_answer, symbol_graph, tests, etc.)
- Acceptable latency overhead: ~50-100ms for routing + tool execution
- You're doing exploratory queries where routing overhead is negligible

**When NOT to use `search`:**
- You know you need raw code results (use `repo_search` directly)
- Time is critical (<100ms target) and routing overhead matters
- You're in a tight loop doing 10+ sequential searches (use `batch_search` instead)

**Routing Performance:**
- Intent detection: ~10-20ms
- Tool dispatch: ~5-10ms
- Total routing overhead: ~20-40ms typical, up to ~100ms worst-case
- For time-critical loops: skip routing with `repo_search` directly

**When to use specialized tools instead:**
- Cross-repo search -> `cross_repo_search`
- Multiple independent searches -> `batch_search` (N searches in one call, ~75% token savings)
- Memory storage/retrieval -> `memory_store`, `memory_find`
- Admin/diagnostics -> `qdrant_status`, `qdrant_list`
- Pattern matching (structural) -> `pattern_search`

**When to use `repo_search` instead of `search`:**
- **Full control over filters**: You know exactly what you're searching for and want to apply specific language, path, or symbol filters without auto-detection overhead
  - Example: "In a polyglot repo, I need Python code only" → use `repo_search` with `language="python"` to avoid search's auto-detected `language=javascript`
  - Example: "Find only test files matching a pattern" → use `repo_search` with `path_glob="**/test_*.py"` directly
- **Speed-critical queries** (<100ms target): You can't afford the ~20-40ms routing overhead
  - Example: Time-sensitive tool loops where each query must complete in <50ms
- **Complex filter combinations**: You need `language` + `under` + `not_glob` together, not guessed by auto-detection
- **Guaranteed exact behavior**: You want reproducible results without routing confidence variations (search routing confidence varies 0.6-0.95)
- **Known tool type**: You already know you need code results (not Q&A, tests, configs, or symbols) so routing is wasted

**Example: When search guesses wrong:**
```
SEARCH (auto-routes, may detect wrong intent):
query: "authenticate in FastAPI"
confidence: 0.75
intent: "Q&A - what does authenticate do in FastAPI?"
→ routes to context_answer, returns explanation instead of code

REPO_SEARCH (explicit, predictable):
query: "authenticate"
language: "python"
under: "src/auth/"
→ returns code implementations in src/auth/ only, no routing overhead
```

## Routing Overhead: When It Matters

**Latency Impact of Using `search` vs `repo_search` directly:**

| Scenario | search Latency | repo_search Latency | Routing Cost | Use search? |
|----------|-----------------|---------------------|--------------|-------------|
| One exploratory query | ~150-200ms | ~80-100ms | ~70-100ms | YES (worth it for auto-routing) |
| 3 independent queries, sequential | ~450-600ms | ~240-300ms | ~210-300ms | NO (use batch_search instead) |
| Time-critical query (<50ms) | Can miss deadline | ~80-100ms | ❌ Unacceptable | NO (use repo_search) |
| Tight loop (20+ queries) | ~3000-4000ms | ~1600-2000ms | ~1400-2000ms | NO (use batch_search) |

**Decision Criteria:**

- **Use `search`** when: One-off query, exploratory, unsure which tool, latency <200ms is acceptable
- **Use `repo_search`** when: Speed <100ms required, complex filter combo needed, tight loop (use batch_search if >2 queries), know you need code (not Q&A)
- **Use `batch_search`** when: 2+ independent code searches to reduce routing overhead by 75-85% per batch

**Real-world example - Interactive AI assistant loop:**
```
Bad (repeated routing overhead):
for query in user_queries:  # 5 queries
    result = search(query)  # ~70-100ms routing × 5 = 350-500ms wasted

Good (one batch call):
results = batch_search([query1, query2, query3, query4, query5])  # Routing once, ~25ms × 5 = 125ms
# Saves ~300ms+ per iteration
```

## Primary Search: repo_search

Use `repo_search` (or its alias `code_search`) for direct code lookups when you need full control. Reranking is ON by default.

```json
{
  "query": "database connection handling",
  "limit": 10,
  "include_snippet": true,
  "context_lines": 3
}
```

Returns:
```json
{
  "results": [
    {"score": 3.2, "path": "src/db/pool.py", "symbol": "ConnectionPool", "start_line": 45, "end_line": 78, "snippet": "..."}
  ],
  "total": 8,
  "used_rerank": true
}
```

**Multi-query for better recall** - pass a list to fuse results:
```json
{
  "query": ["auth middleware", "authentication handler", "login validation"]
}
```

**Apply filters** to narrow results:
```json
{
  "query": "error handling",
  "language": "python",
  "under": "src/api/",
  "not_glob": ["**/test_*", "**/*_test.*"]
}
```

**Search across repos** (same collection):
```json
{
  "query": "shared types",
  "repo": ["frontend", "backend"]
}
```
Use `repo: "*"` to search all indexed repos.

**Search across repos** (separate collections — use `cross_repo_search`):
```json
// cross_repo_search
{"query": "shared types", "target_repos": ["frontend", "backend"]}
// With boundary tracing for cross-repo flow discovery
{"query": "login submit", "trace_boundary": true}
```

### Available Filters

- `language` - Filter by programming language
- `under` - Path prefix (e.g., "src/api/")
- `path_glob` - Include patterns (e.g., ["**/*.ts", "lib/**"])
- `not_glob` - Exclude patterns (e.g., ["**/test_*"])
- `symbol` - Symbol name match
- `kind` - AST node type (function, class, etc.)
- `ext` - File extension
- `repo` - Repository filter for multi-repo setups
- `case` - Case-sensitive matching

## Batch Search: batch_search

Run N independent `repo_search` calls in a single MCP tool invocation. Reduces token overhead by ~75-85% compared to sequential calls.

**Token Savings & Latency Metrics:**

| N Searches | Token Savings | Sequential Latency | Batch Latency | Worth Batching? |
|------------|---------------|--------------------|---------------|-----------------|
| 1 | 0% | ~100ms | N/A | N/A |
| 2 | ~40% | ~180-200ms | ~150-160ms | ✅ YES (save 30-40ms, 40% tokens) |
| 3 | ~55% | ~270-300ms | ~180-200ms | ✅ YES (save 90-100ms, 55% tokens) |
| 5 | ~70% | ~450-500ms | ~220-250ms | ✅ YES (save 250ms, 70% tokens) |
| 10 | ~75% | ~900-1000ms | ~300-350ms | ✅ YES (save 600ms, 75% tokens) |

**Decision Rule**: Always use `batch_search` when you have 2+ independent code searches. The latency savings alone (30-100ms faster) justify batching, plus you save ~40-75% tokens.

```json
{
  "searches": [
    {"query": "authentication middleware", "limit": 5},
    {"query": "rate limiting implementation", "limit": 5},
    {"query": "error handling patterns"}
  ],
  "compact": true,
  "output_format": "toon"
}
```

Returns:
```json
{
  "ok": true,
  "batch_results": [result_set_0, result_set_1, result_set_2],
  "count": 3,
  "elapsed_ms": 245
}
```

Each `result_set` has the same schema as `repo_search` output.

**Shared parameters** (applied to all searches unless overridden per-search):
- `collection`, `output_format`, `compact`, `limit`, `language`, `under`, `repo`, `include_snippet`, `rerank_enabled`

**Per-search overrides**: Each entry in `searches` can include any `repo_search` parameter to override the shared defaults.

**Limits**: Maximum 10 searches per batch.

**When to use `batch_search` vs multiple `search` calls:**
- Use `batch_search` when you have 2+ independent code searches and want to minimize token usage and round-trips
- Use individual `search` calls when you need intent routing (Q&A, symbol graph, etc.) or when searches depend on each other's results

## Simple Lookup: info_request

Use `info_request` for natural language queries with minimal parameters:

```json
{
  "info_request": "how does user authentication work"
}
```

Add explanations:
```json
{
  "info_request": "database connection pooling",
  "include_explanation": true
}
```

## Q&A with Citations: context_answer

Use `context_answer` when you need an LLM-generated explanation grounded in code:

```json
{
  "query": "How does the caching layer invalidate entries?",
  "budget_tokens": 2000
}
```

Returns an answer with file/line citations. Use `expand: true` to generate query variations for better retrieval.

## Pattern Search: pattern_search (Optional)

> **Note:** This tool may not be available in all deployments. If pattern detection is disabled, calls return `{"ok": false, "error": "Pattern search module not available"}`.

Find structurally similar code patterns across all languages. Accepts **either** code examples **or** natural language descriptions—auto-detects which.

**Code example query** - find similar control flow:
```json
{
  "query": "for i in range(3): try: ... except: time.sleep(2**i)",
  "limit": 10,
  "include_snippet": true
}
```

**Natural language query** - describe the pattern:
```json
{
  "query": "retry with exponential backoff",
  "limit": 10,
  "include_snippet": true
}
```

**Cross-language search** - Python pattern finds Go/Rust/Java equivalents:
```json
{
  "query": "if err != nil { return err }",
  "language": "go",
  "limit": 10
}
```

**Explicit mode override** - force code or description mode:
```json
{
  "query": "error handling",
  "query_mode": "description",
  "limit": 10
}
```

**Key parameters:**
- `query` - Code snippet OR natural language description
- `query_mode` - `"code"`, `"description"`, or `"auto"` (default)
- `language` - Language hint for code examples (python, go, rust, etc.)
- `limit` - Max results (default 10)
- `min_score` - Minimum similarity threshold (default 0.3)
- `include_snippet` - Include code snippets in results
- `context_lines` - Lines of context around matches
- `aroma_rerank` - Enable AROMA structural reranking (default true)
- `aroma_alpha` - Weight for AROMA vs original score (default 0.6)
- `target_languages` - Filter results to specific languages

**Returns:**
```json
{
  "ok": true,
  "results": [...],
  "total": 5,
  "query_signature": "L2_2_B0_T2_M0",
  "query_mode": "code",
  "search_mode": "aroma"
}
```

The `query_signature` encodes control flow: `L` (loops), `B` (branches), `T` (try/except), `M` (match).

## Specialized Search Tools

**search_tests_for** - Find test files:
```json
{"query": "UserService", "limit": 10}
```

**search_config_for** - Find config files:
```json
{"query": "database connection", "limit": 5}
```

**search_callers_for** - Find callers of a symbol:
```json
{"query": "processPayment", "language": "typescript"}
```

**search_importers_for** - Find importers:
```json
{"query": "utils/helpers", "limit": 10}
```

**symbol_graph** - Symbol graph navigation (callers / callees / definition / importers / subclasses / base classes):

**Query types:**
| Type | Description |
|------|-------------|
| `callers` | Who calls this symbol? |
| `callees` | What does this symbol call? |
| `definition` | Where is this symbol defined? |
| `importers` | Who imports this module/symbol? |
| `subclasses` | What classes inherit from this symbol? |
| `base_classes` | What classes does this symbol inherit from? |

**Examples:**
```json
{"symbol": "ASTAnalyzer", "query_type": "definition", "limit": 10}
```
```json
{"symbol": "get_embedding_model", "query_type": "callers", "under": "scripts/", "limit": 10}
```
```json
{"symbol": "qdrant_client", "query_type": "importers", "limit": 10}
```
```json
{"symbol": "authenticate", "query_type": "callees", "limit": 10}
```
```json
{"symbol": "BaseModel", "query_type": "subclasses", "limit": 20}
```
```json
{"symbol": "MyService", "query_type": "base_classes"}
```
- Supports `language`, `under`, `depth`, and `output_format` like other tools.
- Use `depth=2` or `depth=3` for multi-hop traversals (callers of callers).
- If there are no graph hits, it falls back to semantic search.
- **Note**: Results are "hydrated" with ~500-char source snippets for immediate context.

**graph_query** - Advanced graph traversals and impact analysis (available to all SaaS users):

**Query types:**
| Type | Description |
|------|-------------|
| `callers` | Direct callers of this symbol |
| `callees` | Direct callees of this symbol |
| `transitive_callers` | Multi-hop callers (up to depth) |
| `transitive_callees` | Multi-hop callees (up to depth) |
| `impact` | What would break if I change this symbol? |
| `dependencies` | Combined calls + imports |
| `definition` | Where is this symbol defined? |
| `cycles` | Detect circular dependencies involving this symbol |

**Examples:**
```json
{"symbol": "UserService", "query_type": "impact", "depth": 3}
```
```json
{"symbol": "auth_module", "query_type": "cycles"}
```
```json
{"symbol": "processPayment", "query_type": "transitive_callers", "depth": 2, "limit": 20}
```
- Supports `language`, `under`, `depth`, `limit`, `include_paths`, and `output_format`.
- Use `include_paths: true` to get full traversal paths in results.
- Use `depth` to control how many hops to traverse (default varies by query type).
- **Note**: `symbol_graph` is always available (Qdrant-backed). `graph_query` provides advanced Memgraph-backed traversals and is available to all SaaS users.

**Comparison: symbol_graph vs graph_query**

| Feature | symbol_graph | graph_query |
|---------|--------------|------------|
| Availability | Always (Qdrant-backed) | SaaS/Enterprise (Memgraph-backed) |
| Performance | ~2-5ms per query | ~50-200ms per query |
| Supported Relationships | callers, callees, definition, importers, subclasses, base_classes | All symbol_graph + impact, cycles, transitive_* |
| Max Depth | up to 3 | up to 5+ |
| Best For | Direct relationships, exploratory queries | Impact analysis, dependency chains, circular detection |
| Fallback When Unavailable | Falls back to semantic search | N/A (use symbol_graph instead) |
| Latency-Critical Loops | ✅ YES (fast) | ❌ NO (slower) |

**Decision Guide:**
- **Use symbol_graph** for: direct callers/callees/definitions, inheritance queries, when you need speed, always as first stop
- **Use graph_query** for: impact analysis ("what breaks?"), cycle detection, transitive chains, when available and you need depth >3

**search_commits_for** - Search git history:
```json
{"query": "fixed authentication bug", "limit": 10}
```

**Predict co-changing files** (predict_related mode):
```json
{"path": "src/api/auth.py", "predict_related": true, "limit": 10}
```
Returns ranked files that historically co-change with the given path, along with the most relevant commit message explaining why.

**change_history_for_path** - File change summary:
```json
{"path": "src/api/auth.py", "include_commits": true}
```

## Memory: Store and Recall Knowledge

Memory tools allow you to persist team knowledge, architectural decisions, and findings for later retrieval across sessions.

### Memory Workflow: Store → Retrieve → Reuse

**Phase 1: During Exploration (Session 1)**
As you discover important patterns, decisions, or findings, store them for future reference:

```json
{
  "memory_store": {
    "information": "Auth service uses JWT tokens with 24h expiry. Refresh tokens last 7 days. Stored in Redis with LRU eviction.",
    "metadata": {
      "kind": "decision",
      "topic": "auth",
      "priority": 5,
      "tags": ["security", "jwt", "session-management"]
    }
  }
}
```

**Phase 2: In Later Sessions**
Retrieve and reuse stored knowledge by similarity:

```json
{
  "memory_find": {
    "query": "token expiration policy",
    "topic": "auth",
    "limit": 5
  }
}
```

Returns the exact note stored in Phase 1, plus any other auth-related memories.

**Phase 3: Blend Code + Memory**
When you want BOTH code search results AND stored team knowledge:

```json
{
  "context_search": {
    "query": "authentication flow",
    "include_memories": true,
    "per_source_limits": {"code": 6, "memory": 3}
  }
}
```

Returns: 6 code snippets + 3 memory notes, all ranked by relevance.

### Timeline and Persistence

| Property | Behavior |
|----------|----------|
| **Searchability** | Memories searchable immediately after `memory_store` (indexing is instant) |
| **Persistence** | Memories persist across sessions indefinitely (durable storage) |
| **Scope** | Org/workspace scoped: one team's memories don't leak to another |
| **Latency** | ~100ms per `memory_find` query (same as code search) |
| **Storage** | Embedded in same Qdrant collection as code, but logically isolated |

### Real-World Example: Session Continuity

**Session 1 (Day 1) - Discovery:**
```
Context: Investigating why JWT refresh tokens sometimes expire unexpectedly

→ memory_store(
    information="Found: RefreshTokenManager.py line 89 uses session.expire_in instead of constants.REFRESH_TTL. This was a bug introduced in PR #1234 where the constant was 7 days but the session value was hardcoded to 3 days. The mismatch causes premature expiration.",
    metadata={"kind": "gotcha", "topic": "auth", "tags": ["bug", "jwt"], "priority": 4}
  )
```

**Session 2 (Day 5) - Troubleshooting a Similar Issue:**
```
→ memory_find(query="refresh token expiration problem", topic="auth")

Response: Found Session 1's note about the RefreshTokenManager bug, plus similar findings about token TTL misconfigurations.

→ User goes directly to line 89 of RefreshTokenManager.py and verifies the fix status.
```

Result: Problem solved in 2 minutes instead of 30 minutes of debugging.

### When to Store What

| Memory Kind | Use Case | Example |
|-------------|----------|---------|
| `decision` | Architectural choices and their rationale | "We chose JWT over sessions because stateless scaling" |
| `gotcha` | Subtle bugs or trap conditions | "RefreshTokenManager line 89 has TTL mismatch" |
| `convention` | Team patterns and standards | "All API responses use envelope pattern with status/data/errors" |
| `note` | General findings or context | "Auth service was moved to separate repo last month" |
| `policy` | Compliance or operational rules | "Session tokens must be rotated every 24h per SOC2" |

### Integration with Code Search

**Pattern 1: Pure Code Search**
```json
{"search": "authentication validation"}
```
Returns: code snippets only. Fast, no memory overhead.

**Pattern 2: Code + Memory Blend**
```json
{
  "context_search": {
    "query": "authentication validation",
    "include_memories": true,
    "per_source_limits": {"code": 5, "memory": 2}
  }
}
```
Returns: 5 code snippets + 2 relevant memory notes (team insights about auth validation patterns).

**Pattern 3: Memory Only**
```json
{"memory_find": {"query": "authentication patterns", "limit": 10}}
```
Returns: stored team knowledge about auth, useful for onboarding or architecture review.

### Common Patterns

**Team Onboarding:**
- New engineer joins → `memory_find(query="project architecture", topic="architecture")`
- Retrieves all stored architectural decisions in one place
- Much faster than reading scattered code comments

**Incident Response:**
- Production auth bug occurs
- → `memory_find(query="auth failures", priority_min=3)`
- Retrieves gotchas, prior incidents, and known traps
- Faster root-cause diagnosis

**Code Review Efficiency:**
- Reviewer checks PR modifying auth module
- → `context_search(query="authentication standards", include_memories=true)`
- Sees both current code AND team conventions/policies
- Makes more informed review decisions

### Error Cases and Recovery

| Error | Cause | Recovery |
|-------|-------|----------|
| "No results from memory_find" | Query too specific or memories not yet stored | Broaden query, check metadata filters (topic, tags, kind) |
| "Memory not found in next session" | Wrong workspace/collection or stale cache | Verify workspace matches, run `qdrant_list` to confirm collection |
| "include_memories=true returns only code" | Memory store empty for this workspace | Start storing with `memory_store` - next session will have memories |
| "Duplicate memories with same info" | Same finding discovered twice | Use `memory_find` with topic/tags filter, consolidate via note |

## Admin and Diagnostics

**qdrant_status** - Check index health:
```json
{}
```

**qdrant_list** - List all collections:
```json
{}
```

**embedding_pipeline_stats** - Get cache efficiency, bloom filter stats, pipeline performance:
```json
{}
```

**set_session_defaults** - Set defaults for session:
```json
{"collection": "my-project", "language": "python"}
```

### Deployment Mode Capabilities

> **SaaS Mode:** In SaaS deployments, indexing is handled automatically by the VS Code extension upload service. The tools below marked "Self-Hosted Only" are **not available** in SaaS mode. All search, symbol graph, memory, and session tools work normally.

**Self-Hosted Only Tools** (not available in SaaS):

| Tool | Purpose | When to Use |
|------|---------|-------------|
| `qdrant_index_root` | Index entire workspace | Initial indexing or after major codebase reorg |
| `qdrant_index` | Index subdirectory | Incremental indexing of specific folders |
| `qdrant_prune` | Remove stale entries | Clean up entries from deleted files |

### Tool Availability Matrix

Which tools are available in which deployment modes:

| Tool Category | Tool | SaaS | Self-Hosted | Enterprise |
|---|---|---|---|---|
| **Search** | `search` | ✅ | ✅ | ✅ |
| | `repo_search` / `code_search` | ✅ | ✅ | ✅ |
| | `cross_repo_search` | ✅ | ✅ | ✅ |
| | `batch_search` | ✅ | ✅ | ✅ |
| **Search (Specialized)** | `info_request` | ✅ | ✅ | ✅ |
| | `context_answer` | ✅ | ✅ | ✅ |
| | `search_tests_for` | ✅ | ✅ | ✅ |
| | `search_config_for` | ✅ | ✅ | ✅ |
| | `search_callers_for` | ✅ | ✅ | ✅ |
| | `search_importers_for` | ✅ | ✅ | ✅ |
| | `search_commits_for` | ✅ | ✅ | ✅ |
| | `change_history_for_path` | ✅ | ✅ | ✅ |
| | `pattern_search` (if enabled) | ✅* | ✅* | ✅* |
| **Symbol Graph** | `symbol_graph` | ✅ | ✅ | ✅ |
| | `batch_symbol_graph` | ✅ | ✅ | ✅ |
| | `graph_query` | ✅ (limited)** | ✅ | ✅ |
| | `batch_graph_query` | ✅ (limited)** | ✅ | ✅ |
| **Memory** | `memory_store` | ✅ | ✅ | ✅ |
| | `memory_find` | ✅ | ✅ | ✅ |
| | `context_search` | ✅ | ✅ | ✅ |
| **Session** | `set_session_defaults` | ✅ | ✅ | ✅ |
| | `expand_query` | ✅ | ✅ | ✅ |
| **Admin** | `qdrant_status` | ✅ | ✅ | ✅ |
| | `qdrant_list` | ✅ | ✅ | ✅ |
| | `embedding_pipeline_stats` | ✅ | ✅ | ✅ |
| | `qdrant_index_root` | ❌ | ✅ | ✅ |
| | `qdrant_index` | ❌ | ✅ | ✅ |
| | `qdrant_prune` | ❌ | ✅ | ✅ |

**Legend:**
- ✅ = Available
- ❌ = Not available
- ✅* = Pattern search available only if enabled during deployment
- ✅ (limited)** = SaaS graph_query has limited depth/performance vs Enterprise with dedicated Memgraph

### Choosing Your Deployment Mode

| Requirement | Best Fit |
|---|---|
| Automatic indexing via VS Code | **SaaS** |
| Manual control over indexing pipeline | **Self-Hosted** |
| Advanced graph queries (cycles, impact analysis) | **Self-Hosted** or **Enterprise** |
| High-performance graph traversal | **Enterprise** (dedicated Memgraph) |
| Cost-sensitive small team | **SaaS** (pay per upload) |
| Large codebase with frequent indexing | **Self-Hosted** (unlimited reindex) |

## Error Handling and Recovery

Tools return structured errors via `error` field or `ok: false` flag. Below are common errors and recovery steps by category.

### Search Tools (search, repo_search, batch_search, info_request)

| Error | HTTP 400? | Cause | Recovery Steps |
|-------|-----------|-------|-----------------|
| `"Collection not found"` | Yes | Collection doesn't exist, workspace hasn't been indexed, or collection was deleted | 1. Run `qdrant_list()` to verify available collections<br>2. Check workspace name in config matches indexed name<br>3. If missing: re-upload workspace to indexing service<br>4. If collection exists but stale: wait for background refresh or trigger reindex |
| `"Invalid language filter"` | Yes | `language` parameter has invalid value | Use only valid language codes: "python", "typescript", "go", "rust", "java", etc.<br>Check qdrant_status for supported languages |
| `"Timeout during rerank"` | No (504) | Reranking took too long (default 5s timeout) | Set `rerank_enabled: false` to skip reranking<br>OR set `rerank_timeout_ms: 10000` for longer timeout<br>OR reduce `limit` to speed up reranking |
| `"Empty results"` | No (200) | Query too specific, collection not fully indexed, or no matches exist | 1. Broaden query (remove filters, use more general terms)<br>2. Check `language` filter is correct<br>3. Run `qdrant_status` to see point count<br>4. If points=0: indexing is incomplete, wait and retry |
| `"Query too long"` | Yes | Query exceeds 400 chars or 50 words | Shorten query or split into multiple searches |
| `"Syntax error in path_glob"` | Yes | Invalid glob pattern in `path_glob` or `not_glob` | Check glob syntax: valid wildcards are `*` (any), `**` (any directories), `?` (any single char) |

**Silent Failure Watches:**
- Empty results when expecting matches → check `under` path filter (may be excluding files)
- Results from wrong language → verify `language` parameter is set correctly
- Reranking disabled silently → check `rerank_timeout_ms` if you set custom timeout
- Wrong collection queried → session defaults may not match workspace (use `set_session_defaults` to "cd" into correct collection)

### Symbol Graph Tools (symbol_graph, batch_symbol_graph, graph_query)

| Error | Cause | Recovery Steps |
|-------|-------|-----------------|
| `"Symbol not found"` | Symbol doesn't exist, wrong name, or graph not indexed | 1. Verify exact symbol name using `repo_search(symbol="...")`<br>2. Check spelling and case sensitivity<br>3. If graph unavailable: use `repo_search` instead<br>4. For imported symbols: search with full module path |
| `"Graph unavailable / not ready"` | Memgraph backend not initialized (graph_query only) | Fall back to `symbol_graph` (always available)<br>graph_query requires SaaS/Enterprise plan with Neo4j/Memgraph |
| `"Depth too high"` | `depth` parameter exceeds max for this tool | Reduce `depth`: symbol_graph max 3, graph_query max 5+<br>For deeper chains, use multiple queries with results as input |
| `"Timeout during graph traversal"` | Graph query took too long | Reduce `depth`, reduce `limit`, or use smaller `under` path filter |

**Silent Failure Watches:**
- No callers found when method is clearly called → fuzzy fallback may have triggered, use repo_search to verify method exists
- Symbol seems undefined but code uses it → cross-module imports may not be resolved in graph yet

### Context Answer (LLM-powered explanation)

| Error | Cause | Recovery Steps |
|-------|-------|-----------------|
| `"Insufficient context"` | Retrieved code wasn't enough to answer question | 1. Rephrase question more specifically<br>2. Use `expand: true` to generate query variations<br>3. Increase `budget_tokens` for deeper retrieval<br>4. Use `repo_search` first to verify code exists |
| `"Timeout during retrieval or generation"` | LLM generation or retrieval took >60s | Set `rerank_enabled: false` to skip reranking<br>Reduce `budget_tokens` for faster shallow retrieval<br>Ask simpler question requiring less context |
| `"Budget exceeded"` | Generated answer would use >budget_tokens | Increase `budget_tokens` or ask more focused question |

### Memory Tools (memory_store, memory_find)

| Error | Cause | Recovery Steps |
|-------|-------|-----------------|
| `"Memory not found"` | No memories match query or metadata filters | 1. Broaden query (more general terms)<br>2. Remove metadata filters (topic, kind, priority_min)<br>3. Check if memories exist: `memory_find(query="*")`<br>4. Verify workspace/collection (memories are org-scoped) |
| `"Storage failure"` | Backend couldn't persist memory | Retry `memory_store` - likely transient<br>Check `qdrant_status` for cluster health |
| `"Duplicate memory detected"` (warning) | Similar memory already exists with higher priority | Review existing memories first: `memory_find(query="...", topic="...")`<br>Consolidate if same information |

### Batch Tools (batch_search, batch_symbol_graph)

| Error | Cause | Recovery Steps |
|-------|-------|-----------------|
| `"Too many searches"` | `searches` / `queries` array > 10 items | Split into multiple batch calls (max 10 per call)<br>If independent: use sequential calls (lower token savings but more granular)<br>If dependent: must be sequential anyway |
| `"Mixed error in batch"` | Some queries succeeded, others failed | Check individual `batch_results` array for per-query `ok: false`<br>Failed queries return error details in `batch_results[i].error`<br>Successful queries still have results in `batch_results[i].results` |
| `"Timeout on any query"` | One query in the batch timed out | Set `rerank_enabled: false` in that query's override<br>Reduce `limit` for slow queries<br>Consider running that query separately |

### Cross-Repo & Discovery

| Error | Cause | Recovery Steps |
|-------|-------|-

…(truncated)
