Retrieval Strategy Selector
The Problem: Which Retrieval Strategy?
Agent memory is only useful if you retrieve the right data. Asking the wrong way loses critical context:
- Semantic only: You search for "user felt anxious" but memory stored "feeling of dread" as a keyword phrase. Miss it.
- Keyword only: You search for "trading strategy" but memory stored similar concepts under different words. Semantic search would find them; keyword won't.
- No time filtering: You retrieve "agent decision" and get a decision from 6 months ago, irrelevant to today's context.
- No type filtering: You retrieve and get 100 results when you only want error outcomes, wasting tokens.
Brain offers 5 retrieval strategies, each optimized for a query type. This guide shows when to use each.
Decision Flowchart
START: What are you trying to retrieve?
├─ "Recent context (last 24 hours)"? → TEMPORAL
├─ "Exact phrase or keyword"? → LEXICAL
├─ "Category or type (errors, decisions)"? → TYPE-FILTERED
├─ "Relationships or causal chains"? → GRAPH
├─ "Conceptual match (similar ideas)"? → SEMANTIC
└─ "Everything above"? → HYBRID (Semantic + Lexical)Retrieval Strategies
1. Semantic Retrieval
Use when: Concept matching, idea similarity, paraphrasing.
Example queries:
- "How did the user feel about the last meeting?"
- "What trading strategies worked well?"
- "Similar customer complaints we've seen?"
How it works: Converts query to embedding, finds memories with similar embeddings.
Strengths:
- Paraphrase-tolerant (query "felt sad" matches memory "depressed mood")
- Multi-concept matching ("trading risk management" matches various risk concepts)
- Domain-agnostic (works across any domain)
Weaknesses:
- Ignores exact phrases ("find the word 'error'")
- Slow for huge indexes (>100M vectors)
TypeScript example:
import { Brain } from "brain-sdk";
const brain = new Brain({ apiKey: process.env.BRAIN_API_KEY });
// Semantic: find conceptually similar memories
const results = await brain.retrieve({
agentId: "support_agent_1",
query: "How did the customer feel?",
topK: 5,
mode: "semantic",
});
console.log(results); // Finds memories with sentiment concepts, even if worded differently2. Temporal Retrieval
Use when: Time-based filtering, recency, session boundaries.
Example queries:
- "All decisions made in the last 24 hours"
- "Events from this month"
- "Trading outcomes between 9am–5pm"
How it works: Filters memories by timestamp, then ranks by recency or relevance.
Strengths:
- Precise time windows (no guessing)
- Combines time + relevance (can add keyword/semantic on top)
- Efficient even for large memory stores
Weaknesses:
- Requires
timestampmetadata - Not for fuzzy time ("around last week")
TypeScript example:
import { Brain } from "brain-sdk";
import { subHours } from "date-fns";
const brain = new Brain({ apiKey: process.env.BRAIN_API_KEY });
// Temporal: memories from the last 24 hours
const oneDayAgo = subHours(new Date(), 24).toISOString();
const results = await brain.retrieve({
agentId: "trader_1",
query: "trading outcomes", // Optional: combine with keyword
filters: {
timestamp: { $gte: oneDayAgo },
},
topK: 10,
mode: "temporal",
});
console.log(results); // All trading outcomes in last 24 hours, ranked by recency3. Lexical Retrieval
Use when: Exact phrases, keywords, boolean logic.
Example queries:
- "Find the word 'error' in memories"
- "All memories tagged 'critical'"
- "Customer name contains 'Smith'"
How it works: Full-text search (BM25), tokenizes and matches terms.
Strengths:
- Exact phrase matching (no approximation)
- Fast for keyword searches
- Boolean logic support (AND, OR, NOT)
Weaknesses:
- Requires exact words or known terminology
- Misses paraphrases ("felt sad" ≠ "depressed")
TypeScript example:
import { Brain } from "brain-sdk";
const brain = new Brain({ apiKey: process.env.BRAIN_API_KEY });
// Lexical: exact keyword matching
const results = await brain.retrieve({
agentId: "support_agent_1",
query: "error AND timeout", // Boolean logic supported
topK: 10,
mode: "lexical",
});
console.log(results); // Only memories containing both "error" and "timeout"4. Type-Filtered Retrieval
Use when: Category filtering, memory types, outcome filtering.
Example queries:
- "All failed trades only"
- "Decisions made by the user (exclude observations)"
- "Error events, not warnings"
How it works: Filters by type metadata field, then retrieves within that type.
Strengths:
- Clean categorical filtering
- Reduces noise (exclude irrelevant memory types)
- Efficient metadata queries
Weaknesses:
- Requires structured
typemetadata - Can't filter on undefined types
TypeScript example:
import { Brain } from "brain-sdk";
const brain = new Brain({ apiKey: process.env.BRAIN_API_KEY });
// Type-filtered: retrieve only decision memories
const results = await brain.retrieve({
agentId: "trader_1",
query: "strategies", // Optional semantic/keyword query
filters: {
type: "decision", // Structured type filter
},
topK: 5,
});
console.log(results); // Only memories where type="decision"5. Graph Retrieval
Use when: Relationships, causal chains, entailment.
Example queries:
- "What caused this error?"
- "What did the agent decide as a result of this observation?"
- "Trace the causal chain leading to this outcome"
How it works: Traverses relationships in graph (edge: "causedBy", "resultedIn", "leadsTo").
Strengths:
- Captures causality (not just similarity)
- Multi-hop reasoning (A → B → C)
- Avoids spurious correlations
Weaknesses:
- Requires graph relationships (edges) in schema
- Slower for deep graphs
TypeScript example:
import { Brain } from "brain-sdk";
const brain = new Brain({ apiKey: process.env.BRAIN_API_KEY });
// Graph: retrieve causal chain
const results = await brain.retrieve({
agentId: "trader_1",
query: "root cause of loss on 2026-05-12",
topK: 5,
mode: "graph",
graphFilters: {
// Traverse "causedBy" relationships
relationshipType: "causedBy",
maxHops: 2, // Up to 2 hops away
},
});
console.log(results); // Causal chain: Trade Loss ← Strategy A ← Market Regime ← ObservationWhen to Use Each: Decision Table
| Scenario | Strategy | Example |
|---|---|---|
| "What did the user like?" (paraphrasing ok) | Semantic | Query "prefer", Memory "enjoy" → Match ✓ |
| "Last 10 decisions" (time-bounded) | Temporal | Filter by timestamp > now - 24h, rank by recency |
| "Find error logs" (exact keyword) | Lexical | Query "error", Memory "error: 500" → Match ✓ |
| "Only failed trades" (category filter) | Type-Filtered | Filter by type = "trade_outcome" AND outcome = "loss" |
| "Why did this fail?" (causality) | Graph | Start at "Trade Loss", follow "causedBy" edges |
| "Everything: recent + semantic + keyword" | Hybrid | Temporal window + semantic + lexical in one query |
Hybrid Retrieval (Most Common)
For most agent loops, use hybrid: combines semantic + lexical + temporal. It's the safest default.
TypeScript:
const results = await brain.retrieve({
agentId: "agent_1",
query: "user preference coffee", // Semantic + lexical
filters: {
timestamp: { $gte: subDays(new Date(), 7) }, // Temporal
type: "preference", // Type-filtered
},
topK: 5,
mode: "hybrid",
});This retrieves memories that are:
- Semantically similar to "user preference coffee"
- Contain keywords related to your query
- Created in the last 7 days
- Tagged as type "preference"
Implementation Examples
Trading Agent: Market Context
import { Brain } from "brain-sdk";
const brain = new Brain({ apiKey: process.env.BRAIN_API_KEY });
async function getMarketContext(
agentId: string,
symbol: string,
timeWindowHours: number = 24
) {
// 1. Temporal + Type: Recent market observations
const oneDayAgo = new Date(
Date.now() - timeWindowHours * 60 * 60 * 1000
).toISOString();
const marketFacts = await brain.retrieve({
agentId,
query: `Market condition for ${symbol}`,
filters: {
timestamp: { $gte: oneDayAgo },
type: "market_observation",
},
topK: 5,
mode: "temporal",
});
// 2. Semantic: Similar past market conditions
const similarConditions = await brain.retrieve({
agentId,
query: `${symbol} bull market resistance level`,
filters: { type: "market_fact" },
topK: 3,
mode: "semantic",
});
// 3. Lexical + Type: Recent error events
const recentErrors = await brain.retrieve({
agentId,
query: "error OR warning",
filters: {
timestamp: { $gte: oneDayAgo },
type: "error_event",
},
topK: 5,
mode: "lexical",
});
return {
recentConditions: marketFacts,
similarPastConditions: similarConditions,
recentErrors: recentErrors,
};
}Support Agent: Customer Sentiment
async function getCustomerContext(agentId: string, customerId: string) {
// 1. Semantic: Similar past interactions
const similarInteractions = await brain.retrieve({
agentId,
query: "customer complaint frustration",
filters: {
customerId,
type: "customer_interaction",
},
topK: 5,
mode: "semantic",
});
// 2. Temporal: Recent sentiment
const recentWeek = new Date(
Date.now() - 7 * 24 * 60 * 60 * 1000
).toISOString();
const recentSentiment = await brain.retrieve({
agentId,
query: "sentiment positive negative",
filters: {
customerId,
timestamp: { $gte: recentWeek },
type: "sentiment_signal",
},
topK: 3,
mode: "hybrid",
});
// 3. Graph: Root cause of last complaint
const rootCause = await brain.retrieve({
agentId,
query: customerId,
topK: 1,
mode: "graph",
graphFilters: {
relationshipType: "rootCauseOf",
maxHops: 2,
},
});
return {
similarPastComplaints: similarInteractions,
recentSentiment: recentSentiment,
rootCauses: rootCause,
};
}Performance & Latency
| Strategy | Latency (P99) | Best Index Size |
|---|---|---|
| Semantic | 100–200ms | <10M vectors |
| Temporal | 50–100ms | <100M |
| Lexical | 30–50ms | <100M |
| Type-Filtered | 10–50ms | Unlimited |
| Graph | 50–200ms (depends on depth) | <5M nodes |
| Hybrid | 100–200ms | <10M |
Implementation Checklist
- Define memory types you'll use (decision, observation, error, preference, etc.)
- Choose primary retrieval strategy based on agent loop (most: hybrid)
- Implement temporal filtering if you care about recency
- Add type metadata to all stored memories
- Test: retrieve queries and verify results include expected memories
- Monitor latency: ensure P99 <200ms for agent loop queries
- Iterate: A/B test strategies, measure retrieval quality
- Document: which memory types use which retrieval strategy
Next Steps
- Deep dive: See Five Retrievers for advanced filtering and query syntax
- Schema design: Read Schema Design Patterns for memory type conventions
- Architecture: Check Memory Architectures for end-to-end agent memory systems