diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index f574903e..c18d8691 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -1297,7 +1297,6 @@ jobs:
test-doc-examples:
runs-on: ubuntu-latest
- needs: test-rust-cli
env:
HINDSIGHT_API_LLM_PROVIDER: vertexai
HINDSIGHT_API_LLM_VERTEXAI_SERVICE_ACCOUNT_KEY: /tmp/gcp-credentials.json
@@ -1315,14 +1314,23 @@ jobs:
PROJECT_ID=$(jq -r '.project_id' /tmp/gcp-credentials.json)
echo "HINDSIGHT_API_LLM_VERTEXAI_PROJECT_ID=$PROJECT_ID" >> $GITHUB_ENV
- - name: Download CLI artifact
- uses: actions/download-artifact@v4
- with:
- name: hindsight-cli
- path: /usr/local/bin
+ - name: Install Rust
+ uses: dtolnay/rust-toolchain@stable
- - name: Make CLI executable
- run: chmod +x /usr/local/bin/hindsight
+ - name: Cache cargo
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.cargo/registry
+ ~/.cargo/git
+ hindsight-cli/target
+ key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
+
+ - name: Build CLI
+ working-directory: hindsight-cli
+ run: |
+ cargo build --release
+ cp target/release/hindsight /usr/local/bin/hindsight
- name: Install uv
uses: astral-sh/setup-uv@v5
diff --git a/hindsight-dev/hindsight_dev/sync_cookbook.py b/hindsight-dev/hindsight_dev/sync_cookbook.py
index 7794264c..f7b5809f 100644
--- a/hindsight-dev/hindsight_dev/sync_cookbook.py
+++ b/hindsight-dev/hindsight_dev/sync_cookbook.py
@@ -29,16 +29,9 @@ IGNORE_DIRS = {".git", "notebooks", "node_modules", "__pycache__", ".venv", "ven
def get_docs_dir() -> Path:
- """Find the hindsight-docs directory relative to this script."""
- # Navigate from hindsight-dev to hindsight-docs
+ """Find the hindsight-docs src/pages/cookbook directory relative to this script."""
script_dir = Path(__file__).parent
- docs_dir = script_dir.parent.parent / "hindsight-docs" / "docs" / "cookbook"
- return docs_dir
-
-
-def get_sidebars_file() -> Path:
- script_dir = Path(__file__).parent
- return script_dir.parent.parent / "hindsight-docs" / "sidebars.ts"
+ return script_dir.parent.parent / "hindsight-docs" / "src" / "pages" / "cookbook"
def slugify(filename: str) -> str:
@@ -82,30 +75,27 @@ def extract_description_from_notebook(notebook_path: Path) -> str | None:
return None
-def extract_tags_from_notebook(notebook_path: Path) -> list[str]:
+def extract_tags_from_notebook(notebook_path: Path) -> dict[str, str]:
"""Extract tags from notebook metadata.
Supports both array format and structured object format.
+ Returns a dict with keys like 'sdk', 'topic', 'language'.
"""
try:
content = json.loads(notebook_path.read_text())
metadata = content.get("metadata", {})
tags = metadata.get("tags", [])
- # Array format: ["Python", "Client"]
- if isinstance(tags, list):
- return tags
-
- # Object format: { "language": "Python", "sdk": "Client", "topic": "Learning" }
+ # Object format already has the right structure
if isinstance(tags, dict):
- result = []
- for key in ["language", "sdk", "topic"]:
- if key in tags and tags[key]:
- result.append(tags[key])
- return result
+ return {k: v for k, v in tags.items() if v}
+
+ # Array format: fall back to heuristic conversion
+ if isinstance(tags, list):
+ return _infer_tags_from_list(tags)
except Exception:
pass
- return []
+ return {}
def extract_description_from_readme(readme_path: Path) -> str | None:
@@ -129,24 +119,24 @@ def extract_description_from_readme(readme_path: Path) -> str | None:
return None
-def extract_tags_from_readme(readme_path: Path) -> list[str]:
+def extract_tags_from_readme(readme_path: Path) -> dict[str, str]:
"""Extract tags from frontmatter in README if present.
Supports multiple formats:
- Array: tags: ["Python", "Client"]
- - Structured YAML: tags:\n language: "Python"\n sdk: "Client"
- - Object literal: tags: { language: "Python", sdk: "Client" }
+ - Structured YAML: tags:\n sdk: "hindsight-client"\n topic: "Learning"
+ - Object literal: tags: { sdk: "hindsight-client", topic: "Learning" }
+
+ Returns a dict with keys like 'sdk', 'topic', 'language'.
"""
try:
content = readme_path.read_text()
- # Check for frontmatter
if content.startswith("---"):
end_idx = content.find("---", 3)
if end_idx > 0:
frontmatter = content[3:end_idx]
lines = frontmatter.split("\n")
- # Look for tags: line
for i, line in enumerate(lines):
if line.strip().startswith("tags:"):
tags_str = line.split("tags:", 1)[1].strip()
@@ -154,51 +144,47 @@ def extract_tags_from_readme(readme_path: Path) -> list[str]:
# Inline array format: tags: ["Python", "Client"]
if tags_str.startswith("["):
tags_str = tags_str.strip("[]")
- return [t.strip().strip('"').strip("'") for t in tags_str.split(",")]
+ values = [t.strip().strip('"').strip("'") for t in tags_str.split(",")]
+ return _infer_tags_from_list(values)
- # JavaScript object literal format: tags: { language: "Python", sdk: "Client", topic: "Learning" }
+ # Object literal: tags: { sdk: "hindsight-client", topic: "Learning" }
if tags_str.startswith("{"):
- tags = []
- # Extract the entire object literal (might span multiple lines)
obj_str = tags_str
if "}" not in obj_str:
- # Multi-line object - collect remaining lines
for j in range(i + 1, len(lines)):
obj_str += " " + lines[j].strip()
if "}" in lines[j]:
break
-
- # Parse the object literal
- obj_str = obj_str.strip("{}")
- # Split by comma and extract key-value pairs
- for pair in obj_str.split(","):
+ result = {}
+ for pair in obj_str.strip("{}").split(","):
if ":" in pair:
- key, value = pair.split(":", 1)
- value = value.strip().strip('"').strip("'")
- if value:
- tags.append(value)
- return tags
+ k, v = pair.split(":", 1)
+ k = k.strip().strip('"').strip("'")
+ v = v.strip().strip('"').strip("'")
+ if k and v:
+ result[k] = v
+ return result
- # Structured YAML format:
+ # Structured YAML:
# tags:
- # language: "Python"
- # sdk: "Client"
- if not tags_str or tags_str == "":
- # Parse structured tags from following lines
- tags = []
+ # sdk: "hindsight-client"
+ # topic: "Learning"
+ if not tags_str:
+ result = {}
for j in range(i + 1, len(lines)):
next_line = lines[j].strip()
if not next_line or not next_line.startswith(("language:", "sdk:", "topic:")):
break
- # Extract value
if ":" in next_line:
- value = next_line.split(":", 1)[1].strip().strip('"').strip("'")
- if value:
- tags.append(value)
- return tags
+ k, v = next_line.split(":", 1)
+ k = k.strip()
+ v = v.strip().strip('"').strip("'")
+ if k and v:
+ result[k] = v
+ return result
except Exception:
pass
- return []
+ return {}
def extract_title_from_readme(readme_path: Path) -> str | None:
@@ -364,6 +350,17 @@ def process_applications(cookbook_dir: Path, apps_dir: Path) -> list[dict]:
if not readme_path.exists():
continue
+ # Validate that README has frontmatter
+ readme_raw = readme_path.read_text()
+ if not readme_raw.startswith("---"):
+ raise SystemExit(
+ f"Error: {readme_path} is missing frontmatter.\n"
+ f"Applications must have a frontmatter block (---) with 'description' and 'tags'."
+ )
+ closing = readme_raw.find("---", 3)
+ if closing <= 0:
+ raise SystemExit(f"Error: {readme_path} has malformed frontmatter (missing closing ---).")
+
slug = entry.name
title = extract_title_from_readme(readme_path) or " ".join(word.capitalize() for word in slug.split("-"))
description = extract_description_from_readme(readme_path)
@@ -371,9 +368,10 @@ def process_applications(cookbook_dir: Path, apps_dir: Path) -> list[dict]:
print(f" Processing app: {entry.name} → {slug}.md")
- # Read README content and strip existing frontmatter
+ # Read README content, strip existing frontmatter and local .md links
readme_content = readme_path.read_text()
readme_content = strip_frontmatter(readme_content)
+ readme_content = strip_local_md_links(readme_content)
# Create application page with frontmatter
app_url = f"https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/{entry.name}"
@@ -460,6 +458,14 @@ def update_sidebars(recipes: list[dict], apps: list[dict], sidebars_file: Path):
print("\nUpdated sidebars.ts")
+def strip_local_md_links(content: str) -> str:
+ """Replace relative .md links with plain text to avoid broken links in Docusaurus.
+
+ e.g. [see article](article.md) → see article
+ """
+ return re.sub(r"\[([^\]]+)\]\((?!https?://)([^)]+\.md)\)", r"\1", content)
+
+
def clean_description(desc: str) -> str:
"""Clean description for display in carousel cards."""
if not desc:
@@ -482,34 +488,19 @@ def clean_description(desc: str) -> str:
return desc
-def convert_tags_to_structured(tags: list[str]) -> dict[str, str]:
- """Convert list of tags to structured format.
+def _infer_tags_from_list(tags: list[str]) -> dict[str, str]:
+ """Infer sdk/topic structure from a plain list of tag values (legacy array format).
- New format has 2 tags:
- - sdk: Package name (detected from tag values)
- - topic: anything else (Learning, Quick Start, etc.)
-
- Supported languages:
- - Node.js: packages starting with '@vectorize-io'
- - Go: packages ending with '-go' or containing 'go-'
- - Python: everything else
+ Uses heuristics: package names contain '@' or '-' or start lowercase → sdk,
+ everything else → topic.
"""
- structured = {}
- topic_tags = {"Learning", "Quick Start", "Recommendation", "Chat"}
-
+ result: dict[str, str] = {}
for tag in tags:
- # Check if it's a topic tag
- if tag in topic_tags:
- structured["topic"] = tag
- # Check if it's already a package name (contains @ or -)
- elif "@" in tag or (tag and not tag[0].isupper()):
- structured["sdk"] = tag
+ if "@" in tag or (tag and not tag[0].isupper()):
+ result["sdk"] = tag
else:
- # Legacy tag values - map to new format
- # For now, treat everything else as SDK/package identifier
- structured["sdk"] = tag
-
- return structured
+ result["topic"] = tag
+ return result
def update_cookbook_index(recipes: list[dict], apps: list[dict], docs_dir: Path):
@@ -521,21 +512,16 @@ def update_cookbook_index(recipes: list[dict], apps: list[dict], docs_dir: Path)
description = r.get("description", "")
if description:
description = clean_description(description).replace('"', '\\"')
- tags = r.get("tags", [])
+ tags: dict[str, str] = r.get("tags", {})
item = f' {{\n title: "{title}",\n href: "/cookbook/recipes/{r["slug"]}"'
if description:
item += f',\n description: "{description}"'
if tags:
- # Convert tags list to structured format
- structured_tags = convert_tags_to_structured(tags)
tags_parts = []
- if "language" in structured_tags:
- tags_parts.append(f'language: "{structured_tags["language"]}"')
- if "sdk" in structured_tags:
- tags_parts.append(f'sdk: "{structured_tags["sdk"]}"')
- if "topic" in structured_tags:
- tags_parts.append(f'topic: "{structured_tags["topic"]}"')
+ for key in ("language", "sdk", "topic"):
+ if key in tags:
+ tags_parts.append(f'{key}: "{tags[key]}"')
if tags_parts:
item += f",\n tags: {{ {', '.join(tags_parts)} }}"
item += "\n }"
@@ -550,21 +536,16 @@ def update_cookbook_index(recipes: list[dict], apps: list[dict], docs_dir: Path)
description = a.get("description", "")
if description:
description = clean_description(description).replace('"', '\\"')
- tags = a.get("tags", [])
+ tags = a.get("tags", {})
item = f' {{\n title: "{title}",\n href: "/cookbook/applications/{a["slug"]}"'
if description:
item += f',\n description: "{description}"'
if tags:
- # Convert tags list to structured format
- structured_tags = convert_tags_to_structured(tags)
tags_parts = []
- if "language" in structured_tags:
- tags_parts.append(f'language: "{structured_tags["language"]}"')
- if "sdk" in structured_tags:
- tags_parts.append(f'sdk: "{structured_tags["sdk"]}"')
- if "topic" in structured_tags:
- tags_parts.append(f'topic: "{structured_tags["topic"]}"')
+ for key in ("language", "sdk", "topic"):
+ if key in tags:
+ tags_parts.append(f'{key}: "{tags[key]}"')
if tags_parts:
item += f",\n tags: {{ {', '.join(tags_parts)} }}"
item += "\n }"
@@ -573,34 +554,42 @@ def update_cookbook_index(recipes: list[dict], apps: list[dict], docs_dir: Path)
apps_json = ",\n".join(app_items)
content = f"""---
-sidebar_position: 1
+title: Cookbook
hide_table_of_contents: true
-pagination_next: null
-pagination_prev: null
-custom_edit_url: null
-sidebar_class_name: hidden-sidebar
---
-import RecipeCarousel from '@site/src/components/RecipeCarousel';
+import CookbookGrid from '@site/src/components/CookbookGrid';
-
+
-# Cookbook
+
+
Cookbook
+
+ Practical examples and complete applications built with Hindsight.
+
+
-Learn how to build with Hindsight through practical examples:
+## Recipes
-- **[Recipes](#recipes)** - Step-by-step guides and patterns for common use cases
-- **[Applications](#applications)** - Complete, runnable applications demonstrating Hindsight integration
-
-
-
;
+}
+
function Card({title, href, description, tags}: CookbookCard) {
return (
@@ -25,7 +46,12 @@ function Card({title, href, description, tags}: CookbookCard) {
{(tags?.topic || tags?.sdk) && (
{tags.topic && {tags.topic}}
- {tags.sdk && {tags.sdk}}
+ {tags.sdk && (
+
+
+ {tags.sdk}
+
+ )}
)}
@@ -34,11 +60,68 @@ function Card({title, href, description, tags}: CookbookCard) {
}
export default function CookbookGrid({items}: CookbookGridProps) {
+ const [selectedTopic, setSelectedTopic] = useState
(null);
+ const [selectedSdk, setSelectedSdk] = useState(null);
+
+ const topics = [...new Set(items.map((i) => i.tags?.topic).filter(Boolean))] as string[];
+ const sdks = [...new Set(items.map((i) => i.tags?.sdk).filter(Boolean))] as string[];
+
+ const filtered = items.filter((item) => {
+ if (selectedTopic && item.tags?.topic !== selectedTopic) return false;
+ if (selectedSdk && item.tags?.sdk !== selectedSdk) return false;
+ return true;
+ });
+
+ const hasFilters = topics.length > 1 || sdks.length > 1;
+
return (
-
- {items.map((item) => (
-
- ))}
+
+ {hasFilters && (
+
+ {topics.length > 1 && (
+
+ Topic
+
+ {topics.map((topic) => (
+
+ ))}
+
+ )}
+ {sdks.length > 1 && (
+
+ SDK
+
+ {sdks.map((sdk) => (
+
+ ))}
+
+ )}
+
+ )}
+
+ {filtered.map((item) => (
+
+ ))}
+
);
}
diff --git a/hindsight-docs/src/css/custom.css b/hindsight-docs/src/css/custom.css
index 9ef4a8a8..9eccdff7 100644
--- a/hindsight-docs/src/css/custom.css
+++ b/hindsight-docs/src/css/custom.css
@@ -396,7 +396,7 @@ a.menu__link[href*="/sdks/python"]::before {
/* Node.js logo */
a.menu__link[href*="/sdks/nodejs"]::before {
- background-image: url('/img/icons/nodejs.svg');
+ background-image: url('/img/icons/nodejs.png');
}
/* CLI - terminal icon */
diff --git a/hindsight-docs/src/pages/cookbook/applications/cable-co.md b/hindsight-docs/src/pages/cookbook/applications/cable-co.md
new file mode 100644
index 00000000..1666f2e7
--- /dev/null
+++ b/hindsight-docs/src/pages/cookbook/applications/cable-co.md
@@ -0,0 +1,143 @@
+---
+sidebar_position: 1
+---
+
+# CableConnect — AI Customer Service Copilot Demo
+
+
+:::info Complete Application
+This is a complete, runnable application demonstrating Hindsight integration.
+[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/cable-co)
+:::
+
+
+An AI copilot that assists a customer service representative (CSR) by suggesting responses and actions for simulated customer scenarios. The CSR approves or rejects each suggestion with feedback. The copilot learns from corrections via [Hindsight](https://hindsight.vectorize.io) and stops repeating mistakes.
+
+## Prerequisites
+
+- Python 3.11+
+- Node.js 18+
+- An OpenAI API key (for GPT-4o)
+- A Hindsight API key ([sign up](https://hindsight.vectorize.io))
+
+## Quick Start
+
+### 1. Backend
+
+```bash
+cd backend
+
+# Create and activate a virtual environment
+python -m venv venv
+source venv/bin/activate
+
+# Install dependencies
+pip install -r requirements.txt
+
+# Create a .env file with your credentials
+cat > .env << 'EOF'
+OPENAI_API_KEY=sk-your-openai-key
+HINDSIGHT_API_KEY=hsk_your-hindsight-key
+HINDSIGHT_API_URL=https://api.hindsight.vectorize.io
+HINDSIGHT_BANK_NAME=cable-connect-demo
+EOF
+
+# Start the backend (port 8002)
+./run.sh
+```
+
+### 2. Frontend
+
+In a second terminal:
+
+```bash
+cd frontend
+
+# Install dependencies
+npm install
+
+# Start the dev server (port 5173)
+npm run dev
+```
+
+Open http://localhost:5173 in your browser.
+
+## Running the Demo
+
+1. Click **Next Customer** to load the first scenario
+2. The AI copilot will analyze the customer's issue and suggest a response
+3. Review the suggestion in the right panel:
+ - **Send to Customer** — approves the response, sends it to the customer chat
+ - **Approve** — executes a system action (credit, dispatch, etc.)
+ - **Reject** — type feedback explaining what was wrong
+4. The copilot adjusts based on your feedback and tries again
+5. Continue until the customer is satisfied, then approve the resolve action
+6. Click **Next Customer** for the next scenario
+
+### What to Watch For
+
+The 8 scenarios include 3 **learning pairs** — the first scenario teaches the agent a rule, the second tests whether it remembers:
+
+| Pair | Scenarios | What the Agent Learns |
+|------|-----------|----------------------|
+| A | 2 then 4 | Credit adjustments are capped at $25 |
+| B | 3 then 8 | Run remote diagnostics before scheduling a dispatch |
+| C | 5 then 6 | Retention offers require 24+ months of tenure |
+
+With **Memory On** (the default), the copilot recalls past CSR feedback before each new customer. By the test scenario, it should handle the situation correctly without being corrected.
+
+Toggle **Memory Off** to see how the agent behaves without learning — it will make the same mistakes every time.
+
+### Controls
+
+- **Mode** dropdown — Switch between Memory On and Memory Off
+- **Reset** — Deletes all stored memories and starts the scenario queue over
+- **Refresh Models** — Manually triggers a refresh of the agent's mental models
+
+## Configuration
+
+All configuration is via environment variables in `backend/.env`:
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `OPENAI_API_KEY` | — | Your OpenAI API key (required) |
+| `HINDSIGHT_API_KEY` | — | Your Hindsight API key (required) |
+| `HINDSIGHT_API_URL` | `https://api.hindsight.vectorize.io` | Hindsight API endpoint |
+| `HINDSIGHT_BANK_NAME` | `cable-connect-demo` | Name of the memory bank |
+| `LLM_MODEL` | `openai/gpt-4o` | LLM model (via LiteLLM format) |
+| `BACKEND_PORT` | `8002` | Backend server port |
+
+## Project Structure
+
+```
+cable-co/
+├── backend/
+│ ├── run.sh # Start script (loads .env, runs uvicorn)
+│ ├── requirements.txt
+│ ├── telecom_data.py # Accounts, plans, billing, outages, scenarios
+│ ├── agent_tools.py # 19 tools + business rule hints
+│ └── app/
+│ ├── main.py # FastAPI + WebSocket
+│ ├── config.py
+│ └── services/
+│ ├── agent_service.py # Copilot loop with CSR approval gate
+│ └── memory_service.py # Hindsight retain/recall/mental models
+├── frontend/
+│ ├── package.json
+│ ├── vite.config.ts
+│ └── src/
+│ ├── App.tsx
+│ ├── stores/sessionStore.ts
+│ ├── hooks/useWebSocket.ts
+│ └── components/
+│ ├── ControlBar.tsx
+│ ├── CustomerChat.tsx
+│ ├── CopilotChat.tsx
+│ ├── KnowledgePanel.tsx
+│ └── MentalModelsPanel.tsx
+└── article.md # Detailed writeup of how agent learning works
+```
+
+## How It Works
+
+See article.md for a detailed explanation of the agent learning architecture, including how Hindsight transforms CSR feedback into observations and mental models that improve the copilot's behavior over time.
diff --git a/hindsight-docs/src/pages/cookbook/applications/chat-memory-cloud.md b/hindsight-docs/src/pages/cookbook/applications/chat-memory-cloud.md
new file mode 100644
index 00000000..c8ac2aab
--- /dev/null
+++ b/hindsight-docs/src/pages/cookbook/applications/chat-memory-cloud.md
@@ -0,0 +1,122 @@
+---
+sidebar_position: 3
+---
+
+# Chat Memory App (Hindsight Cloud)
+
+
+:::info Complete Application
+This is a complete, runnable application demonstrating Hindsight integration.
+[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/chat-memory-cloud)
+:::
+
+
+A demo chat application with persistent per-user memory powered by [Hindsight Cloud](https://hindsight.vectorize.io). Supports OpenAI or Groq as the LLM provider. No local Hindsight server required.
+
+## Features
+
+- 🧠 **Persistent Memory**: Each user gets their own memory bank that remembers conversations
+- ☁️ **Hindsight Cloud**: Memory stored in the cloud — no Docker setup needed
+- 🔀 **Selectable LLM**: Choose between OpenAI (GPT-4o) or Groq (Qwen 32B)
+- 🎯 **Per-User Context**: Isolated memory per user with automatic context retrieval
+- 💬 **Real-time Chat**: Instant responses with memory-augmented context
+
+## Setup
+
+### 1. Get API Keys
+
+- **Hindsight** — Sign up at https://hindsight.vectorize.io
+- **OpenAI** — https://platform.openai.com/api-keys
+- **Groq** (alternative) — Free at https://console.groq.com/home
+
+### 2. Configure Environment
+
+Edit `.env.local` with your API keys and preferred provider:
+
+```bash
+# LLM Provider: "openai" or "groq"
+LLM_PROVIDER=openai
+
+# OpenAI (required if LLM_PROVIDER=openai)
+OPENAI_API_KEY=sk-your-key-here
+
+# Groq (required if LLM_PROVIDER=groq)
+GROQ_API_KEY=gsk_your-key-here
+
+# Hindsight Cloud
+HINDSIGHT_API_URL=https://api.hindsight.vectorize.io
+HINDSIGHT_API_KEY=hsk_your-key-here
+```
+
+You can also override the model with `LLM_MODEL` (defaults to `gpt-4o` for OpenAI, `qwen/qwen3-32b` for Groq).
+
+### 3. Install Dependencies
+
+```bash
+npm install
+```
+
+### 4. Run the App
+
+```bash
+npm run dev
+```
+
+Open http://localhost:3000 in your browser.
+
+## How It Works
+
+1. **User Identity**: Each browser session gets a unique user ID
+2. **Memory Bank Creation**: First message creates a personal memory bank in Hindsight Cloud
+3. **Context Retrieval**: Before responding, relevant memories are recalled
+4. **Memory Augmented Response**: LLM generates responses with memory context
+5. **Conversation Storage**: Each conversation is retained for future context
+
+## Architecture
+
+```
+User Message
+ ↓
+Next.js API Route (/api/chat)
+ ↓
+Hindsight Cloud recall() → Get relevant memories
+ ↓
+OpenAI or Groq → Generate response with memory context
+ ↓
+Hindsight Cloud retain() → Store conversation
+ ↓
+Response to User
+```
+
+## Memory Bank Structure
+
+Each user gets their own isolated memory bank with:
+- **Name**: "Chat Memory for [userId]"
+- **Background**: Conversational AI assistant context
+- **Disposition**: Empathetic (4), Low Skepticism (2), Balanced Literalism (3)
+
+## Try It Out
+
+1. **First Conversation**: Tell the assistant about yourself
+ - "Hi! I'm a software engineer from San Francisco. I love Python and machine learning."
+
+2. **Second Conversation**: Ask what it remembers
+ - "What do you know about me?"
+ - "What programming languages do I like?"
+
+3. **Context Building**: Continue sharing preferences
+ - "I prefer VS Code over other editors"
+ - "I'm working on a React project"
+
+4. **Memory Verification**: Log in to the [Hindsight dashboard](https://hindsight.vectorize.io) to see stored memories
+
+## Configuration
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `LLM_PROVIDER` | `openai` | LLM provider: `openai` or `groq` |
+| `LLM_MODEL` | auto | Model override (defaults: `gpt-4o` / `qwen/qwen3-32b`) |
+| `OPENAI_API_KEY` | — | Required when using OpenAI |
+| `GROQ_API_KEY` | — | Required when using Groq |
+| `HINDSIGHT_API_URL` | `https://api.hindsight.vectorize.io` | Hindsight API endpoint |
+| `HINDSIGHT_API_KEY` | — | Your Hindsight API key |
diff --git a/hindsight-docs/src/pages/cookbook/applications/chat-memory.md b/hindsight-docs/src/pages/cookbook/applications/chat-memory.md
index cf36aa9e..d5e191ab 100644
--- a/hindsight-docs/src/pages/cookbook/applications/chat-memory.md
+++ b/hindsight-docs/src/pages/cookbook/applications/chat-memory.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 1
+sidebar_position: 2
---
# Chat Memory App
diff --git a/hindsight-docs/src/pages/cookbook/applications/chat-sdk-multi-platform.md b/hindsight-docs/src/pages/cookbook/applications/chat-sdk-multi-platform.md
index 3f780aac..424f7808 100644
--- a/hindsight-docs/src/pages/cookbook/applications/chat-sdk-multi-platform.md
+++ b/hindsight-docs/src/pages/cookbook/applications/chat-sdk-multi-platform.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 2
+sidebar_position: 4
---
# Chat SDK Multi-Platform Bot
diff --git a/hindsight-docs/src/pages/cookbook/applications/claims-iq.md b/hindsight-docs/src/pages/cookbook/applications/claims-iq.md
new file mode 100644
index 00000000..ac61c3f9
--- /dev/null
+++ b/hindsight-docs/src/pages/cookbook/applications/claims-iq.md
@@ -0,0 +1,81 @@
+---
+sidebar_position: 5
+---
+
+# ClaimsIQ — Insurance Claims Triage Agent Demo
+
+
+:::info Complete Application
+This is a complete, runnable application demonstrating Hindsight integration.
+[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/claims-iq)
+:::
+
+
+An AI agent that processes insurance claims through a multi-step workflow. The agent starts as a "confused rookie" and becomes a "seasoned expert" as [Hindsight](https://github.com/anthropics/hindsight) memories accumulate.
+
+Watch the agent learn coverage rules, adjuster assignments, and escalation patterns in real-time through a pipeline dashboard.
+
+## Quick Start
+
+### 1. Start Hindsight API (port 8888)
+
+```bash
+docker run -p 8888:8888 ghcr.io/anthropics/hindsight:latest
+```
+
+### 2. Start Backend (port 8000)
+
+```bash
+cd backend
+pip install -r requirements.txt
+./run.sh
+```
+
+### 3. Start Frontend (port 5173)
+
+```bash
+cd frontend
+npm install
+npm run dev
+```
+
+### 4. Open Browser
+
+Navigate to `http://localhost:5173`.
+
+## How It Works
+
+The agent processes insurance claims using 6 tools:
+
+1. **Classify** the claim category (auto, property, flood, etc.)
+2. **Look up** the policy details
+3. **Check coverage** rules for the policy type
+4. **Check fraud** indicators
+5. **Assign** the right adjuster
+6. **Submit** a decision for validation
+
+The system validates each decision against ground truth. If the agent makes a mistake (wrong adjuster, incorrect coverage call), the decision is rejected with feedback — creating learning signal for Hindsight.
+
+## Agent Modes
+
+| Mode | Description |
+|------|-------------|
+| **No Memory** | Baseline — agent starts fresh every claim |
+| **Recall** | Raw facts from past claims injected before processing |
+| **Reflect** | LLM-synthesized knowledge injected |
+| **Mental Models** | Full Hindsight mental models with auto-refresh |
+
+## Key Learning Challenges
+
+- **Water damage vs Flood**: Gold policies cover water damage (burst pipe) but NOT flood damage (rain/river). The agent must learn this subtle distinction.
+- **Adjuster routing**: 8 adjusters with different specialties and regions. The agent must learn who handles what.
+- **Escalation thresholds**: Claims over $50K need a senior adjuster; over $100K need manager review.
+- **Fraud detection**: Multiple indicators (near-limit claims, repeated address) route to the fraud specialist.
+
+## Environment Variables
+
+| Variable | Default | Description |
+|----------|---------|-------------|
+| `LLM_MODEL` | `openai/gpt-4o` | LLM model for the agent |
+| `HINDSIGHT_API_URL` | `http://localhost:8888` | Hindsight API URL |
+| `BACKEND_PORT` | `8000` | Backend server port |
diff --git a/hindsight-docs/src/pages/cookbook/applications/crewai-memory.md b/hindsight-docs/src/pages/cookbook/applications/crewai-memory.md
index b86a0c09..68e8cd3b 100644
--- a/hindsight-docs/src/pages/cookbook/applications/crewai-memory.md
+++ b/hindsight-docs/src/pages/cookbook/applications/crewai-memory.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 3
+sidebar_position: 6
---
# CrewAI + Hindsight Memory
diff --git a/hindsight-docs/src/pages/cookbook/applications/deliveryman-demo.md b/hindsight-docs/src/pages/cookbook/applications/deliveryman-demo.md
index 89aebfdd..f056ab8c 100644
--- a/hindsight-docs/src/pages/cookbook/applications/deliveryman-demo.md
+++ b/hindsight-docs/src/pages/cookbook/applications/deliveryman-demo.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 4
+sidebar_position: 7
---
# Deliveryman Demo
diff --git a/hindsight-docs/src/pages/cookbook/applications/go-memory-service.md b/hindsight-docs/src/pages/cookbook/applications/go-memory-service.md
index aae3b5f5..b55c6f7f 100644
--- a/hindsight-docs/src/pages/cookbook/applications/go-memory-service.md
+++ b/hindsight-docs/src/pages/cookbook/applications/go-memory-service.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 5
+sidebar_position: 8
---
# Go Memory-Augmented API
diff --git a/hindsight-docs/src/pages/cookbook/applications/hindsight-litellm-demo.md b/hindsight-docs/src/pages/cookbook/applications/hindsight-litellm-demo.md
index b9aec100..fb8216bc 100644
--- a/hindsight-docs/src/pages/cookbook/applications/hindsight-litellm-demo.md
+++ b/hindsight-docs/src/pages/cookbook/applications/hindsight-litellm-demo.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 6
+sidebar_position: 9
---
# Memory Approaches Comparison Demo
diff --git a/hindsight-docs/src/pages/cookbook/applications/hindsight-tool-learning-demo.md b/hindsight-docs/src/pages/cookbook/applications/hindsight-tool-learning-demo.md
index c9e16642..3c3a3547 100644
--- a/hindsight-docs/src/pages/cookbook/applications/hindsight-tool-learning-demo.md
+++ b/hindsight-docs/src/pages/cookbook/applications/hindsight-tool-learning-demo.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 7
+sidebar_position: 10
---
# Tool Learning Demo
diff --git a/hindsight-docs/src/pages/cookbook/applications/openai-fitness-coach.md b/hindsight-docs/src/pages/cookbook/applications/openai-fitness-coach.md
index 969c5db1..30a24c1e 100644
--- a/hindsight-docs/src/pages/cookbook/applications/openai-fitness-coach.md
+++ b/hindsight-docs/src/pages/cookbook/applications/openai-fitness-coach.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 8
+sidebar_position: 11
---
# OpenAI Agent + Hindsight Memory Integration
diff --git a/hindsight-docs/src/pages/cookbook/applications/pydantic-ai-memory.md b/hindsight-docs/src/pages/cookbook/applications/pydantic-ai-memory.md
new file mode 100644
index 00000000..26d67404
--- /dev/null
+++ b/hindsight-docs/src/pages/cookbook/applications/pydantic-ai-memory.md
@@ -0,0 +1,236 @@
+---
+sidebar_position: 12
+---
+
+# Pydantic AI + Hindsight Memory
+
+
+:::info Complete Application
+This is a complete, runnable application demonstrating Hindsight integration.
+[**View source on GitHub →**](https://github.com/vectorize-io/hindsight-cookbook/tree/main/applications/pydantic-ai-memory)
+:::
+
+
+Give your Pydantic AI agents persistent long-term memory. Chat with an assistant multiple times and watch it remember what you told it in previous sessions.
+
+## What This Demonstrates
+
+- **Memory tools** — retain, recall, and reflect via `create_hindsight_tools()`
+- **Auto-injected context** — relevant memories in every run via `memory_instructions()`
+- **Persistent memory across sessions** — the agent remembers between script runs
+- **Interactive chat loop** with message history reuse
+
+## Architecture
+
+```
+Session 1:
+ You: "I'm a Python developer working on a FastAPI project"
+ │
+ ├─ memory_instructions() ──► recalls prior context (empty on first run)
+ ├─ Agent decides to call hindsight_retain ──► stores the fact
+ └─ Agent responds with acknowledgement
+
+Session 2:
+ You: "What do you know about me?"
+ │
+ ├─ memory_instructions() ──► injects "User is a Python developer..."
+ ├─ Agent calls hindsight_recall ──► finds stored facts
+ └─ Agent responds with everything it remembers
+```
+
+## Prerequisites
+
+1. **Hindsight running**
+
+ ```bash
+ export OPENAI_API_KEY=your-key
+
+ docker run --rm -it --pull always -p 8888:8888 -p 9999:9999 \
+ -e HINDSIGHT_API_LLM_API_KEY=$OPENAI_API_KEY \
+ -e HINDSIGHT_API_LLM_MODEL=o3-mini \
+ -v $HOME/.hindsight-docker:/home/hindsight/.pg0 \
+ ghcr.io/vectorize-io/hindsight:latest
+ ```
+
+2. **OpenAI API key** (for Pydantic AI's LLM)
+
+ ```bash
+ export OPENAI_API_KEY=your-key
+ ```
+
+3. **Install dependencies**
+
+ ```bash
+ cd applications/pydantic-ai-memory
+ pip install -r requirements.txt
+ ```
+
+## Quick Start
+
+### Interactive Chat
+
+```bash
+python personal_assistant.py
+```
+
+Example session:
+
+```
+Personal assistant ready (bank: personal-assistant)
+Type 'quit' or 'exit' to stop.
+
+You: I'm a Python developer and I love hiking on weekends
+Assistant: I've noted that! You're a Python developer who enjoys weekend hiking.
+
+You: What do you know about me?
+Assistant: From my memory, I know that you're a Python developer and you
+love hiking on weekends.
+
+You: quit
+```
+
+Run it again — the agent still remembers:
+
+```
+You: What are my hobbies?
+Assistant: Based on my memories, you enjoy hiking on weekends!
+```
+
+### Single Query
+
+```bash
+python personal_assistant.py "What do you remember about my preferences?"
+```
+
+### Reset Memory
+
+```bash
+python personal_assistant.py --reset
+```
+
+## How It Works
+
+### 1. Create a Hindsight Client
+
+```python
+from hindsight_client import Hindsight
+
+client = Hindsight(base_url="http://localhost:8888")
+```
+
+### 2. Create Memory Tools
+
+`create_hindsight_tools()` returns Pydantic AI `Tool` instances the agent can call:
+
+```python
+from hindsight_pydantic_ai import create_hindsight_tools
+
+tools = create_hindsight_tools(client=client, bank_id="personal-assistant")
+# Returns: [hindsight_retain, hindsight_recall, hindsight_reflect]
+```
+
+### 3. Add Memory Instructions
+
+`memory_instructions()` returns an async callable that auto-recalls relevant memories and injects them into the system prompt on every run:
+
+```python
+from hindsight_pydantic_ai import memory_instructions
+
+instructions_fn = memory_instructions(
+ client=client,
+ bank_id="personal-assistant",
+ query="important context about the user",
+ max_results=5,
+)
+```
+
+### 4. Wire Up the Agent
+
+```python
+from pydantic_ai import Agent
+
+agent = Agent(
+ "openai:gpt-4o-mini",
+ system_prompt="You are a helpful assistant with long-term memory...",
+ tools=tools,
+ instructions=[instructions_fn],
+)
+
+result = await agent.run("What do you know about me?")
+```
+
+## Core Files
+
+| File | Description |
+|------|-------------|
+| `personal_assistant.py` | Complete working example with interactive chat and single-query modes |
+| `requirements.txt` | Python dependencies |
+
+## Customization
+
+### Use Only Tools (No Auto-Injection)
+
+Let the agent decide when to search memory, rather than always injecting context:
+
+```python
+agent = Agent(
+ "openai:gpt-4o-mini",
+ tools=create_hindsight_tools(client=client, bank_id="my-bank"),
+)
+```
+
+### Use Only Instructions (No Tools)
+
+Auto-inject memories without giving the agent explicit retain/recall/reflect tools:
+
+```python
+agent = Agent(
+ "openai:gpt-4o-mini",
+ instructions=[memory_instructions(client=client, bank_id="my-bank")],
+)
+```
+
+### Select Specific Tools
+
+```python
+tools = create_hindsight_tools(
+ client=client,
+ bank_id="my-bank",
+ include_retain=True,
+ include_recall=True,
+ include_reflect=False, # Omit reflect
+)
+```
+
+### Use a Different Model
+
+Any [Pydantic AI model](https://ai.pydantic.dev/models/) works:
+
+```python
+agent = Agent(
+ "anthropic:claude-sonnet-4-20250514",
+ tools=create_hindsight_tools(client=client, bank_id="my-bank"),
+)
+```
+
+## Common Issues
+
+**"Connection refused"**
+- Make sure Hindsight is running on `localhost:8888`
+
+**"OPENAI_API_KEY not set"**
+```bash
+export OPENAI_API_KEY=your-key
+```
+
+**"No module named 'hindsight_pydantic_ai'"**
+```bash
+pip install -r requirements.txt
+```
+
+---
+
+**Built with:**
+- [Pydantic AI](https://ai.pydantic.dev) - Type-safe AI agent framework
+- [hindsight-pydantic-ai](https://github.com/vectorize-io/hindsight/tree/main/hindsight-integrations/pydantic-ai) - Hindsight memory tools for Pydantic AI
+- [Hindsight](https://github.com/vectorize-io/hindsight) - Long-term memory for AI agents
diff --git a/hindsight-docs/src/pages/cookbook/applications/sanity-blog-memory.md b/hindsight-docs/src/pages/cookbook/applications/sanity-blog-memory.md
index af4b0ed2..0fc6ef09 100644
--- a/hindsight-docs/src/pages/cookbook/applications/sanity-blog-memory.md
+++ b/hindsight-docs/src/pages/cookbook/applications/sanity-blog-memory.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 9
+sidebar_position: 13
---
# Sanity CMS Blog Memory
diff --git a/hindsight-docs/src/pages/cookbook/applications/stancetracker.md b/hindsight-docs/src/pages/cookbook/applications/stancetracker.md
index c7648061..b80c220c 100644
--- a/hindsight-docs/src/pages/cookbook/applications/stancetracker.md
+++ b/hindsight-docs/src/pages/cookbook/applications/stancetracker.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 10
+sidebar_position: 14
---
# Stance Tracker
diff --git a/hindsight-docs/src/pages/cookbook/applications/taste-ai.md b/hindsight-docs/src/pages/cookbook/applications/taste-ai.md
index a6aca6ad..8dbad64d 100644
--- a/hindsight-docs/src/pages/cookbook/applications/taste-ai.md
+++ b/hindsight-docs/src/pages/cookbook/applications/taste-ai.md
@@ -1,5 +1,5 @@
---
-sidebar_position: 11
+sidebar_position: 15
---
# Hindsight AI SDK - Personal Chef
diff --git a/hindsight-docs/src/pages/cookbook/index.mdx b/hindsight-docs/src/pages/cookbook/index.mdx
index e2a47aa7..16d10a9d 100644
--- a/hindsight-docs/src/pages/cookbook/index.mdx
+++ b/hindsight-docs/src/pages/cookbook/index.mdx
@@ -101,11 +101,23 @@ import CookbookGrid from '@site/src/components/CookbookGrid';
\ No newline at end of file
diff --git a/scripts/dev/start-docs.sh b/scripts/dev/start-docs.sh
index 17a0662b..bb259ecd 100755
--- a/scripts/dev/start-docs.sh
+++ b/scripts/dev/start-docs.sh
@@ -14,4 +14,4 @@ echo ""
echo "Starting Docusaurus development server..."
echo "Documentation will be available at: http://localhost:3000"
echo ""
-npm run start -w hindsight-docs
+npm run start -w hindsight-docs -- --no-open