fleet-memory/hindsight-docs/docs/developer/configuration.md
Nicolò Boschi 8d731f2e5f
feat: implement hierarchical configuration (system, tenant, bank) (#329)
* feat: implement hierarchical configuration (system, tenant, bank)

* feat: implement hierarchical configuration (system, tenant, bank)

* docs: add instructions for hierarchical config in CLAUDE.md

* feat: add ENABLE_BANK_CONFIG_API flag (disabled by default)

- Add HINDSIGHT_API_ENABLE_BANK_CONFIG_API env var (default: false)
- Return 403 Forbidden from bank config endpoints when disabled
- Update tests to enable the flag
- Update CLAUDE.md documentation

This provides security control over the bank configuration API,
ensuring it's only accessible when explicitly enabled.

* docs: add hierarchical configuration section

* feat(cli): add bank config commands (config, set-config, reset-config)

- Add 'hindsight bank config' to view bank configuration
- Add 'hindsight bank set-config' to update LLM settings per bank
- Add 'hindsight bank reset-config' to reset to defaults
- Implements client API calls to new bank config endpoints

* fix(cli): fix compilation errors in bank config commands

- Fix type signature: use ApiClient instead of api::Client
- Fix confirmation: use ui::prompt_confirmation instead of ui::confirm
- Fix error handling: use anyhow! macro instead of errors::Error
- Fix type conversion: convert HashMap to serde_json::Map for API call

* feat: implement type-safe hierarchical config with bank overrides

Implements a production-ready hierarchical configuration system that prevents
accidentally using global defaults when bank-specific overrides exist.

- Created StaticConfigProxy that wraps HindsightConfig
- get_config() now returns proxy that blocks access to bank-configurable fields
- Raises ConfigFieldAccessError with clear message when accessing configurable fields
- Added _get_raw_config() for internal use only
- Forces developers to use resolve_full_config(bank_id, context) for bank settings

- Added resolve_full_config() method that returns complete HindsightConfig
- Resolves hierarchy: Global (env) → Tenant → Bank
- No caching to support multi-server deployments (always fresh from DB)
- LLM provider pooling handles expensive operations separately

- Updated entire retain pipeline to pass resolved config through call chain
- memory_engine.py: Resolves config at top level where bank_id/context available
- orchestrator.py: Accepts and passes config to fact_extraction
- fact_extraction.py: Uses passed config instead of get_config()
- utils.py: Added optional config param for backward compatibility

- consolidator.py: Uses resolve_full_config() for enable_observations check
- memory_engine.py: Resolves config before triggering consolidation

- Renamed "Memory Bank" to "Bank Configuration" with tabs
- Combined Stats and Operations into "General" tab
- Consolidated Profile and Configuration into "Configuration" tab
- Moved Actions dropdown to page level (outside tabs)

- Created new component for managing bank-specific config
- Displays configurable fields: retain_chunk_size, retain_extraction_mode, etc.
- Edit via dialog with form validation
- Reset to defaults via AlertDialog confirmation
- Shows field IDs in monospace for clarity
- Visual separation with borders and hover effects

- Removed inline edit mode, switched to dialog-based editing
- Separate dialogs for Disposition and Mission editing
- Read-only display with clear edit buttons
- Removed duplicate stats cards and operations

- bank-stats-view.tsx: Overview statistics (memories, links, documents, pending ops)
- bank-operations-view.tsx: Background operations table with filtering

**Problem**: Consolidation always used global enable_observations, ignoring bank overrides
**Root Cause**: consolidator.py called get_config() instead of resolving bank-specific config
**Solution**: Pass resolved config through the entire pipeline

**Problem**: asyncpg returning JSONB as JSON string instead of parsed dict
**Solution**: Explicit JSON parsing in config_resolver.py with type checking

- All 19 API integration tests pass
- All 10 hierarchical config tests pass
- Retain operations work correctly with bank-specific config
- Consolidation respects bank-specific enable_observations setting

- Updated developer/configuration.md with type-safe config access pattern
- Added examples showing correct usage patterns
- Documented ConfigFieldAccessError and resolution methods

- get_config() now returns StaticConfigProxy (blocks configurable field access)
- Code accessing bank-configurable fields must use resolve_full_config()
- Clear migration path with helpful error messages

Fixes hierarchical configuration to be production-ready with proper type safety.

* refactor: remove LLM client pool and simplify config resolver

Since LLM config (provider, model, api_key) is now static and not
bank-configurable, the LLMClientPool is no longer needed.

Changes:
- Remove hindsight_api/llm_client_pool.py (no longer needed)
- Remove memory_engine._get_bank_llm_config() (dead code, never called)
- Simplify config_resolver.py by eliminating duplication between
  resolve_full_config() and get_bank_config()
- get_bank_config() now calls resolve_full_config() and filters results
- Remove outdated "LLM provider pooling" comments from docstrings

All tests pass (10 hierarchical config tests, 19 API integration tests)

* fix: update tests to use _get_raw_config() for configurable fields

Fixed test fixtures that were accessing configurable fields (like
enable_observations) from get_config(), which now raises
ConfigFieldAccessError due to type-safe config access.

Changes:
- test_consolidation.py: Changed enable_observations fixture to use
  _get_raw_config() instead of get_config()
- test_consolidation.py: Updated test_consolidation_returns_disabled_status
  to set bank config instead of mocking get_config()
- test_link_expansion_retrieval.py: Changed fixture to use _get_raw_config()
- test_observations.py: Changed disable_observations fixture to use
  _get_raw_config()
- Regenerated OpenAPI spec and clients

All 39 previously failing tests now pass.

* fix: add missing config parameter to test calls of extract_facts_from_text()

Fixed 45 test failures where tests were calling extract_facts_from_text()
without the new required config parameter.

Changes:
- Added config=_get_raw_config() to all extract_facts_from_text() calls
- Fixed test_main_module.py to patch _get_raw_config instead of get_config
- Updated 6 test files with 37 function call sites

All tests should now pass.

* fix: add missing config parameter to test_skip_podcast_meta_commentary

One more test was missing the config parameter for extract_facts_from_text().
2026-02-12 13:14:57 +01:00

38 KiB

Configuration

Complete reference for configuring Hindsight services through environment variables.

Hindsight has two services, each with its own configuration prefix:

Service Prefix Description
API Service HINDSIGHT_API_* Core memory engine
Control Plane HINDSIGHT_CP_* Web UI

API Service

The API service handles all memory operations (retain, recall, reflect).

Database

Variable Description Default
HINDSIGHT_API_DATABASE_URL PostgreSQL connection string pg0 (embedded)
HINDSIGHT_API_DATABASE_SCHEMA PostgreSQL schema name for tables public
HINDSIGHT_API_RUN_MIGRATIONS_ON_STARTUP Run database migrations on API startup true

If not provided, the server uses embedded pg0 — convenient for development but not recommended for production.

The DATABASE_SCHEMA setting allows you to use a custom PostgreSQL schema instead of the default public schema. This is useful for:

  • Multi-database setups where you want Hindsight tables in a dedicated schema
  • Hosting platforms (e.g., Supabase) where public schema is reserved or shared
  • Organizational preferences for schema naming conventions
# Example: Using a custom schema
export HINDSIGHT_API_DATABASE_URL=postgresql://user:pass@host:5432/dbname
export HINDSIGHT_API_DATABASE_SCHEMA=hindsight

Migrations will automatically create the schema if it doesn't exist and create all tables in the configured schema.

Database Connection Pool

Variable Description Default
HINDSIGHT_API_DB_POOL_MIN_SIZE Minimum connections in the pool 5
HINDSIGHT_API_DB_POOL_MAX_SIZE Maximum connections in the pool 100
HINDSIGHT_API_DB_COMMAND_TIMEOUT PostgreSQL command timeout in seconds 60
HINDSIGHT_API_DB_ACQUIRE_TIMEOUT Connection acquisition timeout in seconds 30

For high-concurrency workloads, increase DB_POOL_MAX_SIZE. Each concurrent recall/think operation can use 2-4 connections.

To run migrations manually (e.g., before starting the API), use the admin CLI:

hindsight-admin run-db-migration
# Or for a specific schema:
hindsight-admin run-db-migration --schema tenant_acme

LLM Provider

Variable Description Default
HINDSIGHT_API_LLM_PROVIDER Provider: openai, openai-codex, claude-code, anthropic, gemini, groq, ollama, lmstudio, vertexai openai
HINDSIGHT_API_LLM_API_KEY API key for LLM provider -
HINDSIGHT_API_LLM_MODEL Model name gpt-5-mini
HINDSIGHT_API_LLM_BASE_URL Custom LLM endpoint Provider default
HINDSIGHT_API_LLM_MAX_CONCURRENT Max concurrent LLM requests 32
HINDSIGHT_API_LLM_MAX_RETRIES Max retry attempts for LLM API calls 10
HINDSIGHT_API_LLM_INITIAL_BACKOFF Initial retry backoff in seconds (exponential backoff) 1.0
HINDSIGHT_API_LLM_MAX_BACKOFF Max retry backoff cap in seconds 60.0
HINDSIGHT_API_LLM_TIMEOUT LLM request timeout in seconds 120
HINDSIGHT_API_LLM_GROQ_SERVICE_TIER Groq service tier: on_demand, flex, auto auto

Provider Examples

# Groq (recommended for fast inference)
export HINDSIGHT_API_LLM_PROVIDER=groq
export HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx
export HINDSIGHT_API_LLM_MODEL=openai/gpt-oss-20b
# For free tier users: override to on_demand if you get service_tier errors
# export HINDSIGHT_API_LLM_GROQ_SERVICE_TIER=on_demand

# OpenAI
export HINDSIGHT_API_LLM_PROVIDER=openai
export HINDSIGHT_API_LLM_API_KEY=sk-xxxxxxxxxxxx
export HINDSIGHT_API_LLM_MODEL=gpt-4o

# Gemini
export HINDSIGHT_API_LLM_PROVIDER=gemini
export HINDSIGHT_API_LLM_API_KEY=xxxxxxxxxxxx
export HINDSIGHT_API_LLM_MODEL=gemini-2.0-flash

# Anthropic
export HINDSIGHT_API_LLM_PROVIDER=anthropic
export HINDSIGHT_API_LLM_API_KEY=sk-ant-xxxxxxxxxxxx
export HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-20250514

# Vertex AI (Google Cloud - uses native genai SDK)
export HINDSIGHT_API_LLM_PROVIDER=vertexai
export HINDSIGHT_API_LLM_MODEL=gemini-2.0-flash-001
export HINDSIGHT_API_LLM_VERTEXAI_PROJECT_ID=your-gcp-project-id
export HINDSIGHT_API_LLM_VERTEXAI_REGION=us-central1
# Optional: use ADC (gcloud auth application-default login) or provide service account key:
# export HINDSIGHT_API_LLM_VERTEXAI_SERVICE_ACCOUNT_KEY=/path/to/service-account-key.json

# Ollama (local, no API key)
export HINDSIGHT_API_LLM_PROVIDER=ollama
export HINDSIGHT_API_LLM_BASE_URL=http://localhost:11434/v1
export HINDSIGHT_API_LLM_MODEL=llama3

# LM Studio (local, no API key)
export HINDSIGHT_API_LLM_PROVIDER=lmstudio
export HINDSIGHT_API_LLM_BASE_URL=http://localhost:1234/v1
export HINDSIGHT_API_LLM_MODEL=your-local-model

# OpenAI-compatible endpoint
export HINDSIGHT_API_LLM_PROVIDER=openai
export HINDSIGHT_API_LLM_BASE_URL=https://your-endpoint.com/v1
export HINDSIGHT_API_LLM_API_KEY=your-api-key
export HINDSIGHT_API_LLM_MODEL=your-model-name

# OpenAI Codex (ChatGPT Plus/Pro subscription - uses OAuth, no API key needed)
export HINDSIGHT_API_LLM_PROVIDER=openai-codex
export HINDSIGHT_API_LLM_MODEL=gpt-5.2-codex
# No API key needed - uses OAuth tokens from ~/.codex/auth.json

# Claude Code (Claude Pro/Max subscription - uses OAuth, no API key needed)
export HINDSIGHT_API_LLM_PROVIDER=claude-code
export HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-5-20250929
# No API key needed - uses claude auth login credentials

:::tip OpenAI Codex & Claude Code Setup For detailed setup instructions for OpenAI Codex (ChatGPT Plus/Pro) and Claude Code (Claude Pro/Max), see the Models documentation. :::

Vertex AI Setup

Google Cloud's Vertex AI provides access to Gemini models via the native Google GenAI SDK. Hindsight supports two authentication methods:

Prerequisites:

  • GCP project with Vertex AI API enabled
  • IAM role roles/aiplatform.user for your credentials

Environment Variables:

Variable Description Required
HINDSIGHT_API_LLM_VERTEXAI_PROJECT_ID Your GCP project ID Yes
HINDSIGHT_API_LLM_VERTEXAI_REGION GCP region (e.g., us-central1) No (default: us-central1)
HINDSIGHT_API_LLM_VERTEXAI_SERVICE_ACCOUNT_KEY Path to service account JSON key file No (uses ADC if not set)

Authentication Methods:

  1. Application Default Credentials (ADC) - Recommended for development

    # Setup ADC
    gcloud auth application-default login
    
    # Configure Hindsight
    export HINDSIGHT_API_LLM_PROVIDER=vertexai
    export HINDSIGHT_API_LLM_MODEL=gemini-2.0-flash-001
    export HINDSIGHT_API_LLM_VERTEXAI_PROJECT_ID=your-project-id
    
  2. Service Account Key - Recommended for production

    # Create service account and download key
    gcloud iam service-accounts create hindsight-api
    gcloud projects add-iam-policy-binding your-project-id \
      --member="serviceAccount:hindsight-api@your-project-id.iam.gserviceaccount.com" \
      --role="roles/aiplatform.user"
    gcloud iam service-accounts keys create key.json \
      --iam-account=hindsight-api@your-project-id.iam.gserviceaccount.com
    
    # Configure Hindsight
    export HINDSIGHT_API_LLM_PROVIDER=vertexai
    export HINDSIGHT_API_LLM_MODEL=gemini-2.0-flash-001
    export HINDSIGHT_API_LLM_VERTEXAI_PROJECT_ID=your-project-id
    export HINDSIGHT_API_LLM_VERTEXAI_SERVICE_ACCOUNT_KEY=/path/to/key.json
    

Notes:

  • Model names can optionally include the google/ prefix (e.g., google/gemini-2.0-flash-001) - it will be stripped automatically
  • The native SDK handles token refresh automatically
  • Uses service account credentials if provided, otherwise falls back to ADC

Per-Operation LLM Configuration

Different memory operations have different requirements. Retain (fact extraction) benefits from models with strong structured output capabilities, while Reflect (reasoning/response generation) can use lighter, faster models. Configure separate LLM models for each operation to optimize for cost and performance.

Variable Description Default
HINDSIGHT_API_RETAIN_LLM_PROVIDER LLM provider for retain operations Falls back to HINDSIGHT_API_LLM_PROVIDER
HINDSIGHT_API_RETAIN_LLM_API_KEY API key for retain LLM Falls back to HINDSIGHT_API_LLM_API_KEY
HINDSIGHT_API_RETAIN_LLM_MODEL Model for retain operations Falls back to HINDSIGHT_API_LLM_MODEL
HINDSIGHT_API_RETAIN_LLM_BASE_URL Base URL for retain LLM Falls back to HINDSIGHT_API_LLM_BASE_URL
HINDSIGHT_API_RETAIN_LLM_MAX_CONCURRENT Max concurrent requests for retain Falls back to HINDSIGHT_API_LLM_MAX_CONCURRENT
HINDSIGHT_API_RETAIN_LLM_MAX_RETRIES Max retries for retain Falls back to HINDSIGHT_API_LLM_MAX_RETRIES
HINDSIGHT_API_RETAIN_LLM_INITIAL_BACKOFF Initial backoff for retain retries (seconds) Falls back to HINDSIGHT_API_LLM_INITIAL_BACKOFF
HINDSIGHT_API_RETAIN_LLM_MAX_BACKOFF Max backoff cap for retain retries (seconds) Falls back to HINDSIGHT_API_LLM_MAX_BACKOFF
HINDSIGHT_API_RETAIN_LLM_TIMEOUT Timeout for retain requests (seconds) Falls back to HINDSIGHT_API_LLM_TIMEOUT
HINDSIGHT_API_REFLECT_LLM_PROVIDER LLM provider for reflect operations Falls back to HINDSIGHT_API_LLM_PROVIDER
HINDSIGHT_API_REFLECT_LLM_API_KEY API key for reflect LLM Falls back to HINDSIGHT_API_LLM_API_KEY
HINDSIGHT_API_REFLECT_LLM_MODEL Model for reflect operations Falls back to HINDSIGHT_API_LLM_MODEL
HINDSIGHT_API_REFLECT_LLM_BASE_URL Base URL for reflect LLM Falls back to HINDSIGHT_API_LLM_BASE_URL
HINDSIGHT_API_REFLECT_LLM_MAX_CONCURRENT Max concurrent requests for reflect Falls back to HINDSIGHT_API_LLM_MAX_CONCURRENT
HINDSIGHT_API_REFLECT_LLM_MAX_RETRIES Max retries for reflect Falls back to HINDSIGHT_API_LLM_MAX_RETRIES
HINDSIGHT_API_REFLECT_LLM_INITIAL_BACKOFF Initial backoff for reflect retries (seconds) Falls back to HINDSIGHT_API_LLM_INITIAL_BACKOFF
HINDSIGHT_API_REFLECT_LLM_MAX_BACKOFF Max backoff cap for reflect retries (seconds) Falls back to HINDSIGHT_API_LLM_MAX_BACKOFF
HINDSIGHT_API_REFLECT_LLM_TIMEOUT Timeout for reflect requests (seconds) Falls back to HINDSIGHT_API_LLM_TIMEOUT
HINDSIGHT_API_CONSOLIDATION_LLM_PROVIDER LLM provider for observation consolidation Falls back to HINDSIGHT_API_LLM_PROVIDER
HINDSIGHT_API_CONSOLIDATION_LLM_API_KEY API key for consolidation LLM Falls back to HINDSIGHT_API_LLM_API_KEY
HINDSIGHT_API_CONSOLIDATION_LLM_MODEL Model for consolidation operations Falls back to HINDSIGHT_API_LLM_MODEL
HINDSIGHT_API_CONSOLIDATION_LLM_BASE_URL Base URL for consolidation LLM Falls back to HINDSIGHT_API_LLM_BASE_URL
HINDSIGHT_API_CONSOLIDATION_LLM_MAX_CONCURRENT Max concurrent requests for consolidation Falls back to HINDSIGHT_API_LLM_MAX_CONCURRENT
HINDSIGHT_API_CONSOLIDATION_LLM_MAX_RETRIES Max retries for consolidation Falls back to HINDSIGHT_API_LLM_MAX_RETRIES
HINDSIGHT_API_CONSOLIDATION_LLM_INITIAL_BACKOFF Initial backoff for consolidation retries (seconds) Falls back to HINDSIGHT_API_LLM_INITIAL_BACKOFF
HINDSIGHT_API_CONSOLIDATION_LLM_MAX_BACKOFF Max backoff cap for consolidation retries (seconds) Falls back to HINDSIGHT_API_LLM_MAX_BACKOFF
HINDSIGHT_API_CONSOLIDATION_LLM_TIMEOUT Timeout for consolidation requests (seconds) Falls back to HINDSIGHT_API_LLM_TIMEOUT

:::tip When to Use Per-Operation Config

  • Retain: Use models with strong structured output (e.g., GPT-4o, Claude) for accurate fact extraction
  • Reflect: Use faster/cheaper models (e.g., GPT-4o-mini, Groq) for reasoning and response generation
  • Recall: Does not use LLM (pure retrieval), so no configuration needed :::

Example: Separate Models for Retain and Reflect

# Default LLM (used as fallback)
export HINDSIGHT_API_LLM_PROVIDER=openai
export HINDSIGHT_API_LLM_API_KEY=sk-xxxxxxxxxxxx
export HINDSIGHT_API_LLM_MODEL=gpt-4o

# Use GPT-4o for retain (strong structured output)
export HINDSIGHT_API_RETAIN_LLM_MODEL=gpt-4o

# Use faster/cheaper model for reflect
export HINDSIGHT_API_REFLECT_LLM_PROVIDER=groq
export HINDSIGHT_API_REFLECT_LLM_API_KEY=gsk_xxxxxxxxxxxx
export HINDSIGHT_API_REFLECT_LLM_MODEL=llama-3.3-70b-versatile

Example: Tuning Retry Behavior for Rate-Limited APIs

# For Anthropic with tight rate limits (10k output tokens/minute)
export HINDSIGHT_API_LLM_PROVIDER=anthropic
export HINDSIGHT_API_LLM_API_KEY=sk-ant-xxxxxxxxxxxx
export HINDSIGHT_API_LLM_MODEL=claude-sonnet-4-20250514

# Reduce concurrent requests for retain to avoid rate limits
export HINDSIGHT_API_RETAIN_LLM_MAX_CONCURRENT=3

# Fail faster with fewer retries
export HINDSIGHT_API_RETAIN_LLM_MAX_RETRIES=3

# Or increase backoff times to wait out rate limit windows
export HINDSIGHT_API_RETAIN_LLM_INITIAL_BACKOFF=2.0  # Start at 2s instead of 1s
export HINDSIGHT_API_RETAIN_LLM_MAX_BACKOFF=120.0    # Cap at 2min instead of 1min

Embeddings

Variable Description Default
HINDSIGHT_API_EMBEDDINGS_PROVIDER Provider: local, tei, openai, cohere, or litellm local
HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL Model for local provider BAAI/bge-small-en-v1.5
HINDSIGHT_API_EMBEDDINGS_LOCAL_TRUST_REMOTE_CODE Allow loading models with custom code (security risk, disabled by default) false
HINDSIGHT_API_EMBEDDINGS_TEI_URL TEI server URL -
HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY OpenAI API key (falls back to HINDSIGHT_API_LLM_API_KEY) -
HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL OpenAI embedding model text-embedding-3-small
HINDSIGHT_API_EMBEDDINGS_OPENAI_BASE_URL Custom base URL for OpenAI-compatible API (e.g., Azure OpenAI) -
HINDSIGHT_API_EMBEDDINGS_COHERE_API_KEY Cohere API key for embeddings -
HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL Cohere embedding model embed-english-v3.0
HINDSIGHT_API_EMBEDDINGS_COHERE_BASE_URL Custom base URL for Cohere-compatible API (e.g., Azure-hosted) -
HINDSIGHT_API_EMBEDDINGS_LITELLM_API_BASE LiteLLM proxy base URL for embeddings http://localhost:4000
HINDSIGHT_API_EMBEDDINGS_LITELLM_API_KEY LiteLLM proxy API key for embeddings (optional, depends on proxy config) -
HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL LiteLLM embedding model (use provider prefix, e.g., cohere/embed-english-v3.0) text-embedding-3-small
# Local (default) - uses SentenceTransformers
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=local
export HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=BAAI/bge-small-en-v1.5

# Local with custom model requiring trust_remote_code
# WARNING: Only enable trust_remote_code for models you trust (security risk)
# export HINDSIGHT_API_EMBEDDINGS_LOCAL_MODEL=your-custom-model
# export HINDSIGHT_API_EMBEDDINGS_LOCAL_TRUST_REMOTE_CODE=true

# OpenAI - cloud-based embeddings
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai
export HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=sk-xxxxxxxxxxxx  # or reuses HINDSIGHT_API_LLM_API_KEY
export HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small  # 1536 dimensions

# Azure OpenAI - embeddings via Azure endpoint
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=openai
export HINDSIGHT_API_EMBEDDINGS_OPENAI_API_KEY=your-azure-api-key
export HINDSIGHT_API_EMBEDDINGS_OPENAI_MODEL=text-embedding-3-small
export HINDSIGHT_API_EMBEDDINGS_OPENAI_BASE_URL=https://your-resource.openai.azure.com/openai/deployments/your-deployment

# TEI - HuggingFace Text Embeddings Inference (recommended for production)
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=tei
export HINDSIGHT_API_EMBEDDINGS_TEI_URL=http://localhost:8080

# Cohere - cloud-based embeddings
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=cohere
export HINDSIGHT_API_EMBEDDINGS_COHERE_API_KEY=your-api-key
export HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL=embed-english-v3.0  # 1024 dimensions

# Azure-hosted Cohere - embeddings via custom endpoint
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=cohere
export HINDSIGHT_API_EMBEDDINGS_COHERE_API_KEY=your-azure-api-key
export HINDSIGHT_API_EMBEDDINGS_COHERE_MODEL=embed-english-v3.0
export HINDSIGHT_API_EMBEDDINGS_COHERE_BASE_URL=https://your-azure-cohere-endpoint.com

# LiteLLM proxy - unified gateway for multiple providers
export HINDSIGHT_API_EMBEDDINGS_PROVIDER=litellm
export HINDSIGHT_API_EMBEDDINGS_LITELLM_API_BASE=http://localhost:4000
export HINDSIGHT_API_EMBEDDINGS_LITELLM_API_KEY=your-litellm-key  # optional
export HINDSIGHT_API_EMBEDDINGS_LITELLM_MODEL=text-embedding-3-small  # or cohere/embed-english-v3.0

Embedding Dimensions

Hindsight automatically detects the embedding dimension from the model at startup and adjusts the database schema accordingly. The default model (BAAI/bge-small-en-v1.5) produces 384-dimensional vectors, while OpenAI models produce 1536 or 3072 dimensions.

:::warning Dimension Changes Once memories are stored, you cannot change the embedding dimension without losing data. If you need to switch to a model with different dimensions:

  1. Empty database: The schema is adjusted automatically on startup
  2. Existing data: Either delete all memories first, or use a model with matching dimensions

Supported OpenAI embedding dimensions:

  • text-embedding-3-small: 1536 dimensions
  • text-embedding-3-large: 3072 dimensions
  • text-embedding-ada-002: 1536 dimensions (legacy) :::

Reranker

Variable Description Default
HINDSIGHT_API_RERANKER_PROVIDER Provider: local, tei, cohere, flashrank, litellm, or rrf local
HINDSIGHT_API_RERANKER_LOCAL_MODEL Model for local provider cross-encoder/ms-marco-MiniLM-L-6-v2
HINDSIGHT_API_RERANKER_LOCAL_MAX_CONCURRENT Max concurrent local reranking (prevents CPU thrashing under load) 4
HINDSIGHT_API_RERANKER_LOCAL_TRUST_REMOTE_CODE Allow loading models with custom code (security risk, disabled by default) false
HINDSIGHT_API_RERANKER_TEI_URL TEI server URL -
HINDSIGHT_API_RERANKER_TEI_BATCH_SIZE Batch size for TEI reranking 128
HINDSIGHT_API_RERANKER_TEI_MAX_CONCURRENT Max concurrent TEI reranking requests 8
HINDSIGHT_API_RERANKER_COHERE_API_KEY Cohere API key for reranking -
HINDSIGHT_API_RERANKER_COHERE_MODEL Cohere rerank model rerank-english-v3.0
HINDSIGHT_API_RERANKER_COHERE_BASE_URL Custom base URL for Cohere-compatible API (e.g., Azure-hosted) -
HINDSIGHT_API_RERANKER_LITELLM_API_BASE LiteLLM proxy base URL for reranking http://localhost:4000
HINDSIGHT_API_RERANKER_LITELLM_API_KEY LiteLLM proxy API key for reranking (optional, depends on proxy config) -
HINDSIGHT_API_RERANKER_LITELLM_MODEL LiteLLM rerank model (use provider prefix, e.g., cohere/rerank-english-v3.0) cohere/rerank-english-v3.0
HINDSIGHT_API_RERANKER_FLASHRANK_MODEL FlashRank model for fast CPU-based reranking ms-marco-MiniLM-L-12-v2
HINDSIGHT_API_RERANKER_FLASHRANK_CACHE_DIR Cache directory for FlashRank models System default
# Local (default) - uses SentenceTransformers CrossEncoder
export HINDSIGHT_API_RERANKER_PROVIDER=local
export HINDSIGHT_API_RERANKER_LOCAL_MODEL=cross-encoder/ms-marco-MiniLM-L-6-v2

# Local with custom model requiring trust_remote_code (e.g., jina-reranker-v2)
# WARNING: Only enable trust_remote_code for models you trust (security risk)
export HINDSIGHT_API_RERANKER_PROVIDER=local
export HINDSIGHT_API_RERANKER_LOCAL_MODEL=jinaai/jina-reranker-v2-base-multilingual
export HINDSIGHT_API_RERANKER_LOCAL_TRUST_REMOTE_CODE=true

# TEI - for high-performance inference
export HINDSIGHT_API_RERANKER_PROVIDER=tei
export HINDSIGHT_API_RERANKER_TEI_URL=http://localhost:8081

# Cohere - cloud-based reranking
export HINDSIGHT_API_RERANKER_PROVIDER=cohere
export HINDSIGHT_API_RERANKER_COHERE_API_KEY=your-api-key
export HINDSIGHT_API_RERANKER_COHERE_MODEL=rerank-english-v3.0

# Azure-hosted Cohere - reranking via custom endpoint
export HINDSIGHT_API_RERANKER_PROVIDER=cohere
export HINDSIGHT_API_RERANKER_COHERE_API_KEY=your-azure-api-key
export HINDSIGHT_API_RERANKER_COHERE_MODEL=rerank-english-v3.0
export HINDSIGHT_API_RERANKER_COHERE_BASE_URL=https://your-azure-cohere-endpoint.com

# LiteLLM proxy - unified gateway for multiple reranking providers
export HINDSIGHT_API_RERANKER_PROVIDER=litellm
export HINDSIGHT_API_RERANKER_LITELLM_API_BASE=http://localhost:4000
export HINDSIGHT_API_RERANKER_LITELLM_API_KEY=your-litellm-key  # optional
export HINDSIGHT_API_RERANKER_LITELLM_MODEL=cohere/rerank-english-v3.0  # or voyage/rerank-2, together_ai/...

LiteLLM supports multiple reranking providers via the /rerank endpoint:

  • Cohere (cohere/rerank-english-v3.0, cohere/rerank-multilingual-v3.0)
  • Together AI (together_ai/...)
  • Voyage AI (voyage/rerank-2)
  • Jina AI (jina_ai/...)
  • AWS Bedrock (bedrock/...)

Authentication

By default, Hindsight runs without authentication. For production deployments, enable API key authentication using the built-in tenant extension:

# Enable the built-in API key authentication
export HINDSIGHT_API_TENANT_EXTENSION=hindsight_api.extensions.builtin.tenant:ApiKeyTenantExtension
export HINDSIGHT_API_TENANT_API_KEY=your-secret-api-key

When enabled, all requests must include the API key in the Authorization header:

curl -H "Authorization: Bearer your-secret-api-key" \
  http://localhost:8888/v1/default/banks

Requests without a valid API key receive a 401 Unauthorized response.

:::tip Custom Authentication For advanced authentication (JWT, OAuth, multi-tenant schemas), implement a custom TenantExtension. See the Extensions documentation for details. :::

Server

Variable Description Default
HINDSIGHT_API_HOST Bind address 0.0.0.0
HINDSIGHT_API_PORT Server port 8888
HINDSIGHT_API_BASE_PATH Base path for API when behind reverse proxy (e.g., /hindsight) "" (root)
HINDSIGHT_API_WORKERS Number of uvicorn worker processes 1
HINDSIGHT_API_LOG_LEVEL Log level: debug, info, warning, error info
HINDSIGHT_API_LOG_FORMAT Log format: text or json (structured logging for cloud platforms) text
HINDSIGHT_API_MCP_ENABLED Enable MCP server at /mcp/{bank_id}/ true

Retrieval

Variable Description Default
HINDSIGHT_API_GRAPH_RETRIEVER Graph retrieval algorithm: link_expansion, mpfp, or bfs link_expansion
HINDSIGHT_API_RECALL_MAX_CONCURRENT Max concurrent recall operations per worker (backpressure) 32
HINDSIGHT_API_RECALL_CONNECTION_BUDGET Max concurrent DB connections per recall operation 4
HINDSIGHT_API_RERANKER_MAX_CANDIDATES Max candidates to rerank per recall (RRF pre-filters the rest) 300
HINDSIGHT_API_MPFP_TOP_K_NEIGHBORS Fan-out limit per node in MPFP graph traversal 20
HINDSIGHT_API_MENTAL_MODEL_REFRESH_CONCURRENCY Max concurrent mental model refreshes 8

Graph Retrieval Algorithms

  • link_expansion (default): Fast, simple graph expansion from semantic seeds via entity co-occurrence and causal links. Target latency under 100ms. Recommended for most use cases.
  • mpfp: Multi-Path Fact Propagation - iterative graph traversal with activation spreading. More thorough but slower.
  • bfs: Breadth-first search from seed facts. Simple but less effective for large graphs.

Retain

Controls the retain (memory ingestion) pipeline.

Variable Description Default
HINDSIGHT_API_RETAIN_MAX_COMPLETION_TOKENS Max completion tokens for fact extraction LLM calls 64000
HINDSIGHT_API_RETAIN_CHUNK_SIZE Max characters per chunk for fact extraction. Larger chunks extract fewer LLM calls but may lose context. 3000
HINDSIGHT_API_RETAIN_EXTRACTION_MODE Fact extraction mode: concise, verbose, or custom concise
HINDSIGHT_API_RETAIN_CUSTOM_INSTRUCTIONS Custom extraction guidelines (only used when mode is custom) -
HINDSIGHT_API_RETAIN_EXTRACT_CAUSAL_LINKS Extract causal relationships between facts true

Extraction Modes

The extraction mode controls how aggressively facts are extracted from content:

  • concise (default): Selective extraction that focuses on significant, long-term valuable facts. Filters out greetings, filler, and trivial information. Produces fewer but higher-quality facts with better performance.

  • verbose: Detailed extraction that captures every piece of information with maximum verbosity. Produces more facts with extensive detail but slower performance and higher token usage.

  • custom: Inject your own extraction guidelines while keeping the structural parts of the prompt (output format, coreference resolution, temporal handling, etc.) intact. Useful for A/B testing different extraction strategies or domain-specific customization.

Example: Custom Extraction Mode

# Set mode to custom
export HINDSIGHT_API_RETAIN_EXTRACTION_MODE=custom

# Define custom guidelines (multi-line is fine)
export HINDSIGHT_API_RETAIN_CUSTOM_INSTRUCTIONS="ONLY extract facts that are:
✅ Technical decisions and their rationale
✅ Architecture patterns and design choices
✅ Performance metrics and benchmarks
✅ Code reviews and feedback

DO NOT extract:
❌ Generic greetings or pleasantries
❌ Process chatter (\"let me check\", \"one moment\")
❌ Repeated information already captured

CONSOLIDATE related technical discussions into ONE fact when possible.

Ask yourself: 'Would this technical context be useful in 6 months?' If no, skip it."

Observations (Experimental)

Observations are consolidated knowledge synthesized from facts.

Variable Description Default
HINDSIGHT_API_ENABLE_OBSERVATIONS Enable observation consolidation true
HINDSIGHT_API_CONSOLIDATION_BATCH_SIZE Memories to load per batch (internal optimization) 50
HINDSIGHT_API_CONSOLIDATION_MAX_TOKENS Max tokens for recall when finding related observations during consolidation 1024

Reflect

Variable Description Default
HINDSIGHT_API_REFLECT_MAX_ITERATIONS Max tool call iterations before forcing a response 10

MCP Server

Configuration for MCP server endpoints.

Variable Description Default
HINDSIGHT_API_MCP_ENABLED Enable MCP server at /mcp/{bank_id}/ true
HINDSIGHT_API_MCP_AUTH_TOKEN Bearer token for MCP authentication (optional) -
HINDSIGHT_API_MCP_LOCAL_BANK_ID Memory bank ID for local MCP mcp
HINDSIGHT_API_MCP_INSTRUCTIONS Additional instructions appended to retain/recall tool descriptions -

MCP Authentication:

By default, the MCP endpoint is open. For production deployments, set HINDSIGHT_API_MCP_AUTH_TOKEN to require Bearer token authentication:

export HINDSIGHT_API_MCP_AUTH_TOKEN=your-secret-token

Clients must then include the token in the Authorization header. See MCP Server documentation for details.

Local MCP instructions:

# Example: instruct MCP to also store assistant actions
export HINDSIGHT_API_MCP_INSTRUCTIONS="Also store every action you take, including tool calls and decisions made."

Distributed Workers

Configuration for background task processing. By default, the API processes tasks internally. For high-throughput deployments, run dedicated workers. See Services - Worker Service for details.

Variable Description Default
HINDSIGHT_API_WORKER_ENABLED Enable internal worker in API process true
HINDSIGHT_API_WORKER_ID Unique worker identifier hostname
HINDSIGHT_API_WORKER_POLL_INTERVAL_MS Database polling interval in milliseconds 500
HINDSIGHT_API_WORKER_MAX_RETRIES Max retries before marking task failed 3
HINDSIGHT_API_WORKER_HTTP_PORT HTTP port for worker metrics/health (worker CLI only) 8889
HINDSIGHT_API_WORKER_MAX_SLOTS Maximum concurrent tasks per worker 10
HINDSIGHT_API_WORKER_CONSOLIDATION_MAX_SLOTS Maximum concurrent consolidation tasks per worker 2

Performance Optimization

Variable Description Default
HINDSIGHT_API_SKIP_LLM_VERIFICATION Skip LLM connection check on startup false
HINDSIGHT_API_LAZY_RERANKER Lazy-load reranker model (faster startup) false

Programmatic Configuration

You can also configure the API programmatically using MemoryEngine.from_env():

from hindsight_api import MemoryEngine

memory = MemoryEngine.from_env()
await memory.initialize()

Observability & Tracing

Hindsight provides OpenTelemetry-based observability for LLM calls, conforming to GenAI semantic conventions.

OpenTelemetry Tracing

Variable Description Default
HINDSIGHT_API_OTEL_TRACES_ENABLED Enable distributed tracing for LLM calls false
HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT OTLP endpoint URL (e.g., Grafana LGTM, Langfuse, etc.) -
HINDSIGHT_API_OTEL_EXPORTER_OTLP_HEADERS Headers for OTLP exporter (format: "key1=value1,key2=value2") -
HINDSIGHT_API_OTEL_SERVICE_NAME Service name for traces hindsight-api
HINDSIGHT_API_OTEL_DEPLOYMENT_ENVIRONMENT Deployment environment name (e.g., development, staging, production) development

Features:

  • Full prompts and completions recorded as events
  • Token usage tracking (input/output)
  • Model and provider information
  • Error tracking with finish reasons
  • Conforms to OpenTelemetry GenAI semantic conventions v1.37+

OTLP-Compatible Backends:

The tracing implementation uses standard OTLP HTTP protocol, so it works with any OTLP-compatible backend:

  • Grafana LGTM (Recommended for local dev): All-in-one stack with Tempo traces, Loki logs, Mimir metrics, and Grafana UI
  • Langfuse: LLM-focused observability and analytics
  • OpenLIT: Built-in LLM dashboards, cost tracking
  • DataDog, New Relic, Honeycomb: Commercial platforms

Example Configuration:

# Enable tracing
export HINDSIGHT_API_OTEL_TRACES_ENABLED=true

# Configure endpoint (example: OpenLIT Cloud)
export HINDSIGHT_API_OTEL_EXPORTER_OTLP_ENDPOINT=https://otlp.openlit.io
export HINDSIGHT_API_OTEL_EXPORTER_OTLP_HEADERS="Authorization=Bearer olit-xxx"

# Optional: Custom service name and environment
export HINDSIGHT_API_OTEL_SERVICE_NAME=hindsight-production
export HINDSIGHT_API_OTEL_DEPLOYMENT_ENVIRONMENT=production

Local Development:

For local development, we recommend the Grafana LGTM stack which provides traces, metrics, and logs in a single container:

./scripts/dev/start-grafana.sh

See scripts/dev/grafana/README.md for detailed setup instructions.

Other options: See scripts/dev/openlit/README.md for OpenLIT or scripts/dev/jaeger/README.md for standalone Jaeger.

Metrics

Hindsight exposes Prometheus metrics at the /metrics endpoint, including:

  • LLM call duration and token usage
  • Operation duration (retain/recall/reflect)
  • HTTP request metrics
  • Database connection pool metrics

Metrics are always enabled and available at http://localhost:8888/metrics.


Control Plane

The Control Plane is the web UI for managing memory banks.

Variable Description Default
HINDSIGHT_CP_DATAPLANE_API_URL URL of the API service http://localhost:8888
NEXT_PUBLIC_BASE_PATH Base path for Control Plane UI when behind reverse proxy (e.g., /hindsight) "" (root)
# Point Control Plane to a remote API service
export HINDSIGHT_CP_DATAPLANE_API_URL=http://api.example.com:8888

Hierarchical Configuration

Hindsight supports per-bank configuration overrides through a hierarchical system: Global (env vars) → Tenant → Bank.

Type-Safe Config Access

To prevent accidentally using global defaults when bank-specific overrides exist, Hindsight enforces type-safe config access:

In Application Code:

from hindsight_api.config import get_config

# ✅ Access static (infrastructure) fields
config = get_config()
host = config.host  # OK - static field
port = config.port  # OK - static field

# ❌ Attempting to access bank-configurable fields raises an error
chunk_size = config.retain_chunk_size  # ConfigFieldAccessError!

Error Message:

ConfigFieldAccessError: Field 'retain_chunk_size' is bank-configurable and cannot
be accessed from global config. Use ConfigResolver.resolve_full_config(bank_id, context)
to get bank-specific config.

For Bank-Specific Config:

# Internal code that needs bank-specific settings
from hindsight_api.config_resolver import ConfigResolver

# Resolve full config for a specific bank
config = await config_resolver.resolve_full_config(bank_id, request_context)
chunk_size = config.retain_chunk_size  # ✅ Uses bank-specific value

This design prevents bugs where global defaults are used instead of bank overrides, making it impossible to make this mistake at compile/development time.

Security Model

Configuration fields are categorized for security:

  1. Configurable Fields - Safe behavioral settings that can be customized per-bank:

    • Retention: retain_chunk_size, retain_extraction_mode, retain_custom_instructions
    • Consolidation: enable_observations
  2. Credential Fields - NEVER exposed or configurable via API:

    • API keys: *_api_key (all LLM API keys)
    • Infrastructure: *_base_url (all base URLs)
  3. Static Fields - Server-level only, cannot be overridden:

    • Infrastructure: database_url, port, host, worker_count
    • Provider/Model selection: llm_provider, llm_model (requires presets - not yet implemented)
    • Performance tuning: llm_max_concurrent, llm_timeout, retrieval settings, optimization flags

Enabling the API

Variable Description Default
HINDSIGHT_API_ENABLE_BANK_CONFIG_API Enable per-bank config API false

Important: The bank config API is disabled by default for security. Enable it explicitly:

export HINDSIGHT_API_ENABLE_BANK_CONFIG_API=true

API Endpoints

  • GET /v1/default/banks/{bank_id}/config - View resolved config (filtered by permissions)
  • PATCH /v1/default/banks/{bank_id}/config - Update bank overrides (only allowed fields)
  • DELETE /v1/default/banks/{bank_id}/config - Reset to defaults

Permission System

Tenant extensions can control which fields banks are allowed to modify via get_allowed_config_fields():

class CustomTenantExtension(TenantExtension):
    async def get_allowed_config_fields(self, context, bank_id):
        # Option 1: Allow all configurable fields
        return None

        # Option 2: Allow specific fields only
        return {"retain_chunk_size", "retain_custom_instructions"}

        # Option 3: Read-only (no modifications)
        return set()

Examples

# Update retention settings for a bank
curl -X PATCH http://localhost:8888/v1/default/banks/my-bank/config \
  -H "Content-Type: application/json" \
  -d '{
    "updates": {
      "retain_chunk_size": 4000,
      "retain_extraction_mode": "custom",
      "retain_custom_instructions": "Focus on technical details and implementation specifics"
    }
  }'

# Note: retain_extraction_mode must be "custom" to use retain_custom_instructions

# View resolved config (respects permissions)
curl http://localhost:8888/v1/default/banks/my-bank/config

# Reset to defaults
curl -X DELETE http://localhost:8888/v1/default/banks/my-bank/config

Security Notes:

  • Credentials (API keys, base URLs) are never returned in responses
  • Only configurable fields can be modified
  • Responses are filtered by tenant permissions
  • Attempting to set credentials returns 400 error

Reverse Proxy / Subpath Deployment

To deploy Hindsight under a subpath (e.g., example.com/hindsight/):

  1. Set both environment variables to the same path:

    HINDSIGHT_API_BASE_PATH=/hindsight
    NEXT_PUBLIC_BASE_PATH=/hindsight
    
  2. Configure your reverse proxy to:

    • Forward /hindsight/* requests to Hindsight
    • Preserve the full path in forwarded requests
    • Set appropriate proxy headers (X-Forwarded-Proto, X-Forwarded-For)

Example: Nginx Configuration

location /hindsight/ {
    proxy_pass http://localhost:8888/;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto $scheme;
}

Example: Traefik Configuration

http:
  routers:
    hindsight:
      rule: "PathPrefix(`/hindsight`)"
      service: hindsight
      middlewares:
        - hindsight-stripprefix

  middlewares:
    hindsight-stripprefix:
      stripPrefix:
        prefixes:
          - "/hindsight"

  services:
    hindsight:
      loadBalancer:
        servers:
          - url: "http://localhost:8888"

Important Notes:

  • The base path must start with / and should NOT end with /
  • Both API and Control Plane should use the same base path
  • After setting environment variables, restart both services
  • OpenAPI docs will be available at <base-path>/docs (e.g., /hindsight/docs)

Complete Examples:

See docker/compose-examples/ directory for:

  • Nginx configuration files (simple.conf, api-and-control-plane.conf)
  • Docker Compose setups (docker-compose.yml, reverse-proxy-only.yml)
  • Traefik and other reverse proxy examples
  • Full deployment documentation

Example .env File

# API Service
HINDSIGHT_API_DATABASE_URL=postgresql://hindsight:hindsight_dev@localhost:5432/hindsight
# HINDSIGHT_API_DATABASE_SCHEMA=public  # optional, defaults to 'public'
HINDSIGHT_API_LLM_PROVIDER=groq
HINDSIGHT_API_LLM_API_KEY=gsk_xxxxxxxxxxxx

# Authentication (optional, recommended for production)
# HINDSIGHT_API_TENANT_EXTENSION=hindsight_api.extensions.builtin.tenant:ApiKeyTenantExtension
# HINDSIGHT_API_TENANT_API_KEY=your-secret-api-key

# Control Plane
HINDSIGHT_CP_DATAPLANE_API_URL=http://localhost:8888

For configuration issues not covered here, please open an issue on GitHub.