` | Output format: pretty, json, yaml |
+| `--help` | Show help |
+| `--version` | Show version |
+
+## Interactive Explorer
+
+Launch the TUI explorer for visual navigation:
+
+```bash
+hindsight explore
+```
+
+## Example Workflow
+
+```bash
+# Configure API URL
+hindsight configure --api-url http://localhost:8888
+
+# Store some memories
+hindsight memory retain demo "Alice works at Google"
+hindsight memory retain demo "Bob is a data scientist"
+hindsight memory retain demo "Alice and Bob are colleagues"
+
+# Search memories
+hindsight memory recall demo "Who works with Alice?"
+
+# Generate a response
+hindsight memory reflect demo "What do you know about the team?"
+
+# Check bank profile
+hindsight bank profile demo
+```
+
+
+---
+
+
+## File: sdks/mcp.md
+
+# MCP Server
+
+Model Context Protocol server for AI assistants like Claude Desktop.
+
+## Setup
+
+The MCP server is included in the Hindsight API. When running the API with MCP enabled, it exposes MCP tools at `/mcp/{bank_id}/sse`.
+
+### Claude Desktop Configuration
+
+Add to `~/Library/Application Support/Claude/claude_desktop_config.json`:
+
+```json
+{
+ "mcpServers": {
+ "hindsight": {
+ "command": "npx",
+ "args": ["-y", "mcp-remote", "http://localhost:8888/mcp/my-bank-id/sse"]
+ }
+ }
+}
+```
+
+Replace `my-bank-id` with your memory bank ID.
+
+## Available Tools
+
+### retain
+
+Store a memory:
+
+```json
+{
+ "name": "retain",
+ "arguments": {
+ "content": "User prefers Python for data analysis",
+ "context": "preferences"
+ }
+}
+```
+
+**Parameters:**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `content` | string | yes | Memory content to store |
+| `context` | string | no | Category (default: 'general') |
+
+### recall
+
+Search memories:
+
+```json
+{
+ "name": "recall",
+ "arguments": {
+ "query": "What does the user do for work?"
+ }
+}
+```
+
+**Parameters:**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `query` | string | yes | Natural language search query |
+| `max_results` | integer | no | Max results (default: 10) |
+
+## Usage Example
+
+Once configured, Claude can use Hindsight naturally:
+
+**User**: "Remember that I prefer morning meetings"
+
+**Claude**: *Uses retain*
+
+> "I've noted that you prefer morning meetings."
+
+---
+
+**User**: "What do you know about my preferences?"
+
+**Claude**: *Uses recall*
+
+> "Based on our conversations, you prefer morning meetings and like Python for data analysis."
+
+
+---
+
+
+## File: cookbook/index.md
+
+# Cookbook
+
+Practical patterns and recipes for building with Hindsight.
+
+## Use Cases
+
+### [Per-User Memory](/cookbook/per-user-memory)
+
+The simplest pattern: give your agent persistent memory for each user. The agent remembers past conversations, preferences, and context across sessions.
+
+**Use when:** Building chatbots, personal assistants, or any 1:1 user-to-agent interaction.
+
+### [Support Agent with Shared Knowledge](/cookbook/support-agent-with-shared-knowledge)
+
+Build a support agent that combines per-user memory with shared product documentation. Users get personalized support while you index docs only once.
+
+**Use when:** Building multi-tenant support agents, RAG + memory applications, or any scenario needing user isolation with shared reference data.
+
+
+---
+
+
+## File: cookbook/per-user-memory.md
+
+# Per-User Memory
+
+The simplest pattern: give your agent persistent memory for each user. The agent remembers past conversations, user preferences, and context across sessions.
+
+## The Problem
+
+Without memory, every conversation starts from scratch:
+
+```
+Session 1: "I prefer dark mode and use Python"
+Session 2: "What's my preferred language?" → Agent doesn't know
+```
+
+## The Solution: One Bank Per User
+
+```
+┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
+│ User A Bank │ │ User B Bank │ │ User C Bank │
+│ │ │ │ │ │
+│ - Conversations│ │ - Conversations│ │ - Conversations│
+│ - Preferences │ │ - Preferences │ │ - Preferences │
+│ - Context │ │ - Context │ │ - Context │
+└─────────────────┘ └─────────────────┘ └─────────────────┘
+ │ │ │
+ 100% isolated 100% isolated 100% isolated
+```
+
+Each user gets their own memory bank. Complete isolation, simple mental model.
+
+## Implementation
+
+### 1. Create a Bank When User Signs Up
+
+```python
+from hindsight import HindsightClient
+
+client = HindsightClient()
+
+def on_user_signup(user_id: str):
+ client.create_bank(
+ bank_id=f"user-{user_id}",
+ name=f"Memory for {user_id}"
+ )
+```
+
+### 2. Manage Conversation Sessions
+
+Use `document_id` to group messages belonging to the same conversation. When you retain with the same `document_id`, Hindsight replaces the previous version (upsert behavior), keeping the memory up-to-date as the conversation evolves.
+
+```python
+
+
+class ConversationSession:
+ def __init__(self, user_id: str):
+ self.user_id = user_id
+ self.session_id = str(uuid.uuid4()) # Unique ID for this conversation
+ self.messages = []
+
+ def add_message(self, role: str, content: str):
+ self.messages.append({"role": role, "content": content})
+
+ async def save(self, client: HindsightClient):
+ """Save the entire conversation. Replaces previous version if session_id exists."""
+ await client.retain(
+ bank_id=f"user-{self.user_id}",
+ content=self.messages,
+ document_id=self.session_id # Same ID = upsert (replace old version)
+ )
+```
+
+### 3. Recall Context Before Responding
+
+```python
+async def get_context(user_id: str, query: str):
+ result = await client.recall(
+ bank_id=f"user-{user_id}",
+ query=query
+ )
+ return result.results
+```
+
+### 4. Complete Agent Loop
+
+```python
+async def handle_message(session: ConversationSession, user_message: str):
+ # 1. Add user message to session
+ session.add_message("user", user_message)
+
+ # 2. Recall relevant context from past conversations
+ context = await client.recall(
+ bank_id=f"user-{session.user_id}",
+ query=user_message
+ )
+
+ # 3. Build prompt with memory
+ prompt = f"""You are a helpful assistant with memory of past conversations.
+
+## What you remember about this user
+{format_results(context.results)}
+
+## Current conversation
+{format_messages(session.messages)}
+"""
+
+ # 4. Generate response
+ response = await llm.complete(prompt)
+
+ # 5. Add assistant response to session
+ session.add_message("assistant", response)
+
+ # 6. Save the updated conversation (upserts based on session_id)
+ await session.save(client)
+
+ return response
+```
+
+### 5. Starting a New Conversation
+
+```python
+# Each new conversation gets a new session with a unique ID
+session = ConversationSession(user_id="alice")
+
+# Multiple exchanges in the same conversation
+await handle_message(session, "Hi! I'm working on a Python project")
+await handle_message(session, "Can you help me with async/await?")
+
+# Start a new conversation later (new session_id)
+new_session = ConversationSession(user_id="alice")
+await handle_message(new_session, "Different topic today...")
+```
+
+## How Document ID Works
+
+The `document_id` parameter is key to managing evolving conversations:
+
+| Scenario | Behavior |
+|----------|----------|
+| First retain with `document_id="session_123"` | Creates new document |
+| Retain again with same `document_id="session_123"` | **Replaces** previous version (upsert) |
+| Retain with different `document_id="session_456"` | Creates separate document |
+| Retain without `document_id` | Creates new document each time |
+
+This upsert behavior means:
+- You always retain the **full conversation** state
+- Facts are re-extracted from the complete conversation
+- No duplicate or stale facts from old versions
+- Memory stays consistent as conversations evolve
+
+## What Gets Remembered
+
+Hindsight automatically extracts and connects:
+
+- **Facts**: "User prefers Python", "User is building a CLI tool"
+- **Entities**: People, projects, technologies mentioned
+- **Relationships**: How entities relate to each other
+- **Temporal context**: When things happened
+
+You don't need to manually extract or structure this - just retain the conversations.
+
+## When to Use This Pattern
+
+**Good fit:**
+- Chatbots and assistants
+- Personal AI companions
+- Any 1:1 user-to-agent interaction
+
+**Consider adding shared knowledge if:**
+- You have product docs or FAQs to reference
+- Multiple users need access to the same information
+- See [Support Agent with Shared Knowledge](./support-agent-with-shared-knowledge)
+
+
+---
+
+
+## File: cookbook/support-agent-with-shared-knowledge.md
+
+# Support Agent with Shared Knowledge
+
+This pattern shows how to build a support agent that combines **per-user memory** with **shared product knowledge** (RAG), giving users personalized support while leveraging a single source of truth for documentation.
+
+## The Problem
+
+You're building a support agent that needs to:
+- Remember each user's history, preferences, and past issues
+- Access shared product documentation
+- Keep user data completely isolated from other users
+
+A naive approach would index product docs into each user's memory bank, but this is expensive and wasteful (N copies for N users).
+
+## The Solution: Multi-Bank Architecture
+
+Create separate memory banks for different concerns:
+
+```
+┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
+│ User A Bank │ │ User B Bank │ │ Shared Docs │
+│ │ │ │ │ Bank │
+│ - Conversations│ │ - Conversations│ │ │
+│ - Preferences │ │ - Preferences │ │ - Product docs │
+│ - Past issues │ │ - Past issues │ │ - FAQs │
+│ - Solutions │ │ - Solutions │ │ - Guides │
+└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
+ │ │ │
+ └───────────────────────┴───────────────────────┘
+ │
+ Agent queries
+ multiple banks
+```
+
+**Key benefits:**
+- Product docs indexed once, shared by all users
+- User memory is 100% isolated
+- Simple mental model, no complex filtering
+
+## Implementation
+
+### 1. Set Up Memory Banks
+
+Create three types of banks:
+
+```python
+from hindsight import HindsightClient
+
+client = HindsightClient()
+
+# Shared knowledge bank (created once)
+shared_bank = client.create_bank(
+ bank_id="product-docs",
+ name="Product Documentation"
+)
+
+# Per-user banks (created when user signs up)
+def create_user_bank(user_id: str):
+ return client.create_bank(
+ bank_id=f"user-{user_id}",
+ name=f"Memory for {user_id}"
+ )
+```
+
+### 2. Index Product Documentation
+
+Index your product docs into the shared bank (do this once, or on doc updates):
+
+```python
+# Index product documentation
+client.retain(
+ bank_id="product-docs",
+ content=[
+ {
+ "role": "document",
+ "content": "# Pricing Tiers\n\nBasic: $10/mo...",
+ "metadata": {"source": "pricing.md"}
+ },
+ {
+ "role": "document",
+ "content": "# Getting Started\n\nTo set up...",
+ "metadata": {"source": "quickstart.md"}
+ }
+ ]
+)
+```
+
+### 3. Store User Conversations
+
+After each support interaction, retain it in the user's bank:
+
+```python
+def save_conversation(user_id: str, messages: list):
+ client.retain(
+ bank_id=f"user-{user_id}",
+ content=messages # [{"role": "user", "content": "..."}, ...]
+ )
+```
+
+### 4. Query Multiple Banks at Support Time
+
+When handling a user query, retrieve context from both banks:
+
+```python
+async def get_support_context(user_id: str, query: str):
+ # Get user's personal context
+ user_context = await client.recall(
+ bank_id=f"user-{user_id}",
+ query=query
+ )
+
+ # Get relevant product documentation
+ docs_context = await client.recall(
+ bank_id="product-docs",
+ query=query
+ )
+
+ return {
+ "user_history": user_context.results,
+ "documentation": docs_context.results
+ }
+```
+
+### 5. Build the Agent Prompt
+
+Combine both contexts in your agent's prompt:
+
+```python
+def build_prompt(query: str, context: dict) -> str:
+ return f"""You are a helpful support agent.
+
+## User's History
+{format_results(context["user_history"])}
+
+## Product Documentation
+{format_results(context["documentation"])}
+
+## Current Question
+{query}
+
+Use the user's history to personalize your response and the documentation
+for accurate product information. If you find a solution, remember it for
+future reference.
+"""
+```
+
+## Promoting Learnings to Shared Knowledge
+
+When the agent discovers a solution that's not in the docs, you can optionally promote it to a "learnings" bank:
+
+```
+┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
+│ User A Bank │ │ Shared Docs │ │ Learnings │
+│ │ │ Bank │ │ Bank │
+│ - Conversations│ │ │ │ │
+│ - Preferences │ │ - Product docs │ │ - Verified │
+│ - Past issues │ │ - FAQs │ │ solutions │
+│ - Solutions │ │ - Guides │ │ - Workarounds │
+└────────┬────────┘ └────────┬────────┘ └────────┬────────┘
+ │ │ │
+ └───────────────────────┴───────────────────────┘
+ │
+ Agent queries
+ all three banks
+```
+
+```python
+# Optional: Create a curated learnings bank
+learnings_bank = client.create_bank(
+ bank_id="support-learnings",
+ name="Curated Support Learnings"
+)
+
+# After a successful resolution
+def promote_learning(insight: str):
+ client.retain(
+ bank_id="support-learnings",
+ content=[{
+ "role": "system",
+ "content": insight,
+ "metadata": {"type": "verified_solution"}
+ }]
+ )
+```
+
+Then query three banks: user + docs + learnings.
+
+## Complete Example
+
+```python
+from hindsight import HindsightClient
+
+client = HindsightClient()
+
+async def handle_support_request(user_id: str, query: str):
+ # 1. Recall from user's memory
+ user_recall = await client.recall(
+ bank_id=f"user-{user_id}",
+ query=query
+ )
+
+ # 2. Recall from shared docs
+ docs_recall = await client.recall(
+ bank_id="product-docs",
+ query=query
+ )
+
+ # 3. Recall from learnings (optional)
+ learnings_recall = await client.recall(
+ bank_id="support-learnings",
+ query=query
+ )
+
+ # 4. Build context for LLM
+ context = f"""
+User History:
+{format_results(user_recall.results)}
+
+Product Docs:
+{format_results(docs_recall.results)}
+
+Known Solutions:
+{format_results(learnings_recall.results)}
+"""
+
+ # 5. Generate response with your LLM
+ response = await llm.complete(
+ system="You are a support agent...",
+ context=context,
+ query=query
+ )
+
+ # 6. Save the conversation to user's memory
+ await client.retain(
+ bank_id=f"user-{user_id}",
+ content=[
+ {"role": "user", "content": query},
+ {"role": "assistant", "content": response}
+ ]
+ )
+
+ return response
+```
+
+## When to Use This Pattern
+
+**Good fit:**
+- Support agents with shared documentation
+- Multi-tenant applications with shared reference data
+- Any scenario needing user isolation + shared knowledge
+
+**Consider alternatives if:**
+- You need cross-user learning (users benefiting from other users' solutions)
+- Entity relationships must span across users and docs
+
+
+
+---
+
+
+## File: api-reference/endpoints/add-bank-background.api.mdx
+
+
+
+
+
+
+
+
+
+
+Add new background information or merge with existing. LLM intelligently resolves conflicts, normalizes to first person, and optionally infers disposition traits.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/cancel-operation.api.mdx
+
+
+
+
+
+
+
+
+
+
+Cancel a pending async operation by removing it from the queue
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/clear-bank-memories.api.mdx
+
+
+
+
+
+
+
+
+
+
+Delete memory units for a memory bank. Optionally filter by type (world, experience, opinion) to delete only specific types. This is a destructive operation that cannot be undone. The bank profile (disposition and background) will be preserved.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/create-or-update-bank.api.mdx
+
+
+
+
+
+
+
+
+
+
+Create a new agent or update existing agent with disposition and background. Auto-fills missing fields with defaults.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/delete-document.api.mdx
+
+
+
+
+
+
+
+
+
+
+Delete a document and all its associated memory units and links.
+
+This will cascade delete:
+- The document itself
+- All memory units extracted from this document
+- All links (temporal, semantic, entity) associated with those memory units
+
+This operation cannot be undone.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/get-agent-stats.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get statistics about nodes and links for a specific agent
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/get-bank-profile.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get disposition traits and background for a memory bank. Auto-creates agent with defaults if not exists.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/get-chunk.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get a specific chunk by its ID
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/get-document.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get a specific document including its original text
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/get-entity.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get detailed information about an entity including observations (mental model).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/get-graph.api.mdx
+
+
+
+
+
+
+
+
+
+
+Retrieve graph data for visualization, optionally filtered by type (world/experience/opinion). Limited to 1000 most recent items.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/health-endpoint-health-get.api.mdx
+
+
+
+
+
+
+
+
+
+
+Checks the health of the API and database connection
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/hindsight-http-api.info.mdx
+
+
+
+
+
+
+
+
+
+HTTP API for Hindsight
+
+
+
+ Contact
+
+ Memory System:
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/list-banks.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get a list of all agents with their profiles
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/list-documents.api.mdx
+
+
+
+
+
+
+
+
+
+
+List documents with pagination and optional search. Documents are the source content from which memory units are extracted.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/list-entities.api.mdx
+
+
+
+
+
+
+
+
+
+
+List all entities (people, organizations, etc.) known by the bank, ordered by mention count.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/list-memories.api.mdx
+
+
+
+
+
+
+
+
+
+
+List memory units with pagination and optional full-text search. Supports filtering by type. Results are sorted by most recent first (mentioned_at DESC, then created_at DESC).
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/list-operations.api.mdx
+
+
+
+
+
+
+
+
+
+
+Get a list of all async operations (pending and failed) for a specific agent, including error messages for failed operations
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/metrics-endpoint-metrics-get.api.mdx
+
+
+
+
+
+
+
+
+
+
+Exports metrics in Prometheus format for scraping
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/recall-memories.api.mdx
+
+
+
+
+
+
+
+
+
+
+Recall memory using semantic similarity and spreading activation.
+
+ The type parameter is optional and must be one of:
+ - 'world': General knowledge about people, places, events, and things that happen
+ - 'experience': Memories about experience, conversations, actions taken, and tasks performed
+ - 'opinion': The bank's formed beliefs, perspectives, and viewpoints
+
+ Set include_entities=true to get entity observations alongside recall results.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/reflect.api.mdx
+
+
+
+
+
+
+
+
+
+
+Reflect and formulate an answer using bank identity, world facts, and opinions.
+
+ This endpoint:
+ 1. Retrieves experience (conversations and events)
+ 2. Retrieves world facts relevant to the query
+ 3. Retrieves existing opinions (bank's perspectives)
+ 4. Uses LLM to formulate a contextual answer
+ 5. Extracts and stores any new opinions formed
+ 6. Returns plain text answer, the facts used, and new opinions
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/regenerate-entity-observations.api.mdx
+
+
+
+
+
+
+
+
+
+
+Regenerate observations for an entity based on all facts mentioning it.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/retain-memories.api.mdx
+
+
+
+
+
+
+
+
+
+
+Retain memory items with automatic fact extraction.
+
+ This is the main endpoint for storing memories. It supports both synchronous and asynchronous processing
+ via the async parameter.
+
+ Features:
+ - Efficient batch processing
+ - Automatic fact extraction from natural language
+ - Entity recognition and linking
+ - Document tracking with automatic upsert (when document_id is provided on items)
+ - Temporal and semantic linking
+ - Optional asynchronous processing
+
+ The system automatically:
+ 1. Extracts semantic facts from the content
+ 2. Generates embeddings
+ 3. Deduplicates similar facts
+ 4. Creates temporal, semantic, and entity links
+ 5. Tracks document metadata
+
+ When async=true:
+ - Returns immediately after queuing the task
+ - Processing happens in the background
+ - Use the operations endpoint to monitor progress
+
+ When async=false (default):
+ - Waits for processing to complete
+ - Returns after all memories are stored
+
+ Note: If a memory item has a document_id that already exists, the old document and its memory units will be deleted before creating new ones (upsert behavior). Items with the same document_id are grouped together for efficient processing.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/endpoints/update-bank-disposition.api.mdx
+
+
+
+
+
+
+
+
+
+
+Update bank's disposition traits (skepticism, literalism, empathy)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+---
+
+
+## File: api-reference/index.md
+
+# API Reference
+
+Complete reference for Hindsight's HTTP and MCP APIs.
+
+## HTTP API
+
+The HTTP API reference is automatically generated from our OpenAPI specification. Browse the endpoints in the sidebar to see request/response details, parameters, and examples.
+
+**Base URL:** `http://localhost:8888`
+
+| Category | Endpoints |
+|----------|-----------|
+| **Memory Operations** | Store, search, list, delete memories |
+| **Reasoning** | Think and generate personality-aware responses |
+| **Memory bank Management** | Create, update, list memory banks and profiles |
+| **Documents** | Manage document groupings |
+| **Visualization** | Get entity graph data |
+
+## MCP API
+
+The MCP (Model Context Protocol) API exposes Hindsight tools for AI assistants like Claude Desktop.
+
+| Tool | Description |
+|------|-------------|
+| `hindsight_search` | Search memories |
+| `hindsight_think` | Generate personality-aware response |
+| `hindsight_store` | Store new memory |
+| `hindsight_agents` | List available memory banks |
+
+[MCP Tools Reference →](/api-reference/mcp)
+
+## OpenAPI / Swagger
+
+Interactive API documentation available when the server is running:
+
+- **Swagger UI:** [http://localhost:8888/docs](http://localhost:8888/docs)
+- **OpenAPI JSON:** [http://localhost:8888/openapi.json](http://localhost:8888/openapi.json)
+
+
+---
+
+
+## File: api-reference/mcp.md
+
+# MCP API
+
+Model Context Protocol (MCP) tools exposed by the Hindsight MCP server.
+
+## Endpoint
+
+```
+/mcp/{bank_id}/sse
+```
+
+The `bank_id` is extracted from the URL path and used for all tool operations. The MCP server uses Server-Sent Events (SSE) transport.
+
+## Available Tools
+
+### retain
+
+Store a new memory.
+
+**Parameters:**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `content` | string | yes | Memory content to store |
+| `context` | string | no | Category for the memory (default: 'general') |
+
+**Example:**
+
+```json
+{
+ "name": "retain",
+ "arguments": {
+ "content": "User prefers Python for data analysis",
+ "context": "preferences"
+ }
+}
+```
+
+**Response:**
+
+```
+Memory stored successfully
+```
+
+---
+
+### recall
+
+Search memories.
+
+**Parameters:**
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `query` | string | yes | Natural language search query |
+| `max_results` | integer | no | Maximum results to return (default: 10) |
+
+**Example:**
+
+```json
+{
+ "name": "recall",
+ "arguments": {
+ "query": "What does the user do for work?"
+ }
+}
+```
+
+**Response:**
+
+```json
+{
+ "results": [
+ {
+ "id": "550e8400-e29b-41d4-a716-446655440000",
+ "text": "User works at Google as a software engineer",
+ "type": "world",
+ "context": "work",
+ "event_date": null
+ }
+ ]
+}
+```
+
+---
+
+## Usage Guidelines
+
+**When to use `retain`:**
+- User shares personal facts, preferences, or interests
+- Important events or milestones are mentioned
+- Decisions, opinions, or goals are stated
+
+**When to use `recall`:**
+- Start of conversation to get user context
+- Before making recommendations
+- To provide continuity across conversations
+
+
+---
+
+
+## File: changelog/index.md
+
+# Changelog
+
+Coming soon.
+
+
+---
+
+
+## File: developer/api/opinions.md
+
+# Opinions
+
+How memory banks form, store, and evolve beliefs.
+
+
+
+
+:::tip Prerequisites
+Make sure you've completed the [Quick Start](./quickstart) to install the client and start the server.
+:::
+
+## What Are Opinions?
+
+Opinions are beliefs formed by the memory bank based on evidence and personality. Unlike world facts (objective information received) or experience (conversations and events), opinions are **judgments** with confidence scores.
+
+| Type | Example | Confidence |
+|------|---------|------------|
+| World Fact | "Python was created in 1991" | — |
+| Experience | "I recommended Python to Bob" | — |
+| Opinion | "Python is the best language for data science" | 0.85 |
+
+## How Opinions Form
+
+Opinions are created during `think` operations when the memory bank:
+1. Retrieves relevant facts
+2. Applies personality traits
+3. Forms a judgment
+4. Assigns a confidence score
+
+```mermaid
+graph LR
+ F[Facts] --> P[Personality Filter]
+ P --> J[Judgment]
+ J --> O[Opinion + Confidence]
+ O --> S[(Store)]
+```
+
+
+
+
+```python
+# Ask a question that might form an opinion
+answer = client.think(
+ agent_id="my-agent",
+ query="What do you think about functional programming?"
+)
+
+# Check if new opinions were formed
+for opinion in answer["new_opinions"]:
+ print(f"New opinion: {opinion['text']}")
+ print(f"Confidence: {opinion['confidence']}")
+```
+
+
+
+
+## Searching Opinions
+
+
+
+
+```python
+# Search only opinions
+opinions = client.search_memories(
+ agent_id="my-agent",
+ query="programming languages",
+ fact_type=["opinion"]
+)
+
+for op in opinions:
+ print(f"{op['text']} (confidence: {op['confidence_score']:.2f})")
+```
+
+
+
+
+```bash
+hindsight memory search my-agent "programming" --fact-type opinion
+```
+
+
+
+
+## Opinion Evolution
+
+Opinions change as new evidence arrives:
+
+| Evidence Type | Effect |
+|---------------|--------|
+| **Reinforcing** | Confidence increases (+0.1) |
+| **Weakening** | Confidence decreases (-0.15) |
+| **Contradicting** | Opinion revised, confidence reset |
+
+**Example evolution:**
+
+```
+t=0: "Python is best for data science" (0.70)
+ ↓ New evidence: Python dominates ML libraries
+t=1: "Python is best for data science" (0.85)
+ ↓ New evidence: Julia is 10x faster for numerical computing
+t=2: "Python is best for data science, though Julia is faster" (0.75)
+ ↓ New evidence: Most teams still use Python
+t=3: "Python is best for data science" (0.82)
+```
+
+## Personality Influence
+
+Different personalities form different opinions from the same facts:
+
+
+
+
+```python
+# Create two memory banks with different personalities
+client.create_agent(
+ agent_id="open-minded",
+ personality={"openness": 0.9, "conscientiousness": 0.3, "bias_strength": 0.7}
+)
+
+client.create_agent(
+ agent_id="conservative",
+ personality={"openness": 0.2, "conscientiousness": 0.9, "bias_strength": 0.7}
+)
+
+# Store the same facts to both
+facts = [
+ "Rust has better memory safety than C++",
+ "C++ has a larger ecosystem and more libraries",
+ "Rust compile times are longer than C++"
+]
+for fact in facts:
+ client.store(agent_id="open-minded", content=fact)
+ client.store(agent_id="conservative", content=fact)
+
+# Ask both the same question
+q = "Should we rewrite our C++ codebase in Rust?"
+
+answer1 = client.think(agent_id="open-minded", query=q)
+# Likely: "Yes, Rust's safety benefits outweigh migration costs"
+
+answer2 = client.think(agent_id="conservative", query=q)
+# Likely: "No, C++'s ecosystem and our team's expertise make it the safer choice"
+```
+
+
+
+
+## Bias Strength
+
+The `bias_strength` parameter (0-1) controls how much personality influences opinions:
+
+| Value | Behavior |
+|-------|----------|
+| 0.0 | Pure evidence-based reasoning |
+| 0.5 | Balanced personality + evidence |
+| 1.0 | Strongly personality-driven |
+
+```python
+# Evidence-focused agent
+client.create_agent(
+ agent_id="analyst",
+ personality={"bias_strength": 0.2} # Low bias
+)
+
+# Personality-driven agent
+client.create_agent(
+ agent_id="advisor",
+ personality={"bias_strength": 0.8} # High bias
+)
+```
+
+## Opinions in Think Responses
+
+When `think` uses opinions, they appear in `based_on`:
+
+```python
+answer = client.think(agent_id="my-agent", query="What language should I learn?")
+
+print("World facts used:")
+for f in answer["based_on"]["world"]:
+ print(f" {f['text']}")
+
+print("\nOpinions used:")
+for o in answer["based_on"]["opinion"]:
+ print(f" {o['text']} (confidence: {o['confidence_score']})")
+```
+
+## Confidence Thresholds
+
+Opinions below a confidence threshold may be:
+- Excluded from responses
+- Marked as uncertain
+- Revised more easily
+
+```python
+# Low confidence opinions are held loosely
+# "I think Python might be good for this" (0.45)
+
+# High confidence opinions are stated firmly
+# "Python is definitely the right choice" (0.92)
+```
+
+
+---
+
+
+## File: developer/api/think-vs-search.md
+
+# Think vs Search
+
+When to use `search` vs `think`.
+
+## Quick Comparison
+
+| | Search | Think |
+|---|--------|-------|
+| **Returns** | Raw memory results | Generated response |
+| **Use case** | Retrieval, lookup | Q&A, reasoning |
+| **LLM calls** | 0 (retrieval only) | 1+ (generation) |
+| **Speed** | Fast (~100-200ms) | Slower (~500-2000ms) |
+| **Opinions** | Returns existing | Can form new ones |
+| **Personality** | Not applied | Applied to response |
+
+## When to Use Search
+
+**Use Search when you need:**
+
+- Raw facts for your own processing
+- Fast retrieval without generation
+- To populate context for another LLM
+- To check what's in memory
+- Debugging retrieval quality
+
+```python
+# Get raw facts to inject into your own prompt
+results = client.search(agent_id="my-agent", query="Alice's preferences")
+
+context = "\n".join([r["text"] for r in results])
+# Use context in your own LLM call
+```
+
+**Examples:**
+
+```python
+# Lookup — just get the facts
+results = client.search(agent_id="my-agent", query="Alice's email address")
+
+# Context building — feed into another system
+results = client.search(agent_id="my-agent", query="Recent project discussions")
+context = format_for_prompt(results)
+
+# Verification — check what's stored
+results = client.search(agent_id="my-agent", query="What do I know about Bob?")
+```
+
+## When to Use Think
+
+**Use Think when you need:**
+
+- A natural language response
+- Personality-aware answers
+- Opinion formation
+- Reasoning over multiple facts
+- Source attribution
+
+```python
+# Get a complete answer with personality
+answer = client.think(agent_id="my-agent", query="What should I recommend to Alice?")
+print(answer["text"]) # Natural language response
+print(answer["based_on"]) # Sources used
+```
+
+**Examples:**
+
+```python
+# Q&A — need a response, not just facts
+answer = client.think(agent_id="my-agent", query="What does Alice do for work?")
+
+# Reasoning — synthesize multiple facts
+answer = client.think(agent_id="my-agent", query="How are Alice and Bob connected?")
+
+# Opinion — agent forms a view
+answer = client.think(agent_id="my-agent", query="What do you think about Python?")
+
+# Recommendation — personality-influenced
+answer = client.think(agent_id="my-agent", query="What book should I read next?")
+```
+
+## Performance Comparison
+
+```mermaid
+graph LR
+ subgraph Search
+ S1[Query] --> S2[4-way Retrieval]
+ S2 --> S3[RRF + Rerank]
+ S3 --> S4[Results]
+ end
+
+ subgraph Think
+ T1[Query] --> T2[4-way Retrieval]
+ T2 --> T3[RRF + Rerank]
+ T3 --> T4[Load Personality]
+ T4 --> T5[LLM Generation]
+ T5 --> T6[Store Opinions]
+ T6 --> T7[Response]
+ end
+```
+
+| Operation | Search | Think |
+|-----------|--------|-------|
+| Retrieval | ~100ms | ~100ms |
+| Reranking | ~35ms | ~35ms |
+| LLM Generation | — | ~500-1500ms |
+| Opinion Storage | — | ~50ms |
+| **Total** | **~135ms** | **~700-1700ms** |
+
+## Hybrid Pattern
+
+Use Search for context, Think for final response:
+
+```python
+# First: fast search to check relevance
+results = client.search(agent_id="my-agent", query="Alice project status")
+
+if len(results) > 0:
+ # Only call Think if we have relevant memories
+ answer = client.think(agent_id="my-agent", query="Summarize Alice's project status")
+else:
+ answer = {"text": "I don't have information about Alice's projects."}
+```
+
+## Decision Flowchart
+
+```mermaid
+graph TD
+ A[Need memory access] --> B{Need natural language response?}
+ B -->|No| C[Use Search]
+ B -->|Yes| D{Need personality/opinions?}
+ D -->|No| E{Building context for another LLM?}
+ E -->|Yes| C
+ E -->|No| F[Use Think]
+ D -->|Yes| F
+```
+
+## Cost Considerations
+
+| Factor | Search | Think |
+|--------|--------|-------|
+| API calls | 1 | 1 |
+| LLM tokens | 0 | 500-2000 |
+| Latency | Low | Medium |
+| Cost | Low | Higher (LLM usage) |
+
+If you're making many requests or building a high-throughput system, consider:
+- Use Search for bulk operations
+- Use Think for user-facing responses
+- Cache Think responses when appropriate
+
+
+---
+
+
+## File: developer/development.md
+
+# Development Guide
+
+Guide to setting up a local development environment for contributing to Hindsight.
+
+## Prerequisites
+
+- Python 3.11+
+- [uv](https://docs.astral.sh/uv/) - Fast Python package manager
+- Docker and Docker Compose
+- An LLM API key (OpenAI, Groq, or Ollama)
+
+## Local Development Setup
+
+### 1. Clone the Repository
+
+```bash
+git clone https://github.com/vectorize-io/hindsight.git
+cd hindsight
+```
+
+### 2. Install Dependencies
+
+```bash
+uv sync
+```
+
+### 3. Start PostgreSQL
+
+Start only the database via Docker:
+
+```bash
+cd docker && docker-compose up -d postgres
+```
+
+### 4. Configure Environment
+
+```bash
+cp .env.example .env
+```
+
+Edit `.env` with your LLM API key:
+
+```bash
+# Database (connects to Docker postgres)
+HINDSIGHT_API_DATABASE_URL=postgresql://hindsight:hindsight_dev@localhost:5432/hindsight
+
+# LLM Provider (choose one)
+HINDSIGHT_API_LLM_PROVIDER=groq
+HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
+HINDSIGHT_API_LLM_MODEL=llama-3.1-70b-versatile
+```
+
+### 5. Start the API Server
+
+```bash
+./scripts/start-server.sh --env local
+```
+
+The server will be available at http://localhost:8888.
+
+## Running Tests
+
+```bash
+# Run all tests
+uv run pytest
+
+# Run specific test file
+uv run pytest tests/test_retrieval.py
+
+# Run with verbose output
+uv run pytest -v
+```
+
+## Code Generation
+
+### Regenerate API Clients
+
+When you modify the OpenAPI spec, regenerate the clients:
+
+```bash
+./scripts/generate-clients.sh
+```
+
+This generates:
+- Python client in `hindsight-clients/python/`
+- TypeScript client in `hindsight-clients/typescript/`
+
+### Export OpenAPI Schema
+
+```bash
+./scripts/export-openapi.sh
+```
+
+## Project Structure
+
+```
+hindsight/
+├── hindsight-api/ # Main API server
+│ ├── hindsight_api/
+│ │ ├── api/ # HTTP endpoints
+│ │ ├── engine/ # Memory engine, retrieval, reasoning
+│ │ └── web/ # Server entry point
+│ └── tests/
+├── hindsight-clients/ # Generated SDK clients
+│ ├── python/
+│ └── typescript/
+├── hindsight-control-plane/ # Admin UI (Next.js)
+├── docker/ # Docker Compose setup
+└── scripts/ # Development scripts
+```
+
+## Contributing
+
+1. Create a feature branch from `main`
+2. Make your changes
+3. Run tests: `uv run pytest`
+4. Submit a pull request
+
+## Troubleshooting
+
+### Database Connection Issues
+
+Ensure PostgreSQL is running:
+
+```bash
+docker-compose ps
+```
+
+Check database connectivity:
+
+```bash
+psql postgresql://hindsight:hindsight_dev@localhost:5432/hindsight
+```
+
+### ML Model Download
+
+On first run, Hindsight downloads embedding and reranking models. This may take a few minutes. Models are cached in `~/.cache/huggingface/`.
+
+### Port Conflicts
+
+If port 8888 is in use:
+
+```bash
+HINDSIGHT_API_PORT=8889 ./scripts/start-server.sh --env local
+```
+
+
+---
+
+
+## File: developer/mcp-server.md
+
+# MCP Server
+
+Hindsight includes a built-in [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) server that allows AI assistants to store and retrieve memories directly.
+
+## Access
+
+The MCP server is **enabled by default** and mounted at `/mcp` on the API server:
+
+```
+http://localhost:8888/mcp
+```
+
+To disable it, set the environment variable:
+
+```bash
+export HINDSIGHT_API_MCP_ENABLED=false
+```
+
+## Available Tools
+
+### hindsight_put
+
+Store information to a user's memory bank.
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `bank_id` | string | Yes | Unique identifier for the user (e.g., `user_12345`, `alice@example.com`) |
+| `content` | string | Yes | The fact or memory to store |
+| `context` | string | Yes | Category for the memory (e.g., `personal_preferences`, `work_history`) |
+| `explanation` | string | No | Why this memory is being stored |
+
+**Example:**
+```json
+{
+ "name": "hindsight_put",
+ "arguments": {
+ "bank_id": "user_12345",
+ "content": "User prefers Python over JavaScript for backend development",
+ "context": "programming_preferences"
+ }
+}
+```
+
+**When to use:**
+- User shares personal facts, preferences, or interests
+- Important events or milestones are mentioned
+- Decisions, opinions, or goals are stated
+- Work context or project details are discussed
+
+---
+
+### hindsight_search
+
+Search a user's memory bank to provide personalized responses.
+
+| Parameter | Type | Required | Description |
+|-----------|------|----------|-------------|
+| `bank_id` | string | Yes | Unique identifier for the user |
+| `query` | string | Yes | Natural language search query |
+| `max_tokens` | integer | No | Maximum tokens for results (default: 4096) |
+| `explanation` | string | No | Why this search is being performed |
+
+**Example:**
+```json
+{
+ "name": "hindsight_search",
+ "arguments": {
+ "bank_id": "user_12345",
+ "query": "What are the user's programming language preferences?"
+ }
+}
+```
+
+**Response:**
+```json
+{
+ "results": [
+ {
+ "id": "fact_abc123",
+ "text": "User prefers Python over JavaScript for backend development",
+ "type": "world",
+ "context": "programming_preferences",
+ "event_date": null,
+ "document_id": null
+ }
+ ]
+}
+```
+
+**When to use:**
+- Start of conversation to recall relevant context
+- Before making recommendations
+- When user asks about something they may have mentioned before
+- To provide continuity across conversations
+
+---
+
+## Per-User Isolation
+
+Both tools require a `bank_id` that uniquely identifies the user. Memories are strictly isolated per bank — one user cannot access another user's memories.
+
+**Best practices:**
+- Use consistent identifiers (user ID, email, session ID)
+- Don't share `bank_id` between different users
+- Only call these tools when you can identify the specific user
+
+---
+
+## Integration with AI Assistants
+
+The MCP server can be used with any MCP-compatible AI assistant. For Claude Desktop integration using the CLI, see [MCP Server (CLI)](/sdks/mcp).
+
+
+---
+
+
+## File: developer/metrics.md
+
+# Metrics
+
+Hindsight exposes Prometheus metrics at `/metrics` for monitoring.
+
+```bash
+curl http://localhost:8888/metrics
+```
+
+## Available Metrics
+
+### Request Metrics
+
+| Metric | Type | Description |
+|--------|------|-------------|
+| `hindsight_http_requests_total` | Counter | Total HTTP requests (labels: method, endpoint, status_code) |
+| `hindsight_http_request_duration_seconds` | Histogram | Request latency (labels: method, endpoint) |
+
+### Memory Operations
+
+| Metric | Type | Description |
+|--------|------|-------------|
+| `hindsight_retain_duration_seconds` | Histogram | Retain operation latency |
+| `hindsight_retain_items_total` | Counter | Total items retained |
+| `hindsight_recall_duration_seconds` | Histogram | Recall operation latency |
+| `hindsight_recall_results_count` | Histogram | Number of results per recall |
+| `hindsight_reflect_duration_seconds` | Histogram | Reflect operation latency |
+
+### LLM Metrics
+
+| Metric | Type | Description |
+|--------|------|-------------|
+| `hindsight_llm_requests_total` | Counter | LLM API requests (labels: provider, model, status) |
+| `hindsight_llm_request_duration_seconds` | Histogram | LLM request latency |
+| `hindsight_llm_tokens_total` | Counter | Tokens consumed (labels: provider, token_type) |
+
+### Database Metrics
+
+| Metric | Type | Description |
+|--------|------|-------------|
+| `hindsight_db_connections_active` | Gauge | Active database connections |
+| `hindsight_db_connections_idle` | Gauge | Idle connections in pool |
+| `hindsight_db_query_duration_seconds` | Histogram | Query latency (labels: query_type) |
+
+### Memory Bank Metrics
+
+| Metric | Type | Description |
+|--------|------|-------------|
+| `hindsight_bank_memory_units_total` | Gauge | Total memories per bank |
+| `hindsight_bank_entities_total` | Gauge | Total entities per bank |
+
+## Prometheus Configuration
+
+```yaml
+scrape_configs:
+ - job_name: 'hindsight'
+ static_configs:
+ - targets: ['localhost:8888']
+```
+
+
+---
+
+
+## File: developer/performance.md
+
+# Performance
+
+Hindsight is designed for high-performance semantic memory operations at scale. This page covers performance characteristics, optimization strategies, and best practices.
+
+## Overview
+
+Hindsight's performance is optimized across three key operations:
+
+- **Retain (Ingestion)**: Batch processing with async operations for large-scale memory storage
+- **Recall (Search)**: Sub-second semantic search with configurable thinking budgets
+- **Reflect (Reasoning)**: Personality-aware answer generation with controllable compute
+
+## Design Philosophy: Optimized for Fast Reads
+
+Hindsight is **architected from the ground up to prioritize read performance over write performance**. This design decision reflects the typical usage pattern of memory systems: memories are written once but read many times.
+
+The system makes deliberate trade-offs to ensure **sub-second recall operations**:
+
+- **Pre-computed embeddings**: All memory embeddings are generated and indexed during retention
+- **Optimized vector search**: HNSW indexes enable fast approximate nearest neighbor search
+- **Fact extraction at write time**: Complex LLM-based fact extraction happens during retention, not retrieval
+- **Structured memory graphs**: Relationships and temporal information are resolved upfront
+
+This means **Recall (search) operations are blazingly fast** because all the heavy lifting has already been done.
+
+### Performance Comparison
+
+| Operation | Typical Latency | Primary Bottleneck | Optimization Strategy |
+|-----------|----------------|-------------------|----------------------|
+| **Recall** | 100-600ms | Vector search, graph traversal | ✅ Already optimized |
+| **Reflect** | 800-3000ms | LLM generation + search | Reduce search budget, use faster LLM |
+| **Retain** | 500ms-2000ms per batch | **LLM fact extraction** | Use high-throughput LLM provider |
+
+Hindsight is designed to ensure your **application's read path (recall/reflect) is always fast**, even if it means spending more time upfront during writes. This is the right trade-off for memory systems where:
+
+- Memories are retained in background processes or during low-traffic periods
+- Memories are queried frequently in user-facing, latency-sensitive contexts
+- The ratio of reads to writes is high (typically 10:1 or higher)
+
+---
+
+## Retain Performance
+
+**Retain (write) operations are inherently slower** because they involve LLM-based fact extraction, entity recognition, temporal reasoning, relationship mapping, and embedding generation. **The LLM is the primary bottleneck for write latency.**
+
+### Hindsight Doesn't Need a Smart Model
+
+The fact extraction process is structured and well-defined, so smaller, faster models work extremely well. Our recommended model is `gpt-oss-20b` (available via Groq and other providers).
+
+To maximize retention throughput:
+
+1. **Use high-throughput LLM providers**: Choose providers with high requests-per-minute (RPM) limits and low latency
+ - ✅ **Fast**: [Groq](https://groq.com) with `gpt-oss-20b` or other openai-oss models, self-hosted models on GPU clusters (vLLM, TGI)
+ - ⚠️ **Slower**: Standard cloud LLM providers with rate limits
+
+2. **Batch your operations**: Group related content into batch requests. The only limit is the HTTP payload size — Hindsight automatically splits large batches into smaller, optimized chunks under the hood, so you don't have to worry about it.
+
+3. **Use async mode for large datasets**: Queue operations in the background
+
+4. **Parallel processing**: For very large datasets, use multiple concurrent retention requests with different `document_id` values
+
+### Throughput
+
+Typical ingestion performance:
+
+| Mode | Items/second | Use Case |
+|------|--------------|----------|
+| Synchronous | ~50-100 | Real-time updates, small batches |
+| Async (batched) | ~500-1000 | Bulk imports, background processing |
+| Parallel async | ~2000-5000 | Large-scale data migration |
+
+**Factors affecting throughput:**
+- Document size and complexity
+- LLM provider rate limits (for fact extraction)
+- Database write performance
+- Available CPU/memory resources
+
+---
+
+## Recall Performance
+
+### Budget
+
+The `budget` parameter controls the search depth and quality. Choose based on query complexity — comprehensive questions that need thorough analysis benefit from higher budgets:
+
+| Budget | Latency | Memory Activation | Use Case |
+|--------|---------|-------------------|----------|
+| `low` | 100-300ms | ~10-50 facts | Quick lookups, real-time chat |
+| `mid` | 300-600ms | ~50-200 facts | Standard queries, balanced performance |
+| `high` | 500-1500ms | ~200-500 facts | Comprehensive questions, thorough analysis |
+
+### Search Optimization
+
+1. **Appropriate budgets**: Use lower budgets for simple queries, higher for comprehensive reasoning
+2. **Limit result tokens**: Set `max_tokens` to control response size (default: 4096)
+3. **Include entities/chunks**: Use `include_entities` and `include_chunks` to retrieve additional context when needed — each has its own token budget
+
+### Database Performance
+
+Hindsight uses PostgreSQL with pgvector for efficient vector search:
+
+- **Index type**: HNSW for approximate nearest neighbor search
+- **Typical query time**: 10-50ms for vector search on 100K+ facts
+- **Scalability**: Tested with millions of facts per bank
+
+## Reflect Performance
+
+### Performance Characteristics
+
+| Component | Latency | Description |
+|-----------|---------|-------------|
+| Memory search | 300-1000ms | Based on budget (low/mid/high) |
+| LLM generation | 500-2000ms | Depends on provider and response length |
+| **Total** | **800-3000ms** | Typical end-to-end latency |
+
+### Optimization Strategies
+
+1. **Budget selection**: Use lower budgets when context is sufficient
+2. **Context provision**: Provide relevant `context` to reduce search requirements
+3. **Streaming responses**: Use streaming APIs (when available) for faster time-to-first-token
+4. **Caching**: Cache frequent queries at the application level
+
+## Best Practices
+
+### Operations
+- **Use appropriate budgets**: Don't over-provision for simple queries; use higher budgets for comprehensive reasoning
+- **Batch retain operations**: Group related content together for better efficiency
+- **Cache frequent queries**: Cache at the application level for repeated queries
+- **Profile with trace**: Use the `trace` parameter to identify slow operations
+
+### Scaling
+- **Horizontal scaling**: Deploy multiple API instances behind a load balancer with shared PostgreSQL
+- **Concurrency**: 100+ simultaneous requests supported; memory search scales with CPU cores
+- **LLM rate limits**: Distribute load across multiple API keys/providers (typically 60-500 RPM per key)
+
+### Cost Optimization
+- **Use efficient models**: `gpt-oss-20b` via Groq for retain — Hindsight doesn't need frontier models
+- **Control token budgets**: Limit `max_tokens` for recall, use lower budgets when possible
+- **Optimize chunks**: Larger chunks (1000-2000 tokens) are more efficient than many small ones
+
+### Monitoring
+- **Prometheus metrics**: Available at `/metrics` — track latency percentiles, throughput, and error rates
+- **Key metrics**: `hindsight_recall_duration_seconds`, `hindsight_reflect_duration_seconds`, `hindsight_retain_items_total`
+
+
+---
+
+
+## File: developer/storage.md
+
+# Storage
+
+Hindsight uses PostgreSQL as its sole storage backend.
+
+## Why PostgreSQL?
+
+PostgreSQL provides all capabilities required for a semantic memory system in a single database:
+
+| Capability | Implementation |
+|------------|----------------|
+| Vector search | pgvector extension with HNSW indexes |
+| Full-text search | Built-in tsvector with GIN indexes |
+| Relational data | Native PostgreSQL |
+| JSON documents | JSONB with indexing |
+| Graph queries | Recursive CTEs |
+
+### Reduced System Dependencies
+
+Building exclusively for PostgreSQL simplifies deployment and operations:
+
+- Single connection string to configure
+- Single backup and restore strategy
+- Single monitoring target
+- ACID transactions across all data types
+- Single upgrade path
+
+### No Storage Abstraction
+
+Hindsight does not abstract storage behind a generic interface. This is a deliberate trade-off.
+
+We believe PostgreSQL is becoming the standard database API. Its popularity, extension ecosystem, and modularity mean that PostgreSQL-compatible interfaces are appearing everywhere—from serverless offerings to distributed databases. Building for PostgreSQL today means compatibility with a growing ecosystem tomorrow.
+
+Supporting multiple databases would increase flexibility but conflict with our core goals: Hindsight is fully open source and designed to be as simple as possible to run and use. Adding database abstractions introduces complexity in code, testing, documentation, and operations—complexity that we pass on to users.
+
+By committing to PostgreSQL, we keep the system simple:
+- One set of deployment instructions
+- One set of performance characteristics to understand
+- One codebase optimized for one backend
+- No configuration decisions about which database to use
+
+## Development with pg0
+
+For local development, Hindsight uses **[pg0](https://github.com/vectorize-io/pg0)**—an embedded PostgreSQL distribution.
+
+### What is pg0?
+
+pg0 is a single binary containing:
+- PostgreSQL server
+- pgvector extension (pre-installed)
+- Automatic initialization
+
+### Behavior
+
+When no `DATABASE_URL` is configured, Hindsight:
+1. Downloads the pg0 binary for the current platform (macOS ARM, Linux x86_64/ARM64, Windows)
+2. Starts an embedded PostgreSQL instance on port 5555
+3. Initializes the schema
+4. Stores data in `~/.hindsight/pg0/`
+
+### Environments
+
+| Environment | Database | Configuration |
+|-------------|----------|---------------|
+| Development | pg0 (embedded) | Automatic |
+| Production | PostgreSQL 15+ | `DATABASE_URL` environment variable |
+
+## Requirements
+
+- PostgreSQL 15 or later
+- pgvector 0.5.0 or later
+
+Any PostgreSQL instance that satisfies these requirements should work. If you encounter issues with a specific setup, [open a GitHub issue](https://github.com/hindsight-ai/hindsight/issues).
+
+### Tested Managed Services
+
+- AWS RDS (PostgreSQL 15+)
+- Google Cloud SQL
+- Azure Database for PostgreSQL
+- Supabase
+- Neon
+
+
+---
+
+
+## File: sdks/langgraph.md
+
+# LangGraph
+
+Hindsight provides a `BaseStore` implementation for LangGraph's memory system.
+
+## Installation
+
+```bash
+cd hindsight-langmem && uv pip install -e .
+```
+
+## Quick Start
+
+```python
+from hindsight_langmem import HindsightStore
+
+# Create store
+store = HindsightStore(
+ base_url="http://localhost:8888",
+ default_agent_id="my-agent",
+)
+
+# Store data
+store.put(
+ namespace=("user", "preferences"),
+ key="language",
+ value={"language": "Python", "reason": "data science"}
+)
+
+# Retrieve data
+item = store.get(namespace=("user", "preferences"), key="language")
+print(item.value) # {"language": "Python", "reason": "data science"}
+
+# Search
+results = store.search(
+ namespace_prefix=("user",),
+ query="programming language",
+ limit=10
+)
+```
+
+## How It Works
+
+`HindsightStore` implements LangGraph's `BaseStore` interface:
+
+- **Namespaces** map to Hindsight agent IDs (joined with `__`)
+- **Keys** map to document IDs
+- **Values** are stored as JSON in memory content
+
+## BaseStore Interface
+
+### put
+
+Store an item:
+
+```python
+store.put(
+ namespace=("user", "session-123"),
+ key="preferences",
+ value={"theme": "dark", "language": "en"}
+)
+```
+
+### get
+
+Retrieve an item:
+
+```python
+item = store.get(namespace=("user", "session-123"), key="preferences")
+if item:
+ print(item.value) # {"theme": "dark", "language": "en"}
+ print(item.created_at)
+ print(item.updated_at)
+```
+
+### search
+
+Search within a namespace:
+
+```python
+results = store.search(
+ namespace_prefix=("user",),
+ query="theme preferences",
+ limit=10,
+ offset=0
+)
+
+for item in results:
+ print(f"{item.key}: {item.value}")
+```
+
+### delete
+
+Delete an item:
+
+```python
+store.delete(namespace=("user", "session-123"), key="preferences")
+```
+
+## Async Support
+
+All operations have async variants:
+
+```python
+await store.aput(namespace, key, value)
+item = await store.aget(namespace, key)
+results = await store.asearch(namespace_prefix, query)
+await store.adelete(namespace, key)
+```
+
+## With LangGraph
+
+```python
+from langgraph.graph import StateGraph
+from hindsight_langmem import HindsightStore
+
+store = HindsightStore(base_url="http://localhost:8888")
+
+# Use store in your graph
+graph = StateGraph()
+# ... configure graph with store
+```
+
+## Namespace Mapping
+
+Namespaces are converted to Hindsight agent IDs:
+
+| Namespace | bank ID |
+|-----------|----------|
+| `("user",)` | `user` |
+| `("user", "session")` | `user__session` |
+| `("app", "v1", "data")` | `app__v1__data` |
+| `()` | `default_agent_id` |
+
+Memory banks are created automatically if they don't exist.
+
+
+---
+
+
+## File: sdks/openai.md
+
+# OpenAI
+
+Drop-in replacement for the OpenAI Python client with automatic memory integration.
+
+## Installation
+
+```bash
+cd hindsight-openai && uv pip install -e .
+```
+
+## Quick Start
+
+```python
+from hindsight_openai import configure, OpenAI
+
+# Configure once
+configure(
+ hindsight_api_url="http://localhost:8888",
+ agent_id="my-agent",
+)
+
+# Use OpenAI client normally
+client = OpenAI(api_key="sk-...")
+
+response = client.chat.completions.create(
+ model="gpt-4",
+ messages=[{"role": "user", "content": "What did we discuss about AI?"}]
+)
+```
+
+## How It Works
+
+The wrapper intercepts OpenAI calls:
+
+1. **Before**: Retrieves relevant memories and injects as system message
+2. **After**: Stores conversation to Hindsight
+
+Your code works exactly as before, but now has memory.
+
+## Configuration
+
+```python
+configure(
+ hindsight_api_url="http://localhost:8888", # Hindsight API
+ agent_id="my-agent", # Required
+ store_conversations=True, # Store conversations
+ inject_memories=True, # Inject memories into prompts
+ document_id="session-123", # Group by document
+ enabled=True, # Master switch
+)
+```
+
+## Memory Injection
+
+When enabled, memories are automatically injected:
+
+```python
+# Your code
+messages = [{"role": "user", "content": "What trails did Alice recommend?"}]
+
+# What gets sent to OpenAI
+messages = [
+ {
+ "role": "system",
+ "content": "Relevant context:\n- Alice loves hiking in Yosemite\n- Alice recommended Half Dome trail"
+ },
+ {"role": "user", "content": "What trails did Alice recommend?"}
+]
+```
+
+## Async Support
+
+```python
+from hindsight_openai import configure, AsyncOpenAI
+
+configure(hindsight_api_url="http://localhost:8888", agent_id="my-agent")
+
+client = AsyncOpenAI(api_key="sk-...")
+
+response = await client.chat.completions.create(
+ model="gpt-4",
+ messages=[{"role": "user", "content": "Tell me about my preferences"}]
+)
+```
+
+## Streaming
+
+Fully supported:
+
+```python
+stream = client.chat.completions.create(
+ model="gpt-4",
+ messages=[{"role": "user", "content": "Tell me a story"}],
+ stream=True,
+)
+
+for chunk in stream:
+ print(chunk.choices[0].delta.content or "", end="")
+```
+
+## Disable Temporarily
+
+```python
+from hindsight_openai import configure
+
+configure(enabled=False) # Disable
+configure(enabled=True) # Re-enable
+```
+
+
+---
diff --git a/llms.txt b/llms.txt
new file mode 100644
index 00000000..77fbd94e
--- /dev/null
+++ b/llms.txt
@@ -0,0 +1,88 @@
+# Hindsight
+
+> Agent Memory that Works Like Human Memory
+
+Hindsight is an agent memory system that gives AI agents persistent, structured memory across sessions. It extracts facts, entities, and relationships from conversations and enables temporal reasoning, opinion formation, and multi-strategy retrieval.
+
+For complete documentation, see: https://vectorize-io.github.io/hindsight/llms-full.txt
+
+## Core Operations
+
+- **Retain**: Store memories (extracts facts, entities, relationships automatically)
+- **Recall**: Retrieve memories (semantic, keyword, graph, temporal search)
+- **Reflect**: Deep analysis to form opinions and insights
+
+## Quick Start
+
+```python
+from hindsight import HindsightClient
+
+client = HindsightClient(base_url="http://localhost:8888")
+
+# Store
+client.retain(bank_id="my-agent", content="Alice works at Google as a software engineer")
+
+# Query
+results = client.recall(bank_id="my-agent", query="What does Alice do?")
+
+# Reflect
+response = client.reflect(bank_id="my-agent", query="Tell me about Alice")
+```
+
+## Key Concepts
+
+### Memory Banks
+Each bank is an isolated memory store. One bank per user/agent. Banks contain facts, entities, documents, and their relationships.
+
+### Memory Types
+- World facts: General knowledge
+- Experience facts: Personal experiences
+- Opinion facts: Beliefs with confidence scores
+
+### Document ID for Evolving Conversations
+Use `document_id` to group messages in a conversation. Retaining with the same `document_id` replaces the previous version (upsert), keeping memory consistent as conversations evolve.
+
+```python
+client.retain(
+ bank_id="user-123",
+ content=messages,
+ document_id="session_abc" # Same ID = replace old version
+)
+```
+
+## Documentation
+
+- Docs: https://vectorize-io.github.io/hindsight
+- GitHub: https://github.com/vectorize-io/hindsight
+- Python client: pip install hindsight-client
+- TypeScript client: npm install @vectorize-io/hindsight-client
+
+## API Reference
+
+Base URL: http://localhost:8888 (default)
+
+### POST /v1/default/banks/{bank_id}/retain
+Store memories in a bank.
+
+### POST /v1/default/banks/{bank_id}/recall
+Retrieve memories matching a query.
+
+### POST /v1/default/banks/{bank_id}/reflect
+Analyze memories and form opinions/insights.
+
+### GET /v1/default/banks/{bank_id}/profile
+Get bank profile (disposition, background).
+
+### PUT /v1/default/banks/{bank_id}/profile
+Update bank disposition and background.
+
+## Architecture Patterns
+
+### Per-User Memory
+One bank per user. Simplest pattern for chatbots and assistants.
+
+### Support Agent + Shared Knowledge
+User bank + shared docs bank. Client orchestrates queries to both banks and merges results.
+
+### With Curated Learnings
+User bank + shared docs + learnings bank. Promote verified solutions to shared learnings.