diff --git a/.env.template b/.env.template index ed456e91..56a000ab 100644 --- a/.env.template +++ b/.env.template @@ -57,160 +57,135 @@ AUTH_USE_AUTH=false # AUTH_JWT_SECRET=your-secret-key-here # ============================================================================= -# LLM API Keys (REQUIRED for full functionality) +# LLM Provider (REQUIRED) # ============================================================================= -# OpenAI API key for embeddings -LLM_OPENAI_API_KEY=your-openai-api-key-here - -# Anthropic API key for dialectic and deriver functionality -LLM_ANTHROPIC_API_KEY=your-anthropic-api-key-here - -# Google API key for summarization (if using Gemini) -# LLM_GEMINI_API_KEY=your-google-api-key-here - -# Groq API key for query generation (if using Groq) -# LLM_GROQ_API_KEY=your-groq-api-key-here - -# Base URL for OpenAI Compatible Requests if you want to use a different provider -# LLM_OPENAI_COMPATIBLE_BASE_URL= -# LLM_OPENAI_COMPATIBLE_API_KEY= - -# Separate vLLM endpoint (for local models) -# LLM_VLLM_API_KEY= -# LLM_VLLM_BASE_URL= - -# ============================================================================= -# LLM Configuration -# ============================================================================= -# Global LLM settings +# Honcho uses LLMs for memory extraction, summarization, dialectic chat, and +# dream consolidation. The server will fail to start without a provider configured. +# +# Quick start: uncomment the two lines below, set your endpoint and API key, +# then uncomment the provider/model lines in each feature section below. +# Any OpenAI-compatible endpoint works (OpenRouter, Together, Fireworks, etc.). +# Models must support tool calling (function calling). +# +LLM_OPENAI_COMPATIBLE_BASE_URL=https://openrouter.ai/api/v1 +LLM_OPENAI_COMPATIBLE_API_KEY=your-api-key-here +# +# Provider options for each feature: custom, vllm, google, anthropic, openai, groq +# "custom" routes through the OpenAI-compatible endpoint above. +# Model name format depends on your provider (e.g., OpenRouter: vendor/model-name). +# +# ---- Alternative: vLLM self-hosted ------------------------------------------ +# LLM_VLLM_BASE_URL=http://localhost:8000/v1 +# LLM_VLLM_API_KEY=not-needed +# +# ---- Alternative: direct vendor keys (no endpoint needed) ------------------- +# LLM_GEMINI_API_KEY= +# LLM_ANTHROPIC_API_KEY= +# LLM_OPENAI_API_KEY= +# LLM_GROQ_API_KEY= +# +# ---- General LLM settings --------------------------------------------------- +# Embedding provider — defaults to openai (requires LLM_OPENAI_API_KEY). +# Set to openrouter to route embeddings through your custom endpoint instead. +LLM_EMBEDDING_PROVIDER=openrouter # LLM_DEFAULT_MAX_TOKENS=2500 -# LLM_EMBEDDING_PROVIDER=openai -# LLM_MAX_TOOL_OUTPUT_CHARS=10000 # Max chars for tool output (~2500 tokens) -# LLM_MAX_MESSAGE_CONTENT_CHARS=2000 # Max chars per message in tool results +# LLM_MAX_TOOL_OUTPUT_CHARS=10000 +# LLM_MAX_MESSAGE_CONTENT_CHARS=2000 # ============================================================================= -# Deriver (Background Worker) Settings +# Deriver (Background Worker) # ============================================================================= # DERIVER_ENABLED=true +DERIVER_PROVIDER=custom +DERIVER_MODEL=your-model-here # e.g. google/gemini-2.5-flash +# DERIVER_THINKING_BUDGET_TOKENS=1024 # gt=0 required; omit for non-thinking models # DERIVER_WORKERS=1 # DERIVER_POLLING_SLEEP_INTERVAL_SECONDS=1.0 # DERIVER_STALE_SESSION_TIMEOUT_MINUTES=5 -# DERIVER_QUEUE_ERROR_RETENTION_SECONDS=2592000 # 30 days -# DERIVER_PROVIDER=google -# DERIVER_MODEL=gemini-2.5-flash-lite +# DERIVER_QUEUE_ERROR_RETENTION_SECONDS=2592000 # DERIVER_TEMPERATURE= # DERIVER_DEDUPLICATE=true # DERIVER_MAX_OUTPUT_TOKENS=4096 -# DERIVER_THINKING_BUDGET_TOKENS=1024 # DERIVER_LOG_OBSERVATIONS=false # DERIVER_MAX_INPUT_TOKENS=23000 # DERIVER_WORKING_REPRESENTATION_MAX_OBSERVATIONS=100 # DERIVER_REPRESENTATION_BATCH_MAX_TOKENS=1024 -# DERIVER_FLUSH_ENABLED=false # Bypass batch token threshold, process work immediately -# DERIVER_BACKUP_PROVIDER= -# DERIVER_BACKUP_MODEL= +# DERIVER_FLUSH_ENABLED=false # ============================================================================= -# Peer Card Configuration +# Peer Card # ============================================================================= # PEER_CARD_ENABLED=true # ============================================================================= -# Dialectic Settings +# Dialectic # ============================================================================= -# Global dialectic settings # DIALECTIC_MAX_OUTPUT_TOKENS=8192 # DIALECTIC_MAX_INPUT_TOKENS=100000 # DIALECTIC_HISTORY_TOKEN_LIMIT=8192 # DIALECTIC_SESSION_HISTORY_MAX_TOKENS=4096 - -# Per-level settings (reasoning_level parameter in API) -# Each level can have its own provider, model, thinking budget, tool iterations, and max output tokens -# MAX_OUTPUT_TOKENS is optional per level; if not set, uses global DIALECTIC_MAX_OUTPUT_TOKENS - -# Minimal level -# DIALECTIC_LEVELS__minimal__PROVIDER=google -# DIALECTIC_LEVELS__minimal__MODEL=gemini-2.5-flash-lite +# +# Per-level provider, model, and tuning: +DIALECTIC_LEVELS__minimal__PROVIDER=custom +DIALECTIC_LEVELS__minimal__MODEL=your-model-here # e.g. google/gemini-2.5-flash # DIALECTIC_LEVELS__minimal__THINKING_BUDGET_TOKENS=0 # DIALECTIC_LEVELS__minimal__MAX_TOOL_ITERATIONS=1 -# DIALECTIC_LEVELS__minimal__MAX_OUTPUT_TOKENS=250 # Reduced output for cost savings - -# Low level -# DIALECTIC_LEVELS__low__PROVIDER=google -# DIALECTIC_LEVELS__low__MODEL=gemini-2.5-flash-lite +# DIALECTIC_LEVELS__minimal__MAX_OUTPUT_TOKENS=250 +DIALECTIC_LEVELS__low__PROVIDER=custom +DIALECTIC_LEVELS__low__MODEL=your-model-here # DIALECTIC_LEVELS__low__THINKING_BUDGET_TOKENS=0 # DIALECTIC_LEVELS__low__MAX_TOOL_ITERATIONS=5 -# DIALECTIC_LEVELS__low__MAX_OUTPUT_TOKENS=8192 # Optional: override global default - -# Medium level -# DIALECTIC_LEVELS__medium__PROVIDER=anthropic -# DIALECTIC_LEVELS__medium__MODEL=claude-haiku-4-5 -# DIALECTIC_LEVELS__medium__THINKING_BUDGET_TOKENS=1024 +DIALECTIC_LEVELS__medium__PROVIDER=custom +DIALECTIC_LEVELS__medium__MODEL=your-model-here +# DIALECTIC_LEVELS__medium__THINKING_BUDGET_TOKENS=0 # DIALECTIC_LEVELS__medium__MAX_TOOL_ITERATIONS=2 -# DIALECTIC_LEVELS__medium__MAX_OUTPUT_TOKENS=8192 # Optional: override global default -# DIALECTIC_LEVELS__medium__TOOL_CHOICE= - -# High level -# DIALECTIC_LEVELS__high__PROVIDER=anthropic -# DIALECTIC_LEVELS__high__MODEL=claude-haiku-4-5 -# DIALECTIC_LEVELS__high__THINKING_BUDGET_TOKENS=1024 +DIALECTIC_LEVELS__high__PROVIDER=custom +DIALECTIC_LEVELS__high__MODEL=your-model-here +# DIALECTIC_LEVELS__high__THINKING_BUDGET_TOKENS=0 # DIALECTIC_LEVELS__high__MAX_TOOL_ITERATIONS=4 -# DIALECTIC_LEVELS__high__MAX_OUTPUT_TOKENS=8192 # Optional: override global default - -# Max level -# DIALECTIC_LEVELS__max__PROVIDER=anthropic -# DIALECTIC_LEVELS__max__MODEL=claude-haiku-4-5 -# DIALECTIC_LEVELS__max__THINKING_BUDGET_TOKENS=2048 +DIALECTIC_LEVELS__max__PROVIDER=custom +DIALECTIC_LEVELS__max__MODEL=your-model-here +# DIALECTIC_LEVELS__max__THINKING_BUDGET_TOKENS=0 # DIALECTIC_LEVELS__max__MAX_TOOL_ITERATIONS=10 -# DIALECTIC_LEVELS__max__MAX_OUTPUT_TOKENS=8192 # Optional: override global default -# Optional backup per level (must set both or neither): -# DIALECTIC_LEVELS__max__BACKUP_PROVIDER=google -# DIALECTIC_LEVELS__max__BACKUP_MODEL=gemini-2.5-pro # ============================================================================= -# Summary Settings +# Summary # ============================================================================= # SUMMARY_ENABLED=true +SUMMARY_PROVIDER=custom +SUMMARY_MODEL=your-model-here # e.g. google/gemini-2.5-flash +# SUMMARY_THINKING_BUDGET_TOKENS=512 # gt=0 required; omit for non-thinking models # SUMMARY_MESSAGES_PER_SHORT_SUMMARY=20 # SUMMARY_MESSAGES_PER_LONG_SUMMARY=60 -# SUMMARY_PROVIDER=google -# SUMMARY_MODEL=gemini-2.5-flash # SUMMARY_MAX_TOKENS_SHORT=1000 # SUMMARY_MAX_TOKENS_LONG=4000 -# SUMMARY_THINKING_BUDGET_TOKENS=512 -# SUMMARY_BACKUP_PROVIDER= -# SUMMARY_BACKUP_MODEL= # ============================================================================= -# Dream Settings +# Dream # ============================================================================= # DREAM_ENABLED=true +DREAM_PROVIDER=custom +DREAM_MODEL=your-model-here # e.g. google/gemini-2.5-flash +DREAM_DEDUCTION_MODEL=your-model-here +DREAM_INDUCTION_MODEL=your-model-here +# DREAM_THINKING_BUDGET_TOKENS=8192 # gt=0 required; omit for non-thinking models # DREAM_DOCUMENT_THRESHOLD=50 # DREAM_IDLE_TIMEOUT_MINUTES=60 # DREAM_MIN_HOURS_BETWEEN_DREAMS=8 # DREAM_ENABLED_TYPES=["omni"] -# DREAM_PROVIDER=anthropic -# DREAM_MODEL=claude-sonnet-4-20250514 # DREAM_MAX_OUTPUT_TOKENS=16384 -# DREAM_THINKING_BUDGET_TOKENS=8192 # DREAM_MAX_TOOL_ITERATIONS=20 # DREAM_HISTORY_TOKEN_LIMIT=16384 -# DREAM_BACKUP_PROVIDER= -# DREAM_BACKUP_MODEL= - -# Specialist models (use same provider as main model) -# DREAM_DEDUCTION_MODEL=claude-haiku-4-5 -# DREAM_INDUCTION_MODEL=claude-haiku-4-5 - -# Dream Surprisal Settings (Tree-based observation sampling for targeted reasoning) +# +# Surprisal sampling (advanced): # DREAM_SURPRISAL__ENABLED=false -# DREAM_SURPRISAL__TREE_TYPE=kdtree # Options: kdtree, balltree, rptree, covertree, lsh, graph, prototype -# DREAM_SURPRISAL__TREE_K=5 # Number of neighbors for kNN-based trees -# DREAM_SURPRISAL__SAMPLING_STRATEGY=recent # Options: recent, random, all -# DREAM_SURPRISAL__SAMPLE_SIZE=200 # Number of observations to sample for tree building -# DREAM_SURPRISAL__TOP_PERCENT_SURPRISAL=0.10 # Top percentage of observations (0.10 = top 10%) -# DREAM_SURPRISAL__MIN_HIGH_SURPRISAL_FOR_REPLACE=10 # Hybrid mode: min observations to replace standard questions -# DREAM_SURPRISAL__INCLUDE_LEVELS=["explicit","deductive"] # Observation levels to include +# DREAM_SURPRISAL__TREE_TYPE=kdtree +# DREAM_SURPRISAL__TREE_K=5 +# DREAM_SURPRISAL__SAMPLING_STRATEGY=recent +# DREAM_SURPRISAL__SAMPLE_SIZE=200 +# DREAM_SURPRISAL__TOP_PERCENT_SURPRISAL=0.10 +# DREAM_SURPRISAL__MIN_HIGH_SURPRISAL_FOR_REPLACE=10 +# DREAM_SURPRISAL__INCLUDE_LEVELS=["explicit","deductive"] # ============================================================================= # Webhook Settings diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2297b658..9817dd1e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -106,7 +106,7 @@ git commit -m "docs(readme): update installation instructions" ### Python Code Style - Follow [PEP 8](https://www.python.org/dev/peps/pep-0008/) style guidelines -- Use [Black](https://black.readthedocs.io/) for code formatting (we may add this to CI in the future) +- Use [ruff](https://docs.astral.sh/ruff/) for linting and code formatting - Use type hints where possible - Write docstrings for functions and classes using Google style docstrings diff --git a/Dockerfile b/Dockerfile index 4a68d617..c116775e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,6 +41,7 @@ RUN addgroup --system app && adduser --system --group app && mkdir -p /tmp/uv-ca COPY --chown=app:app src/ /app/src/ COPY --chown=app:app migrations/ /app/migrations/ COPY --chown=app:app scripts/ /app/scripts/ +COPY --chown=app:app docker/ /app/docker/ COPY --chown=app:app alembic.ini /app/alembic.ini # Copy config files - this will copy config.toml if it exists, and config.toml.example COPY --chown=app:app config.toml* /app/ @@ -51,6 +52,6 @@ USER app EXPOSE 8000 HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/openapi.json')" || exit 1 + CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1 CMD ["fastapi", "run", "--host", "0.0.0.0", "src/main.py"] diff --git a/README.md b/README.md index 1a909d0f..990f7cc3 100644 --- a/README.md +++ b/README.md @@ -162,8 +162,8 @@ Server. Honcho is developed using [python](https://www.python.org/) and [uv](https://docs.astral.sh/uv/). -The minimum python version is `3.9` -The minimum uv version is `0.4.9` +The minimum python version is `3.10` +The minimum uv version is `0.5.0` ### Setup @@ -221,11 +221,11 @@ Below are the required configurations: ```env DB_CONNECTION_URI= # Connection uri for a postgres database (with postgresql+psycopg prefix) -# LLM Provider API Keys (at least one required depending on your configuration) -LLM_ANTHROPIC_API_KEY= # API Key for Anthropic (used for dialectic by default) -LLM_OPENAI_API_KEY= # API Key for OpenAI (optional, for embeddings if EMBED_MESSAGES=true) -LLM_GEMINI_API_KEY= # API Key for Google Gemini (used for summary/deriver by default) -LLM_GROQ_API_KEY= # API Key for Groq (used for query generation by default) +# LLM Provider API Keys +LLM_GEMINI_API_KEY= # API Key for Google Gemini (used for deriver, summary, and dialectic minimal/low by default) +LLM_ANTHROPIC_API_KEY= # API Key for Anthropic (used for dialectic medium/high/max and dream by default) +LLM_OPENAI_API_KEY= # API Key for OpenAI (used for embeddings when EMBED_MESSAGES=true) +LLM_GROQ_API_KEY= # API Key for Groq (optional) ``` > Note that the `DB_CONNECTION_URI` must have the prefix `postgresql+psycopg` to @@ -455,14 +455,14 @@ If you have this in `config.toml`: ```toml [db] -CONNECTION_URI = "postgresql://localhost/honcho_dev" +CONNECTION_URI = "postgresql+psycopg://localhost/honcho_dev" POOL_SIZE = 10 ``` You can override just the connection URI in production: ```bash -export DB_CONNECTION_URI="postgresql://prod-server/honcho_prod" +export DB_CONNECTION_URI="postgresql+psycopg://prod-server/honcho_prod" ``` The application will use the production connection URI while keeping the pool size from config.toml. diff --git a/config.toml.example b/config.toml.example index b6b407dc..b9cf84c0 100644 --- a/config.toml.example +++ b/config.toml.example @@ -55,17 +55,21 @@ EMBEDDING_PROVIDER = "openai" MAX_TOOL_OUTPUT_CHARS = 10000 # Max chars for tool output (~2500 tokens) MAX_MESSAGE_CONTENT_CHARS = 2000 # Max chars per message in tool results -# API Keys for LLM providers -# ANTHROPIC_API_KEY = "your-api-key" -# OPENAI_API_KEY = "your-api-key" -# OPENAI_COMPATIBLE_API_KEY = "your-api-key" -# GEMINI_API_KEY = "your-api-key" -# GROQ_API_KEY = "your-api-key" -# OPENAI_COMPATIBLE_BASE_URL = "your-base-url" +# API Keys for LLM providers (set the ones you need) +# GEMINI_API_KEY = "your-api-key" # Default: deriver, summary, dialectic minimal/low +# ANTHROPIC_API_KEY = "your-api-key" # Default: dialectic medium/high/max, dream +# OPENAI_API_KEY = "your-api-key" # Default: embeddings +# GROQ_API_KEY = "your-api-key" # Not used by default -# Separate vLLM endpoint (for local models) -# VLLM_API_KEY = "your-api-key" -# VLLM_BASE_URL = "your-base-url" +# OpenAI-compatible endpoint (OpenRouter, Together, Fireworks, LiteLLM, etc.) +# Set provider to "custom" in feature config to route calls through this endpoint. +# OPENAI_COMPATIBLE_BASE_URL = "https://openrouter.ai/api/v1" +# OPENAI_COMPATIBLE_API_KEY = "your-api-key" + +# vLLM endpoint (for self-hosted models) +# Set provider to "vllm" in feature config to route calls through this endpoint. +# VLLM_BASE_URL = "http://localhost:8000/v1" +# VLLM_API_KEY = "not-needed" # Deriver settings [deriver] diff --git a/docker-compose.yml.example b/docker-compose.yml.example index 8bb8507f..d59f1cee 100644 --- a/docker-compose.yml.example +++ b/docker-compose.yml.example @@ -1,6 +1,15 @@ +# Honcho Docker Compose +# +# Usage: +# cp docker-compose.yml.example docker-compose.yml +# cp .env.template .env # edit with your provider config +# docker compose up -d --build +# +# By default, ports are bound to 127.0.0.1 (localhost only). +# For development, uncomment the source mounts and monitoring services below. + services: api: - image: honcho:latest build: context: . dockerfile: Dockerfile @@ -11,16 +20,20 @@ services: redis: condition: service_healthy ports: - - 8000:8000 - volumes: - - .:/app - - venv:/app/.venv + - "127.0.0.1:8000:8000" + # -- Development: mount source for live reload -- + # volumes: + # - .:/app + # - venv:/app/.venv environment: - DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres - CACHE_URL=redis://redis:6379/0?suppress=true + - CACHE_ENABLED=true env_file: - path: .env required: false + restart: unless-stopped + deriver: build: context: . @@ -31,27 +44,29 @@ services: condition: service_healthy redis: condition: service_healthy - volumes: - - .:/app - - venv:/app/.venv + # -- Development: mount source for live reload -- + # volumes: + # - .:/app + # - venv:/app/.venv environment: - DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres - CACHE_URL=redis://redis:6379/0?suppress=true - - METRICS_ENABLED=true + - CACHE_ENABLED=true env_file: - path: .env required: false + restart: unless-stopped + database: image: pgvector/pgvector:pg15 - restart: always + restart: unless-stopped ports: - - 5432:5432 - command: ["postgres", "-c", "max_connections=800"] + - "127.0.0.1:5432:5432" + command: ["postgres", "-c", "max_connections=200"] environment: - POSTGRES_DB=postgres - POSTGRES_USER=postgres - POSTGRES_PASSWORD=postgres - - POSTGRES_HOST_AUTH_METHOD=trust - PGDATA=/var/lib/postgresql/data/pgdata volumes: - ./database/init.sql:/docker-entrypoint-initdb.d/init.sql @@ -61,44 +76,49 @@ services: interval: 5s timeout: 5s retries: 5 + redis: image: redis:8.2 - restart: always + restart: unless-stopped ports: - - 6379:6379 + - "127.0.0.1:6379:6379" volumes: - - ./redis-data:/data + - redis-data:/data healthcheck: test: ["CMD-SHELL", "redis-cli ping"] interval: 5s timeout: 5s retries: 5 - prometheus: - image: prom/prometheus:v3.2.1 - ports: - - 9090:9090 - volumes: - - ./docker/prometheus.yml:/etc/prometheus/prometheus.yml:ro - - prometheus-data:/prometheus - depends_on: - api: - condition: service_started - grafana: - image: grafana/grafana:11.4.0 - ports: - - 3000:3000 - environment: - - GF_SECURITY_ADMIN_USER=admin - - GF_SECURITY_ADMIN_PASSWORD=admin - - GF_AUTH_ANONYMOUS_ENABLED=true - - GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer - volumes: - - ./grafana-data:/var/lib/grafana - - ./docker/grafana-datasource.yml:/etc/grafana/provisioning/datasources/datasource.yml:ro - depends_on: - prometheus: - condition: service_started + + # -- Development: monitoring stack (uncomment to enable) -- + # prometheus: + # image: prom/prometheus:v3.2.1 + # ports: + # - "127.0.0.1:9090:9090" + # volumes: + # - ./docker/prometheus.yml:/etc/prometheus/prometheus.yml:ro + # - prometheus-data:/prometheus + # depends_on: + # api: + # condition: service_started + # grafana: + # image: grafana/grafana:11.4.0 + # ports: + # - "127.0.0.1:3000:3000" + # environment: + # - GF_SECURITY_ADMIN_USER=admin + # - GF_SECURITY_ADMIN_PASSWORD=admin + # - GF_AUTH_ANONYMOUS_ENABLED=true + # - GF_AUTH_ANONYMOUS_ORG_ROLE=Viewer + # volumes: + # - ./docker/grafana-datasource.yml:/etc/grafana/provisioning/datasources/datasource.yml:ro + # depends_on: + # prometheus: + # condition: service_started + volumes: pgdata: - venv: - prometheus-data: + redis-data: + # -- Development: uncomment if using source mounts -- + # venv: + # prometheus-data: diff --git a/docs/docs.json b/docs/docs.json index 02f7f27f..a81217cc 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -143,7 +143,8 @@ "group": "Self-Hosting", "pages": [ "v3/contributing/self-hosting", - "v3/contributing/configuration" + "v3/contributing/configuration", + "v3/contributing/troubleshooting" ] }, { diff --git a/docs/v2/contributing/configuration.mdx b/docs/v2/contributing/configuration.mdx index 59cf5a73..c172369c 100644 --- a/docs/v2/contributing/configuration.mdx +++ b/docs/v2/contributing/configuration.mdx @@ -96,14 +96,14 @@ If you have this in `config.toml`: ```toml [db] -CONNECTION_URI = "postgresql://localhost/honcho_dev" +CONNECTION_URI = "postgresql+psycopg://localhost/honcho_dev" POOL_SIZE = 10 ``` You can override just the connection URI in production: ```bash -export DB_CONNECTION_URI="postgresql://prod-server/honcho_prod" +export DB_CONNECTION_URI="postgresql+psycopg://prod-server/honcho_prod" ``` The application will use the production connection URI while keeping the pool size from config.toml. @@ -149,7 +149,7 @@ LOCAL_METRICS_FILE=metrics.jsonl DB_CONNECTION_URI=postgresql+psycopg://username:password@host:port/database # Example for local development -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho +DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/postgres # Example for production DB_CONNECTION_URI=postgresql+psycopg://honcho_user:secure_password@db.example.com:5432/honcho_prod diff --git a/docs/v2/contributing/self-hosting.mdx b/docs/v2/contributing/self-hosting.mdx index 99a22528..eda94e7f 100644 --- a/docs/v2/contributing/self-hosting.mdx +++ b/docs/v2/contributing/self-hosting.mdx @@ -135,24 +135,21 @@ Download from [postgresql.org](https://www.postgresql.org/download/windows/) ```bash docker run --name honcho-db \ - -e POSTGRES_DB=honcho \ -e POSTGRES_USER=postgres \ -e POSTGRES_PASSWORD=postgres \ -p 5432:5432 \ -d pgvector/pgvector:pg15 ``` -### 3. Create Database and Enable Extensions +### 3. Enable Extensions -Connect to PostgreSQL and set up the database: +Connect to PostgreSQL and enable pgvector: ```bash # Connect to PostgreSQL psql -U postgres -# Create database and enable extensions -CREATE DATABASE honcho; -\c honcho +# Enable extensions on the default database CREATE EXTENSION IF NOT EXISTS vector; CREATE EXTENSION IF NOT EXISTS pg_trgm; \q @@ -170,7 +167,7 @@ Edit `.env` with your configuration: ```bash # Database connection -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho +DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/postgres # Optional API keys (required for LLM features) OPENAI_API_KEY=your-openai-api-key diff --git a/docs/v3/contributing/configuration.mdx b/docs/v3/contributing/configuration.mdx index 57b77e40..5ae99cc9 100644 --- a/docs/v3/contributing/configuration.mdx +++ b/docs/v3/contributing/configuration.mdx @@ -1,285 +1,145 @@ --- title: "Configuration Guide" -description: "Complete guide to configuring Honcho for development and production" +description: "Complete reference for configuring Honcho providers, features, and infrastructure" icon: "gear" --- -Honcho uses a flexible configuration system that supports both TOML files and environment variables. Configuration values are loaded in the following priority order (highest to lowest): + +Most users only need the setup from the [Self-Hosting Guide](./self-hosting#llm-setup). This page is the full reference for customizing providers, tuning features, and hardening your deployment. + -1. Environment variables (always take precedence) -2. `.env` file (for local development) -3. `config.toml` file (base configuration) -4. Default values +Honcho loads configuration in this priority order (highest wins): -## Recommended Configuration Approaches +1. **Environment variables** (always take precedence) +2. **`.env` file** +3. **`config.toml` file** +4. **Built-in defaults** -### Option 1: Environment Variables Only (Production) -- Use environment variables for all configuration -- No config files needed -- Ideal for containerized deployments (Docker, Kubernetes) -- Secrets managed by your deployment platform - -### Option 2: config.toml (Development/Simple Deployments) -- Use config.toml for base configuration -- Override sensitive values with environment variables -- Good for development and simple deployments - -### Option 3: Hybrid Approach -- Use config.toml for non-sensitive base settings -- Use .env file for sensitive values (API keys, secrets) -- Good for development teams - -### Option 4: .env Only (Local Development) -- Use .env file for all configuration -- Simple for local development -- Never commit .env files to version control - -## Configuration Methods - -### Using config.toml - -Copy the example configuration file to get started: +Use `.env` for secrets and overrides, `config.toml` for base settings. Or use environment variables exclusively — whatever fits your deployment. Copy the examples to get started: ```bash +cp .env.template .env cp config.toml.example config.toml ``` -Then modify the values as needed. The TOML file is organized into sections: +### Environment Variable Naming -- `[app]` - Application-level settings (log level, session limits, embedding settings, Langfuse integration, local metrics collection, namespace) -- `[db]` - Database connection and pool settings (connection URI, pool size, timeouts, connection recycling) -- `[auth]` - Authentication configuration (enable/disable auth, JWT secret) -- `[cache]` - Redis cache configuration (enable/disable caching, Redis URL, TTL settings, lock configuration for cache stampede prevention) -- `[llm]` - LLM provider API keys (Anthropic, OpenAI, Gemini, Groq, vLLM, OpenAI-compatible endpoints) and general LLM settings -- `[dialectic]` - Dialectic API configuration with per-level reasoning settings (minimal, low, medium, high, max) -- `[deriver]` - Background worker settings (worker count, polling intervals, queue management) and theory of mind configuration (model, tokens, observation limits) -- `[peer_card]` - Peer card generation settings (enable/disable) -- `[summary]` - Session summarization settings (frequency thresholds, provider, model, token limits for short and long summaries) -- `[dream]` - Dream processing configuration (enable/disable, thresholds, idle timeouts, dream types, LLM settings, surprisal sampling) -- `[webhook]` - Webhook configuration (webhook secret, workspace limits) -- `[metrics]` - Prometheus pull-based metrics settings -- `[telemetry]` - CloudEvents telemetry settings for analytics -- `[vector_store]` - Vector store configuration (pgvector, Turbopuffer, LanceDB) -- `[sentry]` - Error tracking and monitoring settings (enable/disable, DSN, environment, sample rates) +All config values map to environment variables: -### Using Environment Variables +- `{SECTION}_{KEY}` for section settings (e.g., `DB_CONNECTION_URI` → `[db].CONNECTION_URI`) +- `{KEY}` for app-level settings (e.g., `LOG_LEVEL` → `[app].LOG_LEVEL`) +- `{SECTION}__{NESTED}__{KEY}` for deeply nested settings (double underscore, e.g., `DIALECTIC_LEVELS__minimal__PROVIDER`) -All configuration values can be overridden using environment variables. The environment variable names follow this pattern: +## LLM Configuration -- `{SECTION}_{KEY}` for nested settings -- Just `{KEY}` for app-level settings -- `{SECTION}__{NESTED}__{KEY}` for deeply nested settings (double underscore) +The [Self-Hosting Guide](./self-hosting#llm-setup) covers the basic setup: one OpenAI-compatible endpoint, one model for all features. This section covers recommended model tiers, using multiple providers, and per-feature tuning. -Examples: + +All Honcho agents (deriver, dialectic, dream) require tool calling. Your models must support the OpenAI tool calling format. + -- `DB_CONNECTION_URI` → `[db].CONNECTION_URI` -- `DB_POOL_SIZE` → `[db].POOL_SIZE` -- `AUTH_JWT_SECRET` → `[auth].JWT_SECRET` -- `DERIVER_MODEL` → `[deriver].MODEL` -- `LOG_LEVEL` (no section) → `[app].LOG_LEVEL` -- `DIALECTIC_LEVELS__minimal__PROVIDER` → `[dialectic.levels.minimal].PROVIDER` -- `DREAM_SURPRISAL__ENABLED` → `[dream.surprisal].ENABLED` +### Choosing Models -### Configuration Priority +Model choice matters more for tool-use reliability than raw intelligence: -When a configuration value is set in multiple places, Honcho uses this priority: +| Tier | Example models | Use case | Notes | +|---|---|---|---| +| **Light** | Gemini 2.5 Flash, GLM-4.7-Flash | Deriver, summary, dialectic minimal/low | High throughput, cheap, reliable tool use | +| **Medium** | Claude Haiku 4.5, Grok 4.1 Fast | Dialectic medium/high | Good reasoning + tool use balance | +| **Heavy** | Claude Sonnet 4, GLM-5 | Dream, dialectic max | Best quality for rare/complex tasks | -1. **Environment variables** - Always take precedence -2. **.env file** - Loaded for local development -3. **config.toml** - Base configuration -4. **Default values** - Built-in defaults +You can mix providers freely — for example, use Gemini for the deriver and Claude for dreaming. -This allows you to: +### Provider Types -- Use `config.toml` for base configuration -- Override specific values with environment variables in production -- Use `.env` files for local development without modifying config.toml +| Provider value | What it connects to | Key env var | +|---|---|---| +| `custom` | Any OpenAI-compatible endpoint (OpenRouter, Together, Fireworks, LiteLLM, Ollama) | `LLM_OPENAI_COMPATIBLE_API_KEY` + `LLM_OPENAI_COMPATIBLE_BASE_URL` | +| `vllm` | vLLM self-hosted models | `LLM_VLLM_API_KEY` + `LLM_VLLM_BASE_URL` | +| `google` | Google Gemini (direct) | `LLM_GEMINI_API_KEY` | +| `anthropic` | Anthropic Claude (direct) | `LLM_ANTHROPIC_API_KEY` | +| `openai` | OpenAI (direct) | `LLM_OPENAI_API_KEY` | +| `groq` | Groq (direct) | `LLM_GROQ_API_KEY` | -### Example +### Tiered Model Setup -If you have this in `config.toml`: - -```toml -[db] -CONNECTION_URI = "postgresql://localhost/honcho_dev" -POOL_SIZE = 10 -``` - -You can override just the connection URI in production: +Once you're past initial setup, you can assign different models per feature for better cost/quality tradeoffs. This example uses OpenRouter with light/medium/heavy tiers: ```bash -export DB_CONNECTION_URI="postgresql://prod-server/honcho_prod" +LLM_OPENAI_COMPATIBLE_BASE_URL=https://openrouter.ai/api/v1 +LLM_OPENAI_COMPATIBLE_API_KEY=sk-or-v1-... + +# Light tier — high throughput, cheap +DERIVER_PROVIDER=custom +DERIVER_MODEL=google/gemini-2.5-flash-lite +SUMMARY_PROVIDER=custom +SUMMARY_MODEL=google/gemini-2.5-flash +DIALECTIC_LEVELS__minimal__PROVIDER=custom +DIALECTIC_LEVELS__minimal__MODEL=google/gemini-2.5-flash-lite +DIALECTIC_LEVELS__low__PROVIDER=custom +DIALECTIC_LEVELS__low__MODEL=google/gemini-2.5-flash-lite + +# Medium tier — better reasoning +DIALECTIC_LEVELS__medium__PROVIDER=custom +DIALECTIC_LEVELS__medium__MODEL=anthropic/claude-haiku-4-5 +DIALECTIC_LEVELS__high__PROVIDER=custom +DIALECTIC_LEVELS__high__MODEL=anthropic/claude-haiku-4-5 +DIALECTIC_LEVELS__max__PROVIDER=custom +DIALECTIC_LEVELS__max__MODEL=anthropic/claude-haiku-4-5 + +# Heavy tier — best quality for complex tasks +DREAM_PROVIDER=custom +DREAM_MODEL=anthropic/claude-sonnet-4-20250514 +DREAM_DEDUCTION_MODEL=anthropic/claude-haiku-4-5 +DREAM_INDUCTION_MODEL=anthropic/claude-haiku-4-5 ``` -The application will use the production connection URI while keeping the pool size from config.toml. +### Direct Vendor Keys -## Core Configuration - -### Application Settings - -Application-level settings control core behavior of the Honcho server including logging, session limits, message handling, and optional integrations. - -**Basic Application Configuration:** -```bash -# Logging and server settings -LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL - -# Session and context limits -SESSION_OBSERVERS_LIMIT=10 # Maximum number of observers per session -GET_CONTEXT_MAX_TOKENS=100000 # Maximum tokens for context retrieval -MAX_MESSAGE_SIZE=25000 # Maximum message size in characters -MAX_FILE_SIZE=5242880 # Maximum file size in bytes (5MB) - -# Embedding settings -EMBED_MESSAGES=true # Enable vector embeddings for messages -MAX_EMBEDDING_TOKENS=8192 # Maximum tokens per embedding -MAX_EMBEDDING_TOKENS_PER_REQUEST=300000 # Batch embedding limit - -# Global namespace (propagated to nested settings if not explicitly set) -NAMESPACE=honcho -``` - -**Optional Integrations:** -```bash -# Langfuse integration for LLM observability -LANGFUSE_HOST=https://cloud.langfuse.com -LANGFUSE_PUBLIC_KEY=your-langfuse-public-key - -# Local metrics collection -COLLECT_METRICS_LOCAL=false -LOCAL_METRICS_FILE=metrics.jsonl - -# Reasoning traces (for debugging) -REASONING_TRACES_FILE=traces.jsonl -``` - -### Database Configuration - -**Required Database Settings:** -```bash -# PostgreSQL connection string (required) -DB_CONNECTION_URI=postgresql+psycopg://username:password@host:port/database - -# Example for local development -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho - -# Example for production -DB_CONNECTION_URI=postgresql+psycopg://honcho_user:secure_password@db.example.com:5432/honcho_prod -``` - -**Database Pool Settings:** -```bash -# Connection pool configuration -DB_SCHEMA=public -DB_POOL_CLASS=default -DB_POOL_PRE_PING=true # Health check before reusing connections -DB_POOL_SIZE=10 -DB_MAX_OVERFLOW=20 -DB_POOL_TIMEOUT=30 # seconds (max 5 minutes) -DB_POOL_RECYCLE=300 # seconds (max 2 hours) -DB_POOL_USE_LIFO=true # Use LIFO for connection reuse -DB_SQL_DEBUG=false # Echo SQL queries -DB_TRACING=false # Enable query tracing -``` - -**Docker Compose for PostgreSQL:** -```yaml -# docker-compose.yml -version: '3.8' -services: - database: - image: pgvector/pgvector:pg15 - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: postgres - POSTGRES_DB: honcho - ports: - - "5432:5432" - volumes: - - postgres_data:/var/lib/postgresql/data - - ./init.sql:/docker-entrypoint-initdb.d/init.sql - -volumes: - postgres_data: -``` - -### Authentication Configuration - -**JWT Authentication:** -```bash -# Enable/disable authentication -AUTH_USE_AUTH=false # Set to true for production - -# JWT settings (required if AUTH_USE_AUTH is true) -AUTH_JWT_SECRET=your-super-secret-jwt-key -``` - -**Generate JWT Secret:** -```bash -# Generate a secure JWT secret -python scripts/generate_jwt_secret.py -``` - -### Cache Configuration - -Honcho supports Redis caching to improve performance by caching frequently accessed data like peers, sessions, and working representations. Caching also includes lock mechanisms to prevent cache stampede scenarios. - -**Redis Cache Settings:** -```bash -# Enable/disable Redis caching -CACHE_ENABLED=false # Set to true to enable caching - -# Redis connection -CACHE_URL=redis://localhost:6379/0?suppress=true - -# Cache namespace (inherits from app.NAMESPACE if not set) -CACHE_NAMESPACE=honcho - -# Cache TTL -CACHE_DEFAULT_TTL_SECONDS=300 # How long items stay in cache (5 minutes) - -# Lock settings for preventing cache stampede -CACHE_DEFAULT_LOCK_TTL_SECONDS=5 # Lock duration when fetching from DB on cache miss -``` - -**When to Enable Caching:** -- High-traffic production environments -- Applications with many repeated reads of the same data -- When you need to reduce database load - -**Note:** Caching requires a Redis instance. You can run Redis locally with Docker: -```bash -docker run -d -p 6379:6379 redis:latest -``` - -## LLM Provider Configuration - -Honcho supports multiple LLM providers for different tasks. API keys are configured in the `[llm]` section, while specific features use their own configuration sections. - -### API Keys - -All provider API keys use the `LLM_` prefix: +Instead of an OpenAI-compatible proxy, you can use vendor APIs directly. Leave `PROVIDER` overrides unset and the code defaults route per feature: ```bash -# Provider API Keys -LLM_ANTHROPIC_API_KEY=your-anthropic-api-key -LLM_OPENAI_API_KEY=your-openai-api-key -LLM_GEMINI_API_KEY=your-gemini-api-key -LLM_GROQ_API_KEY=your-groq-api-key +LLM_GEMINI_API_KEY=... # deriver, summary, dialectic minimal/low +LLM_ANTHROPIC_API_KEY=... # dialectic medium/high/max, dream +LLM_OPENAI_API_KEY=... # embeddings +``` -# OpenAI-compatible endpoints -LLM_OPENAI_COMPATIBLE_API_KEY=your-api-key -LLM_OPENAI_COMPATIBLE_BASE_URL=https://your-openai-compatible-endpoint.com +### Self-Hosted (vLLM / Ollama) -# vLLM endpoint (for local models) -LLM_VLLM_API_KEY=your-vllm-api-key -LLM_VLLM_BASE_URL=http://localhost:8000 +```bash +# vLLM +LLM_VLLM_BASE_URL=http://localhost:8000/v1 +LLM_VLLM_API_KEY=not-needed +DERIVER_PROVIDER=vllm +DERIVER_MODEL=your-model-name + +# Ollama (uses custom provider) +LLM_OPENAI_COMPATIBLE_BASE_URL=http://localhost:11434/v1 +LLM_OPENAI_COMPATIBLE_API_KEY=ollama +DERIVER_PROVIDER=custom +DERIVER_MODEL=llama3.3:70b +``` + +Set `PROVIDER` and `MODEL` for each feature the same way. + +### Thinking Budget + +Default configs use `THINKING_BUDGET_TOKENS` tuned for Anthropic models. Non-Anthropic providers don't support extended thinking and will error or silently fail. The [Self-Hosting Guide](./self-hosting#llm-setup) sets these to `0` by default. If you switch to Anthropic models, you can re-enable them: + +```bash +# Anthropic models — enable thinking +DERIVER_THINKING_BUDGET_TOKENS=1024 +SUMMARY_THINKING_BUDGET_TOKENS=512 +DREAM_THINKING_BUDGET_TOKENS=8192 +DIALECTIC_LEVELS__medium__THINKING_BUDGET_TOKENS=1024 +DIALECTIC_LEVELS__high__THINKING_BUDGET_TOKENS=1024 +DIALECTIC_LEVELS__max__THINKING_BUDGET_TOKENS=2048 +# minimal and low stay at 0 ``` ### General LLM Settings ```bash -# Default settings for all LLM calls LLM_DEFAULT_MAX_TOKENS=2500 # Embedding provider (used when EMBED_MESSAGES=true) @@ -292,23 +152,23 @@ LLM_MAX_MESSAGE_CONTENT_CHARS=2000 # Max chars per message in tool results ### Feature-Specific Model Configuration -Different features can use different providers and models: +Each feature can use a different provider and model. Below are all the tuning knobs. **Dialectic API:** -The Dialectic API provides theory-of-mind informed responses by integrating long-term facts with current context. It uses a tiered reasoning system with five levels: +The Dialectic API provides theory-of-mind informed responses. It uses a tiered reasoning system with five levels: ```bash # Global dialectic settings DIALECTIC_MAX_OUTPUT_TOKENS=8192 DIALECTIC_MAX_INPUT_TOKENS=100000 -DIALECTIC_HISTORY_TOKEN_LIMIT=8192 # Token limit for get_recent_history tool -DIALECTIC_SESSION_HISTORY_MAX_TOKENS=4096 # Max tokens of recent messages to include +DIALECTIC_HISTORY_TOKEN_LIMIT=8192 +DIALECTIC_SESSION_HISTORY_MAX_TOKENS=4096 ``` **Per-Level Configuration:** -Each reasoning level (minimal, low, medium, high, max) has its own provider, model, and settings: +Each reasoning level has its own provider, model, and settings: ```toml # config.toml example @@ -317,8 +177,8 @@ PROVIDER = "google" MODEL = "gemini-2.5-flash-lite" THINKING_BUDGET_TOKENS = 0 MAX_TOOL_ITERATIONS = 1 -MAX_OUTPUT_TOKENS = 250 # Optional: overrides global MAX_OUTPUT_TOKENS -TOOL_CHOICE = "any" # Options: null/auto, "any", "required" +MAX_OUTPUT_TOKENS = 250 +TOOL_CHOICE = "any" [dialectic.levels.low] PROVIDER = "google" @@ -344,12 +204,9 @@ PROVIDER = "anthropic" MODEL = "claude-haiku-4-5" THINKING_BUDGET_TOKENS = 2048 MAX_TOOL_ITERATIONS = 10 -# Backup provider (optional, must set both or neither) -# BACKUP_PROVIDER = "google" -# BACKUP_MODEL = "gemini-2.5-pro" ``` -**Environment variables for nested dialectic levels:** +Environment variables for nested levels use double underscores: ```bash DIALECTIC_LEVELS__minimal__PROVIDER=google DIALECTIC_LEVELS__minimal__MODEL=gemini-2.5-flash-lite @@ -359,103 +216,67 @@ DIALECTIC_LEVELS__minimal__MAX_TOOL_ITERATIONS=1 **Deriver (Theory of Mind):** -The Deriver is a background processing system that extracts facts from messages and builds theory-of-mind representations of peers. +The Deriver extracts facts from messages and builds theory-of-mind representations of peers. ```bash -# Enable/disable deriver DERIVER_ENABLED=true -# LLM settings for deriver +# LLM settings DERIVER_PROVIDER=google DERIVER_MODEL=gemini-2.5-flash-lite DERIVER_MAX_OUTPUT_TOKENS=4096 DERIVER_THINKING_BUDGET_TOKENS=1024 -DERIVER_MAX_INPUT_TOKENS=23000 # Maximum input tokens for deriver -DERIVER_TEMPERATURE= # Optional temperature override (unset by default) - -# Backup provider (optional, must set both or neither) -# DERIVER_BACKUP_PROVIDER=anthropic -# DERIVER_BACKUP_MODEL=claude-haiku-4-5 +DERIVER_MAX_INPUT_TOKENS=23000 +DERIVER_TEMPERATURE= # Optional override (unset by default) # Worker settings -DERIVER_WORKERS=1 # Number of background worker processes -DERIVER_POLLING_SLEEP_INTERVAL_SECONDS=1.0 # Time between queue checks -DERIVER_STALE_SESSION_TIMEOUT_MINUTES=5 # Timeout for stale sessions +DERIVER_WORKERS=1 # Increase for higher throughput +DERIVER_POLLING_SLEEP_INTERVAL_SECONDS=1.0 +DERIVER_STALE_SESSION_TIMEOUT_MINUTES=5 # Queue management -DERIVER_QUEUE_ERROR_RETENTION_SECONDS=2592000 # Keep errored items for 30 days - -# Document settings -DERIVER_DEDUPLICATE=true # Deduplicate documents when creating +DERIVER_QUEUE_ERROR_RETENTION_SECONDS=2592000 # 30 days # Observation settings -DERIVER_LOG_OBSERVATIONS=false # Log all observations -DERIVER_WORKING_REPRESENTATION_MAX_OBSERVATIONS=100 # Max observations stored -DERIVER_REPRESENTATION_BATCH_MAX_TOKENS=1024 # Max tokens per batch (must be <= MAX_INPUT_TOKENS) +DERIVER_DEDUPLICATE=true +DERIVER_LOG_OBSERVATIONS=false +DERIVER_WORKING_REPRESENTATION_MAX_OBSERVATIONS=100 +DERIVER_REPRESENTATION_BATCH_MAX_TOKENS=1024 ``` **Peer Card:** -Peer cards are short, structured summaries of peer identity and characteristics. - ```bash -# Enable/disable peer card generation PEER_CARD_ENABLED=true ``` **Summary Generation:** -Session summaries provide compressed context for long conversations. Honcho creates two types: short summaries (frequent) and long summaries (comprehensive). +Session summaries provide compressed context for long conversations — short summaries (frequent) and long summaries (comprehensive). ```bash -# Enable/disable summarization SUMMARY_ENABLED=true - -# LLM settings for summary generation SUMMARY_PROVIDER=google SUMMARY_MODEL=gemini-2.5-flash -SUMMARY_MAX_TOKENS_SHORT=1000 # Max tokens for short summaries -SUMMARY_MAX_TOKENS_LONG=4000 # Max tokens for long summaries +SUMMARY_MAX_TOKENS_SHORT=1000 +SUMMARY_MAX_TOKENS_LONG=4000 SUMMARY_THINKING_BUDGET_TOKENS=512 - -# Backup provider (optional, must set both or neither) -# SUMMARY_BACKUP_PROVIDER=anthropic -# SUMMARY_BACKUP_MODEL=claude-haiku-4-5 - -# Summary frequency thresholds -SUMMARY_MESSAGES_PER_SHORT_SUMMARY=20 # Create short summary every N messages -SUMMARY_MESSAGES_PER_LONG_SUMMARY=60 # Create long summary every N messages +SUMMARY_MESSAGES_PER_SHORT_SUMMARY=20 +SUMMARY_MESSAGES_PER_LONG_SUMMARY=60 ``` -### Default Provider Usage +**Dream Processing:** -By default, Honcho uses: -- **Google** (Gemini) for dialectic API (minimal/low levels), deriver, and summarization -- **Anthropic** (Claude) for dialectic API (medium/high/max levels) and dream processing -- **OpenAI** for embeddings (if `EMBED_MESSAGES=true`) +Dream processing consolidates and refines peer representations during idle periods. -You only need to set the API keys for the providers you plan to use. All providers are configurable per feature. - -## Additional Features Configuration - -### Dream Processing - -Dream processing consolidates and refines peer representations during idle periods, similar to how human memory consolidation works during sleep. - -**Dream Settings:** ```bash -# Enable/disable dream processing DREAM_ENABLED=true +DREAM_DOCUMENT_THRESHOLD=50 +DREAM_IDLE_TIMEOUT_MINUTES=60 +DREAM_MIN_HOURS_BETWEEN_DREAMS=8 +DREAM_ENABLED_TYPES=["omni"] -# Trigger thresholds -DREAM_DOCUMENT_THRESHOLD=50 # Minimum documents to trigger a dream -DREAM_IDLE_TIMEOUT_MINUTES=60 # Minutes of inactivity before dream can start -DREAM_MIN_HOURS_BETWEEN_DREAMS=8 # Minimum hours between dreams for a peer - -# Dream types to enable -DREAM_ENABLED_TYPES=["omni"] # Currently supported: omni - -# LLM settings for dream processing +# LLM settings DREAM_PROVIDER=anthropic DREAM_MODEL=claude-sonnet-4-20250514 DREAM_MAX_OUTPUT_TOKENS=16384 @@ -463,10 +284,6 @@ DREAM_THINKING_BUDGET_TOKENS=8192 DREAM_MAX_TOOL_ITERATIONS=20 DREAM_HISTORY_TOKEN_LIMIT=16384 -# Backup provider (optional, must set both or neither) -# DREAM_BACKUP_PROVIDER=google -# DREAM_BACKUP_MODEL=gemini-2.5-flash - # Specialist models (use same provider as main model) DREAM_DEDUCTION_MODEL=claude-haiku-4-5 DREAM_INDUCTION_MODEL=claude-haiku-4-5 @@ -474,155 +291,163 @@ DREAM_INDUCTION_MODEL=claude-haiku-4-5 **Surprisal-Based Sampling (Advanced):** -The dream system includes an optional surprisal-based sampling subsystem for identifying unusual or surprising observations: +Optional subsystem for identifying unusual observations during dreaming: ```bash -# Enable/disable surprisal sampling DREAM_SURPRISAL__ENABLED=false - -# Tree configuration for similarity search -DREAM_SURPRISAL__TREE_TYPE=kdtree # Options: kdtree, balltree, rptree, covertree, lsh, graph, prototype -DREAM_SURPRISAL__TREE_K=5 # k for kNN-based trees - -# Sampling strategy -DREAM_SURPRISAL__SAMPLING_STRATEGY=recent # Options: recent, random, all +DREAM_SURPRISAL__TREE_TYPE=kdtree +DREAM_SURPRISAL__TREE_K=5 +DREAM_SURPRISAL__SAMPLING_STRATEGY=recent DREAM_SURPRISAL__SAMPLE_SIZE=200 - -# Surprisal filtering (normalized scores: 0.0 = lowest, 1.0 = highest) -DREAM_SURPRISAL__TOP_PERCENT_SURPRISAL=0.10 # Top 10% of observations +DREAM_SURPRISAL__TOP_PERCENT_SURPRISAL=0.10 DREAM_SURPRISAL__MIN_HIGH_SURPRISAL_FOR_REPLACE=10 - -# Observation level filtering DREAM_SURPRISAL__INCLUDE_LEVELS=["explicit", "deductive"] ``` -### Webhook Configuration +## Core Configuration -Webhooks allow you to receive real-time notifications when events occur in Honcho (e.g., new messages, session updates). +### Application Settings -**Webhook Settings:** ```bash -# Webhook secret for signing payloads (optional but recommended) -WEBHOOK_SECRET=your-webhook-signing-secret +LOG_LEVEL=INFO # DEBUG, INFO, WARNING, ERROR, CRITICAL +SESSION_OBSERVERS_LIMIT=10 +GET_CONTEXT_MAX_TOKENS=100000 +MAX_MESSAGE_SIZE=25000 +MAX_FILE_SIZE=5242880 # 5MB +EMBED_MESSAGES=true +MAX_EMBEDDING_TOKENS=8192 +MAX_EMBEDDING_TOKENS_PER_REQUEST=300000 +NAMESPACE=honcho +``` -# Limit on webhooks per workspace +**Optional Integrations:** +```bash +LANGFUSE_HOST=https://cloud.langfuse.com +LANGFUSE_PUBLIC_KEY=your-langfuse-public-key +COLLECT_METRICS_LOCAL=false +LOCAL_METRICS_FILE=metrics.jsonl +REASONING_TRACES_FILE=traces.jsonl +``` + +### Database + +```bash +# Connection (required) +DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/postgres + +# Pool settings +DB_SCHEMA=public +DB_POOL_PRE_PING=true +DB_POOL_SIZE=10 +DB_MAX_OVERFLOW=20 +DB_POOL_TIMEOUT=30 +DB_POOL_RECYCLE=300 +DB_POOL_USE_LIFO=true +DB_SQL_DEBUG=false +``` + +### Authentication + +```bash +AUTH_USE_AUTH=false # Set to true to require JWT tokens +AUTH_JWT_SECRET=your-super-secret-jwt-key # Required when auth is enabled +``` + +Generate a secret: `python scripts/generate_jwt_secret.py` + +### Cache (Redis) + +Redis caching is optional. Honcho works without it but benefits from caching in high-traffic scenarios. + +```bash +CACHE_ENABLED=false +CACHE_URL=redis://localhost:6379/0?suppress=true +CACHE_NAMESPACE=honcho +CACHE_DEFAULT_TTL_SECONDS=300 +CACHE_DEFAULT_LOCK_TTL_SECONDS=5 # Cache stampede prevention +``` + +### Webhooks + +```bash +WEBHOOK_SECRET=your-webhook-signing-secret WEBHOOK_MAX_WORKSPACE_LIMIT=10 ``` -### Vector Store Configuration +### Vector Store -Honcho supports multiple vector store backends for storing embeddings. - -**Vector Store Settings:** ```bash -# Vector store type VECTOR_STORE_TYPE=pgvector # Options: pgvector, turbopuffer, lancedb - -# Migration flag (set to true when migration from pgvector is complete) VECTOR_STORE_MIGRATED=false - -# Global namespace prefix for all vector namespaces VECTOR_STORE_NAMESPACE=honcho - -# Embedding dimensions (default for OpenAI text-embedding-3-small) VECTOR_STORE_DIMENSIONS=1536 -# Reconciliation interval for syncing -VECTOR_STORE_RECONCILIATION_INTERVAL_SECONDS=300 # 5 minutes - -# Turbopuffer-specific settings (required if TYPE=turbopuffer) +# Turbopuffer-specific VECTOR_STORE_TURBOPUFFER_API_KEY=your-turbopuffer-api-key VECTOR_STORE_TURBOPUFFER_REGION=us-east-1 -# LanceDB-specific settings (local embedded mode) +# LanceDB-specific VECTOR_STORE_LANCEDB_PATH=./lancedb_data ``` -## Monitoring Configuration +## Monitoring -### Prometheus Metrics (Pull-based) +### Prometheus Metrics -Honcho exposes Prometheus metrics via `/metrics` endpoints for scraping: -- **API process**: Port 8000 at `/metrics` -- **Deriver process**: Port 9090 at `/metrics` +Honcho exposes `/metrics` endpoints for scraping: +- **API process**: Port 8000 +- **Deriver process**: Port 9090 -**Metrics Settings:** ```bash -# Enable/disable Prometheus metrics METRICS_ENABLED=false - -# Namespace label for all metrics (inherits from app.NAMESPACE if not set) METRICS_NAMESPACE=honcho ``` -### CloudEvents Telemetry (Analytics) +### CloudEvents Telemetry -Honcho can emit structured CloudEvents for analytics purposes. - -**Telemetry Settings:** ```bash -# Enable/disable CloudEvents emission TELEMETRY_ENABLED=false - -# CloudEvents HTTP endpoint TELEMETRY_ENDPOINT=https://telemetry.honcho.dev/v1/events - -# Optional auth headers (JSON format in env var) TELEMETRY_HEADERS='{"Authorization": "Bearer your-token"}' - -# Batching configuration TELEMETRY_BATCH_SIZE=100 TELEMETRY_FLUSH_INTERVAL_SECONDS=1.0 -TELEMETRY_FLUSH_THRESHOLD=50 - -# Retry configuration TELEMETRY_MAX_RETRIES=3 - -# Buffer configuration TELEMETRY_MAX_BUFFER_SIZE=10000 - -# Namespace for instance identification (inherits from app.NAMESPACE if not set) -TELEMETRY_NAMESPACE=honcho ``` -### Sentry Error Tracking +### Sentry -**Sentry Settings:** ```bash -# Enable/disable Sentry error tracking SENTRY_ENABLED=false - -# Sentry configuration SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id -SENTRY_RELEASE=2.4.0 # Optional: track which version errors come from -SENTRY_ENVIRONMENT=production # Environment name (development, staging, production) - -# Sampling rates (0.0 to 1.0) -SENTRY_TRACES_SAMPLE_RATE=0.1 # 10% of transactions tracked -SENTRY_PROFILES_SAMPLE_RATE=0.1 # 10% of transactions profiled +SENTRY_ENVIRONMENT=production +SENTRY_TRACES_SAMPLE_RATE=0.1 +SENTRY_PROFILES_SAMPLE_RATE=0.1 ``` -## Environment-Specific Examples +## Reference config.toml -### Development Configuration +A complete config.toml with all defaults. Copy and modify what you need: -**config.toml for development:** ```toml [app] -LOG_LEVEL = "DEBUG" +LOG_LEVEL = "INFO" SESSION_OBSERVERS_LIMIT = 10 -EMBED_MESSAGES = false -NAMESPACE = "honcho-dev" +EMBED_MESSAGES = true +NAMESPACE = "honcho" [db] -CONNECTION_URI = "postgresql+psycopg://postgres:postgres@localhost:5432/honcho_dev" -POOL_SIZE = 5 +CONNECTION_URI = "postgresql+psycopg://postgres:postgres@localhost:5432/postgres" +POOL_SIZE = 10 +MAX_OVERFLOW = 20 [auth] USE_AUTH = false [cache] ENABLED = false +URL = "redis://localhost:6379/0?suppress=true" +DEFAULT_TTL_SECONDS = 300 [deriver] ENABLED = true @@ -670,8 +495,6 @@ MAX_TOOL_ITERATIONS = 10 ENABLED = true PROVIDER = "google" MODEL = "gemini-2.5-flash" -MAX_TOKENS_SHORT = 1000 -MAX_TOKENS_LONG = 4000 [dream] ENABLED = true @@ -694,194 +517,25 @@ TYPE = "pgvector" ENABLED = false ``` -**Environment variables for development:** +## Database Migrations + ```bash -# .env.development -LOG_LEVEL=DEBUG -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho_dev -AUTH_USE_AUTH=false -CACHE_ENABLED=false - -# LLM Provider API Keys -LLM_ANTHROPIC_API_KEY=your-dev-anthropic-key -LLM_OPENAI_API_KEY=your-dev-openai-key -LLM_GEMINI_API_KEY=your-dev-gemini-key -``` - -### Production Configuration - -**config.toml for production:** -```toml -[app] -LOG_LEVEL = "WARNING" -SESSION_OBSERVERS_LIMIT = 10 -EMBED_MESSAGES = true -NAMESPACE = "honcho-prod" - -[db] -CONNECTION_URI = "postgresql+psycopg://honcho_user:secure_password@prod-db:5432/honcho_prod" -POOL_SIZE = 20 -MAX_OVERFLOW = 40 - -[auth] -USE_AUTH = true - -[cache] -ENABLED = true -URL = "redis://redis:6379/0" -DEFAULT_TTL_SECONDS = 300 - -[deriver] -ENABLED = true -WORKERS = 4 -PROVIDER = "google" -MODEL = "gemini-2.5-flash-lite" - -[peer_card] -ENABLED = true - -[dialectic] -MAX_OUTPUT_TOKENS = 8192 - -[dialectic.levels.minimal] -PROVIDER = "google" -MODEL = "gemini-2.5-flash-lite" -THINKING_BUDGET_TOKENS = 0 -MAX_TOOL_ITERATIONS = 1 - -[dialectic.levels.low] -PROVIDER = "google" -MODEL = "gemini-2.5-flash-lite" -THINKING_BUDGET_TOKENS = 0 -MAX_TOOL_ITERATIONS = 5 - -[dialectic.levels.medium] -PROVIDER = "anthropic" -MODEL = "claude-haiku-4-5" -THINKING_BUDGET_TOKENS = 1024 -MAX_TOOL_ITERATIONS = 2 - -[dialectic.levels.high] -PROVIDER = "anthropic" -MODEL = "claude-haiku-4-5" -THINKING_BUDGET_TOKENS = 1024 -MAX_TOOL_ITERATIONS = 4 - -[dialectic.levels.max] -PROVIDER = "anthropic" -MODEL = "claude-haiku-4-5" -THINKING_BUDGET_TOKENS = 2048 -MAX_TOOL_ITERATIONS = 10 - -[summary] -ENABLED = true -PROVIDER = "google" -MODEL = "gemini-2.5-flash" -MAX_TOKENS_SHORT = 1000 -MAX_TOKENS_LONG = 4000 - -[dream] -ENABLED = true -PROVIDER = "anthropic" -MODEL = "claude-sonnet-4-20250514" - -[webhook] -MAX_WORKSPACE_LIMIT = 10 - -[metrics] -ENABLED = true - -[telemetry] -ENABLED = true - -[vector_store] -TYPE = "pgvector" - -[sentry] -ENABLED = true -ENVIRONMENT = "production" -TRACES_SAMPLE_RATE = 0.1 -PROFILES_SAMPLE_RATE = 0.1 -``` - -**Environment variables for production:** -```bash -# .env.production -LOG_LEVEL=WARNING -DB_CONNECTION_URI=postgresql+psycopg://honcho_user:secure_password@prod-db:5432/honcho_prod - -# Authentication -AUTH_USE_AUTH=true -AUTH_JWT_SECRET=your-super-secret-jwt-key - -# Cache -CACHE_ENABLED=true -CACHE_URL=redis://redis:6379/0 - -# LLM Provider API Keys -LLM_ANTHROPIC_API_KEY=your-prod-anthropic-key -LLM_OPENAI_API_KEY=your-prod-openai-key -LLM_GEMINI_API_KEY=your-prod-gemini-key -LLM_GROQ_API_KEY=your-prod-groq-key - -# Webhooks -WEBHOOK_SECRET=your-webhook-signing-secret - -# Monitoring -METRICS_ENABLED=true -TELEMETRY_ENDPOINT=https://telemetry.honcho.dev/v1/events -SENTRY_DSN=https://your-sentry-dsn@sentry.io/project-id -SENTRY_ENVIRONMENT=production -``` - -## Migration Management - -**Running Database Migrations:** -```bash -# Check current migration status -uv run alembic current - -# Upgrade to latest -uv run alembic upgrade head - -# Downgrade to specific revision -uv run alembic downgrade revision_id - -# Create new migration -uv run alembic revision --autogenerate -m "Description of changes" +uv run alembic current # Check status +uv run alembic upgrade head # Upgrade to latest +uv run alembic downgrade # Downgrade to specific revision +uv run alembic revision --autogenerate -m "Description" # Create new migration ``` ## Troubleshooting -**Common Configuration Issues:** +1. **Database connection errors** — Ensure `DB_CONNECTION_URI` uses `postgresql+psycopg://` prefix. Verify database is running and pgvector extension is installed. -1. **Database Connection Errors** - - Ensure `DB_CONNECTION_URI` uses `postgresql+psycopg://` prefix - - Verify database is running and accessible - - Check pgvector extension is installed +2. **Authentication issues** — Generate and set `AUTH_JWT_SECRET` when `AUTH_USE_AUTH=true`. Use `python scripts/generate_jwt_secret.py`. -2. **Authentication Issues** - - Set `AUTH_USE_AUTH=true` for production - - Generate and set `AUTH_JWT_SECRET` if authentication is enabled - - Use `python scripts/generate_jwt_secret.py` to create a secure secret +3. **LLM provider errors** — Verify API keys are set. Check model names match your provider's format. Ensure models support tool calling. -3. **LLM Provider Issues** - - Verify API keys are set correctly - - Check model names match provider specifications - - Ensure provider is enabled in configuration +4. **Deriver not processing** — Check logs. Increase `DERIVER_WORKERS` for throughput. Verify database and LLM connectivity. -4. **Deriver Issues** - - Increase `DERIVER_WORKERS` for better performance - - Check `DERIVER_STALE_SESSION_TIMEOUT_MINUTES` for session cleanup - - Monitor background processing logs +5. **Dialectic level issues** — All five levels must be configured. For Anthropic, `THINKING_BUDGET_TOKENS` must be >= 1024. For non-Anthropic providers, set to `0`. `MAX_OUTPUT_TOKENS` must exceed `THINKING_BUDGET_TOKENS`. -5. **Dialectic Level Configuration** - - Ensure all five reasoning levels are configured (minimal, low, medium, high, max) - - For Anthropic provider, `THINKING_BUDGET_TOKENS` must be >= 1024 when enabled - - `MAX_OUTPUT_TOKENS` must be greater than `THINKING_BUDGET_TOKENS` for all levels - -6. **Vector Store Issues** - - For Turbopuffer, ensure `VECTOR_STORE_TURBOPUFFER_API_KEY` is set - - Check `VECTOR_STORE_DIMENSIONS` matches your embedding model - -This configuration guide covers all the settings available in Honcho. Always use environment-specific configuration files and never commit sensitive values like API keys or JWT secrets to version control. +6. **Vector store issues** — For Turbopuffer, set the API key. Check `VECTOR_STORE_DIMENSIONS` matches your embedding model. diff --git a/docs/v3/contributing/self-hosting.mdx b/docs/v3/contributing/self-hosting.mdx index 4c9c4f22..fc298bd8 100644 --- a/docs/v3/contributing/self-hosting.mdx +++ b/docs/v3/contributing/self-hosting.mdx @@ -20,9 +20,9 @@ By the end of this guide, you'll have: Before you begin, ensure you have the following installed: ### Required Software -- **uv** - Python package manager: `pip install uv` (manages Python installations automatically) +- **uv** - Python package manager: `curl -LsSf https://astral.sh/uv/install.sh | sh` or `brew install uv` - **Git** - [Download from git-scm.com](https://git-scm.com/downloads) -- **Docker** (optional) - [Download from docker.com](https://www.docker.com/products/docker-desktop/) +- **Docker** (required for Docker setup, not needed for manual setup) - [Download from docker.com](https://www.docker.com/products/docker-desktop/) ### Database Options You'll need a PostgreSQL database with the pgvector extension. Choose one: @@ -32,9 +32,48 @@ You'll need a PostgreSQL database with the pgvector extension. Choose one: - **Railway** - Simple cloud PostgreSQL hosting - **Your own PostgreSQL server** +## LLM Setup + +Honcho uses LLMs for memory extraction, summarization, dialectic chat, and dreaming. The server will **fail to start** without a provider configured. + +You need one API key and one model. Any OpenAI-compatible endpoint works — OpenRouter, Together, Fireworks, Ollama, vLLM, or a direct vendor API. Models must support tool calling (function calling). + +The `.env.template` has provider and model lines ready for each feature. After copying it to `.env`, you need to set three things: + +```bash +# 1. Your endpoint and API key (already uncommented in the template) +LLM_OPENAI_COMPATIBLE_BASE_URL=https://openrouter.ai/api/v1 +LLM_OPENAI_COMPATIBLE_API_KEY=sk-or-v1-... + +# 2. Replace "your-model-here" everywhere with your model +# (these are spread across the Deriver, Dialectic, Summary, and Dream sections) +DERIVER_MODEL=google/gemini-2.5-flash # e.g. google/gemini-2.5-flash +SUMMARY_MODEL=google/gemini-2.5-flash +DREAM_MODEL=google/gemini-2.5-flash +DIALECTIC_LEVELS__minimal__MODEL=google/gemini-2.5-flash +# ... same for low, medium, high, max + +# 3. Everything else is already configured: +# - PROVIDER=custom for all features (routes through your endpoint) +# - THINKING_BUDGET_TOKENS=0 (correct for non-Anthropic models) +# - LLM_EMBEDDING_PROVIDER=openrouter (uses same endpoint for embeddings) +``` + +Use find-and-replace to swap all `your-model-here` with your chosen model in one step. + + +For recommended model tiers per feature, using multiple providers, or direct vendor API keys, see the [Configuration Guide](./configuration#llm-configuration). + + + +**Community quick-start**: [elkimek/honcho-self-hosted](https://github.com/elkimek/honcho-self-hosted) provides a one-command installer with pre-configured model tiers, interactive provider setup, and Hermes Agent integration. + + ## Docker Setup (Recommended) -The easiest way to get started is using Docker Compose, which handles both the database and Honcho server. +Docker Compose handles the database, Redis, and Honcho server. The compose file **builds the image from source** (there is no pre-built image on Docker Hub). This requires Docker with BuildKit enabled — see [Troubleshooting](./troubleshooting#docker-build-fails-with-permission-errors) if the build fails. + +The compose file is production-oriented by default (ports bound to `127.0.0.1`, restart policies, caching enabled). For development, uncomment the source mounts and monitoring services inside the file. ### 1. Clone the Repository @@ -51,45 +90,37 @@ Copy the example environment file and configure it: cp .env.template .env ``` -Edit `.env` and set your API keys (if using LLM features): - -```bash -# Optional API keys (required for LLM features) -OPENAI_API_KEY=your-openai-api-key -ANTHROPIC_API_KEY=your-anthropic-api-key - -# Database will be created automatically by Docker -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres - -# Disable auth for local development -AUTH_USE_AUTH=false -``` +Edit `.env` and configure your LLM provider — see [LLM Setup](#llm-setup) above. The database connection is set in the compose file. Auth is disabled by default (`AUTH_USE_AUTH=false`). ### 3. Start the Services ```bash -# Copy the example docker-compose file cp docker-compose.yml.example docker-compose.yml - -# Start PostgreSQL and Honcho -docker compose up -d +docker compose up -d --build ``` -### 4. Verify It's Working +The first build takes a few minutes (compiling from source). Subsequent starts are fast. -Check that both services are running: +This starts four services: **api** (port 8000), **deriver** (background worker), **database** (PostgreSQL with pgvector, port 5432), and **redis** (port 6379). All ports are bound to `127.0.0.1`. Redis caching is enabled by default. + +For development, uncomment the source mount and monitoring sections inside `docker-compose.yml` to enable live reload, Prometheus, and Grafana. + +### 4. Verify + +Migrations run automatically on startup. ```bash +# Check all containers are running docker compose ps -``` -Test the Honcho API: - -```bash +# Health check (confirms the process is up) curl http://localhost:8000/health + +# Check the deriver is processing (look for "polling" or "processing" in logs) +docker compose logs deriver --tail 20 ``` -You should see a response indicating the service is healthy. +For a full end-to-end test, see [Verify Your Setup](#verify-your-setup) below. ## Manual Setup @@ -134,26 +165,22 @@ Download from [postgresql.org](https://www.postgresql.org/download/windows/) ```bash docker run --name honcho-db \ - -e POSTGRES_DB=honcho \ -e POSTGRES_USER=postgres \ -e POSTGRES_PASSWORD=postgres \ -p 5432:5432 \ -d pgvector/pgvector:pg15 ``` -### 3. Create Database and Enable Extensions +### 3. Enable Extensions -Connect to PostgreSQL and set up the database: +Connect to PostgreSQL and enable pgvector: ```bash # Connect to PostgreSQL psql -U postgres -# Create database and enable extensions -CREATE DATABASE honcho; -\c honcho +# Enable the pgvector extension on the default database CREATE EXTENSION IF NOT EXISTS vector; -CREATE EXTENSION IF NOT EXISTS pg_trgm; \q ``` @@ -165,17 +192,10 @@ Create a `.env` file with your settings: cp .env.template .env ``` -Edit `.env` with your configuration: +Edit `.env` — configure your LLM provider (see [LLM Setup](#llm-setup) above) and set the database connection: ```bash -# Database connection -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho - -# Optional API keys (required for LLM features) -OPENAI_API_KEY=your-openai-api-key -ANTHROPIC_API_KEY=your-anthropic-api-key - -# Development settings +DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/postgres AUTH_USE_AUTH=false LOG_LEVEL=DEBUG ``` @@ -191,11 +211,21 @@ uv run alembic upgrade head ```bash # Start the development server -fastapi dev src/main.py +uv run fastapi dev src/main.py ``` The server will be available at `http://localhost:8000`. +### 7. Start the Background Worker (Deriver) + +In a **separate terminal**, start the deriver background worker: + +```bash +uv run python -m src.deriver +``` + +The deriver is essential for Honcho's core functionality. It processes incoming messages to extract observations, build peer representations, generate session summaries, and run dream consolidation. Without it, messages will be stored but no memory or reasoning will occur. + ## Cloud Database Setup If you prefer to use a managed PostgreSQL service: @@ -206,7 +236,6 @@ If you prefer to use a managed PostgreSQL service: 2. **Enable pgvector extension** in the SQL editor: ```sql CREATE EXTENSION IF NOT EXISTS vector; - CREATE EXTENSION IF NOT EXISTS pg_trgm; ``` 3. **Get your connection string** from Settings > Database 4. **Update your `.env` file** with the connection string @@ -227,23 +256,38 @@ Once your Honcho server is running, verify everything is working: ```bash curl http://localhost:8000/health +# {"status":"ok"} ``` -### 2. API Documentation +Note: `/health` only confirms the process is running. It does not check database or LLM connectivity. + +### 2. Smoke Test (database + API) + +This confirms the database connection, migrations, and API are all working: + +```bash +# Create a workspace +curl -s -X POST http://localhost:8000/v3/workspaces \ + -H "Content-Type: application/json" \ + -d '{"name": "test"}' | python3 -m json.tool +``` + +If you get back a workspace object with an `id`, your database is connected and migrations ran correctly. + +### 3. API Documentation Visit `http://localhost:8000/docs` to see the interactive API documentation. -### 3. Test with SDK - -Create a simple test script: +### 4. Test with SDK ```python from honcho import Honcho -# Connect to your local instance -client = Honcho(base_url="http://localhost:8000") +client = Honcho( + base_url="http://localhost:8000", + workspace_id="test" +) -# Create a test peer peer = client.peer("test-user") print(f"Created peer: {peer.id}") ``` @@ -259,8 +303,7 @@ Now that Honcho is running locally, you can connect your applications: from honcho import Honcho client = Honcho( - base_url="http://localhost:8000", # Your local instance - api_key="your-api-key" # If auth is enabled + base_url="http://localhost:8000", ) ``` @@ -269,56 +312,93 @@ client = Honcho( import { Honcho } from '@honcho-ai/sdk'; const client = new Honcho({ - baseUrl: 'http://localhost:8000', // Your local instance - apiKey: 'your-api-key' // If auth is enabled + baseUrl: 'http://localhost:8000', }); ``` ### Next Steps +- **Configure Honcho**: Visit the [Configuration Guide](./configuration) for model tiers, provider options, and tuning - **Explore the API**: Check out the [API Reference](../api-reference/introduction) - **Try the SDKs**: See our [guides](../guides) for examples -- **Configure Honcho**: Visit the [Configuration Guide](./configuration) for detailed settings - **Join the community**: [Discord](https://discord.gg/honcho) ## Troubleshooting -### Common Issues +Running into issues? See the [Troubleshooting Guide](./troubleshooting) for detailed solutions to common problems including: -**Database Connection Errors** -- Ensure PostgreSQL is running -- Verify the connection string format: `postgresql+psycopg://...` -- Check that pgvector extension is installed +- Startup failures (missing API keys, database issues) +- Runtime errors ("An unexpected error occurred" on every request) +- Deriver not processing messages +- Database connection and migration issues +- Docker and Redis problems -**API Key Issues** -- Verify your OpenAI and Anthropic API keys are valid -- Check that the keys have sufficient credits/quota - -**Port Already in Use** -- Pass a different port to FastAPI or stop other services using port 8000 - -**Docker Issues** -- Ensure Docker is running -- Check container logs: `docker compose logs` -- Restart containers: `docker compose down && docker compose up -d` - -**Migration Errors** -- Ensure the database exists and pgvector is enabled -- Check database permissions -- Run migrations manually: `uv run alembic upgrade head` - -### Getting Help - -- **GitHub Issues**: [Report bugs](https://github.com/plastic-labs/honcho/issues) -- **Discord**: [Join our community](https://discord.gg/honcho) -- **Documentation**: Check the [Configuration Guide](./configuration) for detailed settings +**Quick checks:** +- Verify the server is running: `curl http://localhost:8000/health` +- Check logs: `docker compose logs api` (Docker) or check terminal output (manual setup) +- Ensure migrations ran: `uv run alembic upgrade head` ## Production Considerations -When self-hosting for production, consider: +The default compose file is already production-oriented — ports bound to `127.0.0.1`, restart policies, caching enabled. -- **Security**: Enable authentication, use HTTPS, secure your database -- **Scaling**: Use connection pooling, consider load balancing -- **Monitoring**: Set up logging, error tracking, health checks -- **Backups**: Regular database backups, disaster recovery plan -- **Updates**: Keep Honcho and dependencies updated +### Security +- Set `AUTH_USE_AUTH=true` and generate a JWT secret with `python scripts/generate_jwt_secret.py` +- Use HTTPS via a reverse proxy in front of Honcho. Example with Caddy (automatic TLS): + ``` + honcho.example.com { + reverse_proxy localhost:8000 + } + ``` + Or with nginx: + ```nginx + server { + listen 443 ssl; + server_name honcho.example.com; + ssl_certificate /etc/letsencrypt/live/honcho.example.com/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/honcho.example.com/privkey.pem; + location / { + proxy_pass http://127.0.0.1:8000; + 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; + } + } + ``` +- Secure your database with strong credentials and restrict network access +- The production compose binds PostgreSQL and Redis to `127.0.0.1` only — they are not accessible from the network + +### Scaling the Deriver +- Increase `DERIVER_WORKERS` (default: 1) for higher message throughput +- You can also run multiple deriver processes across machines — they coordinate via the database queue +- Monitor deriver logs for processing backlog + +### Caching +- The production compose enables Redis caching by default (`CACHE_ENABLED=true`) +- For the development compose, enable manually: `CACHE_ENABLED=true` +- Configure `CACHE_URL` to point to your Redis instance (or use a managed Redis service) + +### Database Migrations +- Always run `uv run alembic upgrade head` after updating Honcho before starting the server +- Check current migration status with `uv run alembic current` + +### LLM Providers +- Ensure your API keys are configured (see [LLM Setup](#llm-setup)) +- For alternative providers or per-feature model overrides, see the [Configuration Guide](./configuration#llm-configuration) + +### Monitoring +- Enable Prometheus metrics with `METRICS_ENABLED=true`. The API exposes `/metrics` on port 8000, the deriver on port 9090 (internal to its container — not published to the host by default). +- Enable Sentry error tracking with `SENTRY_ENABLED=true` +- The development compose includes Prometheus (host port 9090) and Grafana (host port 3000) for scraping and dashboards. Uncomment those services to enable them. + +### Backups +- Set up regular PostgreSQL backups: + ```bash + # One-off backup + docker compose exec database pg_dump -U postgres postgres > backup-$(date +%Y%m%d).sql + + # Restore + cat backup.sql | docker compose exec -T database psql -U postgres postgres + ``` +- Back up your `.env` or `config.toml` configuration files diff --git a/docs/v3/contributing/troubleshooting.mdx b/docs/v3/contributing/troubleshooting.mdx new file mode 100644 index 00000000..f041e2db --- /dev/null +++ b/docs/v3/contributing/troubleshooting.mdx @@ -0,0 +1,299 @@ +--- +title: 'Troubleshooting' +sidebarTitle: 'Troubleshooting' +description: 'Common issues and solutions when self-hosting Honcho' +icon: 'wrench' +--- + +This page covers common issues you may encounter when self-hosting Honcho, what causes them, and how to fix them. + +## Startup Failures + +### Server won't start: "Missing client for ..." + +``` +ValueError: Missing client for Deriver: google +``` + +**Cause:** The server validates at startup that all configured LLM providers have API keys. If a provider is referenced in your configuration but the corresponding API key isn't set, the server refuses to start. + +**Fix:** Set the API keys for your configured providers. With default configuration, you need: + +```bash +LLM_GEMINI_API_KEY=... # Used by deriver, summary, dialectic minimal/low +LLM_ANTHROPIC_API_KEY=... # Used by dialectic medium/high/max, dream +LLM_OPENAI_API_KEY=... # Used by embeddings (when EMBED_MESSAGES=true) +``` + +See the [LLM Setup](/v3/contributing/self-hosting#llm-setup) section for provider configuration. You can change which providers are used in your `.env` or `config.toml` (see [Configuration Guide](./configuration#llm-configuration)). + +### Server won't start: "JWT_SECRET must be set" + +``` +ValueError: JWT_SECRET must be set if USE_AUTH is true +``` + +**Cause:** You enabled authentication (`AUTH_USE_AUTH=true`) but didn't provide a JWT secret. + +**Fix:** Generate a secret and set it: + +```bash +python scripts/generate_jwt_secret.py +# Then set the output as: +AUTH_JWT_SECRET= +``` + +Or disable authentication for local development: `AUTH_USE_AUTH=false` + +## Runtime Errors + +### API returns "An unexpected error occurred" on every request + +**Cause:** This is almost always a database issue. The health endpoint (`/health`) will return `{"status": "ok"}` even when the database is unreachable because it doesn't check the database connection. The actual error appears in the server logs. + +**Common causes and fixes:** + +1. **Database is unreachable** — Check that PostgreSQL is running and the `DB_CONNECTION_URI` is correct +2. **Migrations haven't been run** — The server starts successfully without tables, but every API call will fail. Run: + ```bash + uv run alembic upgrade head + ``` + In Docker: + ```bash + docker compose exec api uv run alembic upgrade head + ``` +3. **pgvector extension not installed** — The `vector` extension must be enabled in your database: + ```sql + CREATE EXTENSION IF NOT EXISTS vector; + ``` + +**How to diagnose:** Check the server logs for the actual error. Look for: +- `sqlalchemy.exc.OperationalError` — database connection issue +- `sqlalchemy.exc.ProgrammingError` with "relation does not exist" — migrations not run +- `psycopg.OperationalError` — connection refused or authentication failed + +### Health check passes but API calls fail + +The `/health` endpoint is a lightweight check that confirms the server process is running. It does **not** verify: +- Database connectivity +- That migrations have been run +- That LLM providers are reachable + +To verify full functionality, try creating a workspace: + +```bash +curl -X POST http://localhost:8000/v3/workspaces \ + -H "Content-Type: application/json" \ + -d '{"name": "test"}' +``` + +If this succeeds, your database connection and migrations are working. + +### Deriver not processing messages + +Messages are stored but no observations, summaries, or representations are being generated. + +**Common causes:** + +1. **Deriver isn't running** — In manual setup, the deriver is a separate process: + ```bash + uv run python -m src.deriver + ``` + In Docker, it starts automatically via `docker compose up`. + +2. **Deriver can't reach the database** — Check deriver logs for connection errors. The deriver uses the same `DB_CONNECTION_URI` as the API server. + +3. **Missing LLM API key for deriver provider** — By default the deriver uses Google Gemini (`LLM_GEMINI_API_KEY`). Check deriver logs for API errors. + +4. **Processing backlog** — With `DERIVER_WORKERS=1` (default), high message volume can cause a backlog. Increase workers: + ```bash + DERIVER_WORKERS=4 + ``` +5. **Representation Batch Max** — By default the deriver is set to buffer its operations until there are enough tokens for a given representation in a session. This is set via the `REPRESENTATION_BATCH_MAX_TOKENS` environment variable. If you aren't seeing tasks continue it may be that the batch size is set too high or enough data hasn't flowed into to the session yet. See [token batching](/v3/documentation/core-concepts/reasoning#token-batching) for more details + +## Alternative Provider Issues + +### OpenRouter / custom provider not working + +If you set `PROVIDER=custom` but calls fail: + +1. **Verify the endpoint and key are set:** + ```bash + LLM_OPENAI_COMPATIBLE_BASE_URL=https://openrouter.ai/api/v1 + LLM_OPENAI_COMPATIBLE_API_KEY=sk-or-v1-... + ``` + +2. **Check model names match the provider's format.** OpenRouter uses `vendor/model` format (e.g., `anthropic/claude-haiku-4-5`), not the raw model ID. + +3. **Ensure your model supports tool calling.** The deriver, dialectic, and dream agents require tool use. Check the provider's model page for tool calling support. + +4. **Check server logs for the actual error.** API errors from the upstream provider will appear in Honcho's logs with the HTTP status code and message body. + +### vLLM / Ollama not responding + +1. **Verify the model server is running** and accessible from the Honcho process (or container): + ```bash + curl http://localhost:8000/v1/models # vLLM + curl http://localhost:11434/v1/models # Ollama + ``` + +2. **In Docker**, `localhost` inside a container doesn't reach the host. Use `host.docker.internal` (macOS/Windows) or the host's network IP: + ```bash + LLM_VLLM_BASE_URL=http://host.docker.internal:8000/v1 + ``` + +3. **Structured output failures** — vLLM's structured output support is limited to certain response formats. If you see JSON parsing errors, check the deriver/dream logs for the raw response. + +### Thinking budget errors with non-Anthropic providers + +If you see errors like `thinking budget not supported`, `invalid parameter`, or silent failures where agents produce no output, your `THINKING_BUDGET_TOKENS` is likely set to a value > 0 with a provider that doesn't support Anthropic-style extended thinking. + +**Fix:** Set `THINKING_BUDGET_TOKENS=0` for every component when using non-Anthropic providers: + +```bash +DERIVER_THINKING_BUDGET_TOKENS=0 +SUMMARY_THINKING_BUDGET_TOKENS=0 +DREAM_THINKING_BUDGET_TOKENS=0 +DIALECTIC_LEVELS__minimal__THINKING_BUDGET_TOKENS=0 +DIALECTIC_LEVELS__low__THINKING_BUDGET_TOKENS=0 +DIALECTIC_LEVELS__medium__THINKING_BUDGET_TOKENS=0 +DIALECTIC_LEVELS__high__THINKING_BUDGET_TOKENS=0 +DIALECTIC_LEVELS__max__THINKING_BUDGET_TOKENS=0 +``` + +This applies to OpenRouter (with non-Anthropic models), vLLM, Ollama, Groq, Google, and OpenAI providers. Only Anthropic models support the thinking budget parameter. + +## Database Issues + +### Connection string format + +The connection URI **must** use the `postgresql+psycopg` prefix: + +```bash +# Correct +DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/postgres + +# Wrong - will fail +DB_CONNECTION_URI=postgresql://postgres:postgres@localhost:5432/postgres +DB_CONNECTION_URI=postgres://postgres:postgres@localhost:5432/postgres +``` + +### Checking migration status + +```bash +# See current migration version +uv run alembic current + +# See migration history +uv run alembic history + +# Upgrade to latest +uv run alembic upgrade head +``` + +## Cache & Redis + +### Redis is optional + +Redis is used for caching when `CACHE_ENABLED=true` (default: `false`). If Redis is unreachable, Honcho **gracefully falls back to in-memory caching** and logs a warning. This means: + +- The server and deriver will still start and function normally +- Performance may be reduced under high load without Redis +- You do not need Redis for local development or testing + +### Redis connection issues + +If you see Redis connection warnings in logs but `CACHE_ENABLED=false`, they can be safely ignored. If you want caching: + +```bash +# Start Redis via Docker +docker run -d -p 6379:6379 redis:latest + +# Configure Honcho +CACHE_ENABLED=true +CACHE_URL=redis://localhost:6379/0 +``` + +## Docker Issues + +### Docker build fails with permission errors + +The Honcho Dockerfile uses BuildKit mount syntax and creates a non-root `app` user. Common build failures: + +**1. BuildKit not enabled** + +The Dockerfile uses `RUN --mount=type=cache` which requires Docker BuildKit. If you see syntax errors during build: + +```bash +# Ensure BuildKit is enabled +DOCKER_BUILDKIT=1 docker compose build +``` + +Or add to your Docker daemon config (`/etc/docker/daemon.json`): +```json +{ "features": { "buildkit": true } } +``` + +**2. Permission denied during build or at runtime (Linux)** + +On Linux, AppArmor or SELinux can block Docker build operations and volume mounts. Symptoms include permission denied errors during `COPY`, `RUN`, or when the container tries to access mounted volumes. + +```bash +# Check if AppArmor is blocking Docker +sudo aa-status | grep docker + +# Temporarily test without AppArmor (for diagnosis only) +docker compose down +sudo aa-remove-unknown +docker compose up -d +``` + +For SELinux, add `:z` to volume mounts in `docker-compose.yml`: +```yaml +volumes: + - .:/app:z +``` + +**3. Volume mount UID mismatch** + +The Dockerfile creates a non-root `app` user, but `docker-compose.yml.example` mounts `.:/app` which overlays the container filesystem with host-owned files. The `app` user inside the container may not have permission to read them. + +If you see permission errors at runtime (not build time), you can either: +- Run without the source mount (remove `- .:/app` from volumes — the image already contains the code) +- Or fix ownership: `sudo chown -R 100:101 .` (matches the `app` user inside the container) + +### Containers start but API fails + +1. Check container status: `docker compose ps` +2. Check API logs: `docker compose logs api` +3. Check database logs: `docker compose logs database` +4. Ensure migrations ran: `docker compose exec api uv run alembic upgrade head` + +### Port conflicts + +If port 8000 is already in use: + +```bash +# Check what's using the port +lsof -i :8000 + +# Or change the port mapping in docker-compose.yml +ports: + - "8001:8000" # Map to a different host port +``` + +### Rebuilding after code changes + +```bash +docker compose build --no-cache +docker compose up -d +``` + +## Getting Help + +If your issue isn't covered here: + +- **Check the logs** — most issues are diagnosed from server or deriver logs +- **GitHub Issues** — [Report bugs](https://github.com/plastic-labs/honcho/issues) +- **Discord** — [Join our community](https://discord.gg/plasticlabs) +- **Configuration** — See the [Configuration Guide](./configuration) for all available settings diff --git a/docs/v3/guides/integrations/hermes.mdx b/docs/v3/guides/integrations/hermes.mdx index e19d2d64..9fe46973 100644 --- a/docs/v3/guides/integrations/hermes.mdx +++ b/docs/v3/guides/integrations/hermes.mdx @@ -41,130 +41,82 @@ Hermes exposes four Honcho tools to the agent: | `honcho_context` | Dialectic Q&A powered by Honcho's LLM. Synthesizes answers from conversation history. | | `honcho_conclude` | Writes durable facts to Honcho when the user states preferences, corrections, or important context. | -## Two memory layers - -When Honcho is enabled, Hermes operates with two layer memory by default (`hybrid`): - -**Local session history** -- the immediate transcript for the current chat, thread, or CLI session. Use it for recent turns, short-lived task context, and follow-up questions. - -**Honcho memory** -- the semantic, cross-session layer. Use it for user preferences, durable project facts, cross-session continuity, and synthesized peer context. - ## Running Honcho locally with Hermes -If you want to point Hermes at a local Honcho instance instead of the hosted API: - -### Docker (quickest) +Follow the [Self-Hosting Guide](/v3/contributing/self-hosting) to get Honcho running locally. Once it's up, point Hermes at your instance: ```bash -git clone https://github.com/plastic-labs/honcho.git -cd honcho -cp .env.template .env -cp docker-compose.yml.example docker-compose.yml +hermes memory setup # select "honcho", enter http://localhost:8000 as the base URL ``` -Edit `.env`: - -```bash -OPENAI_API_KEY=your-openai-api-key -ANTHROPIC_API_KEY=your-anthropic-api-key -DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/honcho -AUTH_USE_AUTH=false -``` - -```bash -docker compose up -d -curl http://localhost:8000/health -``` - -### Manual - -```bash -git clone https://github.com/plastic-labs/honcho.git -cd honcho -uv sync -cp .env.template .env -``` - -Edit `.env` with a local or cloud Postgres connection string and API keys, then: - -```bash -uv run alembic upgrade head -uv run fastapi dev src/main.py -``` - -Then update `~/.honcho/config.json` to point at your local instance: +Or manually create/edit the config file (checked in order: `$HERMES_HOME/honcho.json` > `~/.hermes/honcho.json` > `~/.honcho/config.json`): ```json { - "apiKey": "not-needed-with-auth-disabled", "baseUrl": "http://localhost:8000", "hosts": { "hermes": { - "workspace": "hermes", - "peerName": "your-name", + "enabled": true, "aiPeer": "hermes", - "memoryMode": "hybrid", - "enabled": true + "peerName": "your-name", + "workspace": "hermes" } } } ``` -The `baseUrl` field overrides the default hosted API. With `AUTH_USE_AUTH=false` on the server, the `apiKey` value is ignored but the field must still be present. +For the full list of config fields (`recallMode`, `writeFrequency`, `sessionStrategy`, `dialecticReasoningLevel`, etc.), see the [Hermes memory provider docs](https://hermes-agent.nousresearch.com/docs/user-guide/features/memory-providers#honcho). -See the full [self-hosting guide](/v3/contributing/self-hosting) for database options, cloud setup, and troubleshooting. + +**Community quick-start**: [elkimek/honcho-self-hosted](https://github.com/elkimek/honcho-self-hosted) provides a one-command installer with pre-configured model tiers and Hermes Agent integration. + ## Verifying the integration -Steps to test the integration via CLI and agentically by speaking to Hermes agent in natural language. - -### 1. Check configuration +### 1. Check status ```bash -hermes honcho status +hermes memory status ``` -### 2. Test cross-session recall +This should show Honcho as the active memory provider with your base URL. -In one conversation: +### 2. Store a fact and recall it across sessions + +In one conversation, tell Hermes something specific: ```text -Remember that my test phrase is velvet circuit. +My favorite programming language is Rust and I always use dark mode. ``` -In a fresh conversation (different thread, new CLI session): +Start a **new session** (different thread, new CLI invocation, or a different platform). Ask: ```text -What is my test phrase? +What do you know about my preferences? ``` -If Hermes recalls "velvet circuit" after short-term context is gone, Honcho is working. +If Hermes mentions Rust and dark mode without being told again, cross-session memory is working. The deriver processed your messages, extracted observations, and the dialectic recalled them. -### 3. Test writeback +### 3. Test tool calling directly -Tell Hermes a preference: +Ask Hermes to use a specific Honcho tool: ```text -Remember that I prefer terse answers. +Use your honcho_search tool to find anything you know about me. ``` -Wait briefly if writes are asynchronous. Open a fresh conversation: +If Hermes calls the tool and returns results, the full tool pipeline (API connection, vector search, embedding) is functional. -```text -How should you respond to me? -``` - -If Hermes answers with the stored preference, writeback is functioning. - - -## Session strategy - -| Scope | When to use | -|----------------------|---------------------------------------------------------| -| Per-Session | A honcho session starts fresh each time a new Hermes session is created. Hermes remembers the user across sessions. | -| Per Directory | One honcho session per project directory. Context is scoped to each directory. Coding/project memory scoped to each repository/workspace. | -| Global (per user) | Continuity across all chats, threads, and projects. One honcho session globally for the user and Hermes agent. | +## Configuration options +| Field | Default | Description | +|---|---|---| +| `recallMode` | `hybrid` | `hybrid` (auto-inject + tools), `context` (inject only), `tools` (tools only) | +| `writeFrequency` | `async` | `async`, `turn`, `session`, or integer N | +| `sessionStrategy` | `per-directory` | `per-directory`, `per-repo`, `per-session`, `global` | +| `dialecticReasoningLevel` | `low` | `minimal`, `low`, `medium`, `high`, `max` | +| `dialecticDynamic` | `true` | Auto-bump reasoning level by query complexity | +| `messageMaxChars` | `25000` | Max chars per message (chunked if exceeded) | ## Next steps @@ -182,6 +134,6 @@ If Hermes answers with the stored preference, writeback is functioning. - Full local environment setup, database options, and troubleshooting. + Full local environment setup, provider configuration, and troubleshooting. diff --git a/src/main.py b/src/main.py index 571bbb54..46dc5bc9 100644 --- a/src/main.py +++ b/src/main.py @@ -196,6 +196,12 @@ app.include_router(webhooks.router, prefix="/v3") app.add_route("/metrics", metrics_endpoint, methods=["GET"]) +@app.get("/health") +async def health_check(): + """Health check endpoint for monitoring and container orchestration.""" + return {"status": "ok"} + + # Global exception handlers @app.exception_handler(HonchoException) async def honcho_exception_handler(_request: Request, exc: HonchoException):