fix: align self-hosting config and docs

This commit is contained in:
adavyas 2026-03-17 12:30:25 -07:00
parent 7928c39bf4
commit fd239611a3
9 changed files with 339 additions and 64 deletions

View File

@ -32,7 +32,9 @@ LOG_LEVEL=INFO
# =============================================================================
# Connection URI for PostgreSQL database with pgvector support
# Must use postgresql+psycopg prefix for SQLAlchemy compatibility
DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/postgres
# Keep localhost for host-based runs; docker-compose.yml.example overrides the
# hostname to the "database" service inside containers.
DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@localhost:5432/honcho
# Optional database settings
# DB_SCHEMA=public
@ -57,16 +59,19 @@ AUTH_USE_AUTH=false
# AUTH_JWT_SECRET=your-secret-key-here
# =============================================================================
# LLM API Keys (REQUIRED for full functionality)
# LLM API Keys
# =============================================================================
# The shipped defaults need Anthropic and Gemini for startup. OpenAI is also
# needed if you keep the default embedding behavior
# (EMBED_MESSAGES=true and LLM_EMBEDDING_PROVIDER=openai).
# OpenAI API key for embeddings
LLM_OPENAI_API_KEY=your-openai-api-key-here
# Anthropic API key for dialectic and deriver functionality
# Anthropic API key for dialectic 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
# Google API key for summary/deriver and Gemini-backed reasoning
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

View File

@ -216,20 +216,30 @@ Honcho uses a `.env` file for managing runtime environment variables. A
are not required and are only necessary for additional logging, monitoring, and
security.
Below are the required configurations:
Below are the required configurations for the shipped defaults:
```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 Provider API Keys
LLM_ANTHROPIC_API_KEY= # Required to boot with default dialectic settings
LLM_GEMINI_API_KEY= # Required to boot with default summary/deriver and dialectic minimal/low settings
LLM_OPENAI_API_KEY= # Required if you keep the default embedding behavior (EMBED_MESSAGES=true and LLM_EMBEDDING_PROVIDER=openai)
LLM_GROQ_API_KEY= # API Key for Groq (used for query generation by default)
```
> Note that the `DB_CONNECTION_URI` must have the prefix `postgresql+psycopg` to
> function properly. This is a requirement brought by `sqlalchemy`
>
> If you change the default providers in `config.toml` or via environment
> variables, the required LLM keys change with them.
>
> Current limitation: embeddings have their own provider selector
> (`LLM_EMBEDDING_PROVIDER`), but other LLM features use per-feature
> `PROVIDER`/`MODEL` fields backed by a shared global client pool. In
> particular, `custom` and `vllm` are global OpenAI-compatible connection slots,
> so you cannot point two different features at two different custom endpoints at
> the same time.
The template has the additional functionality disabled by default. To ensure
that they are disabled you can verify the following environment variables are
@ -266,6 +276,10 @@ uv run alembic upgrade head
This will create all tables for Honcho including workspaces, peers, sessions,
messages, and the queue system.
> `uv run alembic ...` reads `DB_CONNECTION_URI` (or `[db].CONNECTION_URI` in
> `config.toml`) through Honcho's settings loader. The placeholder URL in
> `alembic.ini` is not the effective source of truth.
6. **Launch Honcho**
With everything set up, you can now launch a local instance of Honcho. In addition to the database, two
@ -347,8 +361,10 @@ As mentioned earlier a `docker-compose` template is included for running Honcho.
As an alternative to running Honcho locally it can also be run with the compose
template.
The docker-compose template is set to use an environment file called `.env`.
You can also copy the `.env.template` and fill with the appropriate values.
The self-hosting setup treats `.env.template` as the canonical source of truth
for local/manual defaults. `config.toml.example` mirrors the same settings in
TOML form. The compose example keeps those defaults and only overrides
container-local details such as service hostnames.
Copy the template and update the appropriate environment variables before
launching the service:
@ -356,11 +372,19 @@ launching the service:
```bash
cd honcho
cp .env.template .env
# update the file with openai key and other wanted environment variables
# keep DB_CONNECTION_URI pointed at localhost; docker-compose overrides the host
# to the internal "database" service automatically
# update the file with LLM keys and any other wanted environment variables
cp docker-compose.yml.example docker-compose.yml
docker compose up
```
Once the stack is up, you can verify the API with:
```bash
curl http://localhost:8000/openapi.json
```
### Deploy on Fly
The API can also be deployed on fly.io. Follow the [Fly.io
@ -390,6 +414,9 @@ Honcho uses a flexible configuration system that supports both TOML files and en
3. `config.toml` file
4. Default values
`.env.template` is the canonical setup template. `config.toml.example` is the
equivalent TOML transcription of that template, not a separate set of defaults.
### Using config.toml
Copy the example configuration file to get started:
@ -398,7 +425,9 @@ Copy the example configuration file to get started:
cp config.toml.example config.toml
```
Then modify the values as needed. The TOML file is organized into sections:
Then modify the values as needed. Use `.env.template` as the source of truth
for placeholder values and required-vs-optional settings; `config.toml.example`
mirrors those same values in TOML form. The TOML file is organized into sections:
- `[app]` - Application-level settings (log level, session limits, embedding settings, namespace)
- `[db]` - Database connection and pool settings
@ -434,6 +463,14 @@ Examples:
- `METRICS_ENABLED` - Enable Prometheus metrics
- `TELEMETRY_ENABLED` - Enable CloudEvents telemetry
Canonical mappings used throughout the self-hosting docs:
- `DB_CONNECTION_URI``[db].CONNECTION_URI`
- `CACHE_ENABLED``[cache].ENABLED`
- `CACHE_URL``[cache].URL`
- `METRICS_ENABLED``[metrics].ENABLED`
- `LLM_*` env vars ↔ `[llm]` keys
### Configuration Priority
When a configuration value is set in multiple places, Honcho uses this priority:
@ -455,14 +492,14 @@ If you have this in `config.toml`:
```toml
[db]
CONNECTION_URI = "postgresql://localhost/honcho_dev"
CONNECTION_URI = "postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"
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.

View File

@ -22,7 +22,9 @@ NAMESPACE = "honcho"
# Database settings
[db]
CONNECTION_URI = "postgresql+psycopg://postgres:postgres@localhost:5432/postgres"
# Keep localhost for host-based runs; docker-compose.yml.example overrides the
# hostname to the "database" service inside containers.
CONNECTION_URI = "postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"
SCHEMA = "public"
POOL_CLASS = "default"
POOL_PRE_PING = true
@ -37,13 +39,13 @@ TRACING = false
# Authentication settings
[auth]
USE_AUTH = false
JWT_SECRET = "your-secret-key-here" # Must be set if USE_AUTH is true
# JWT_SECRET = "your-secret-key-here" # Must be set if USE_AUTH is true
# Sentry settings
[sentry]
ENABLED = false
DSN = ""
RELEASE = ""
# DSN = "your-sentry-dsn-here"
# RELEASE = "your-release-semver"
ENVIRONMENT = "development"
TRACES_SAMPLE_RATE = 0.1
PROFILES_SAMPLE_RATE = 0.1
@ -56,6 +58,11 @@ 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
# Required to boot with the shipped defaults:
# - ANTHROPIC_API_KEY for anthropic-backed dialectic levels
# - GEMINI_API_KEY for summary/deriver and Gemini-backed reasoning levels
# OPENAI_API_KEY is additionally required if you keep the default embedding
# behavior (EMBED_MESSAGES=true and EMBEDDING_PROVIDER="openai").
# ANTHROPIC_API_KEY = "your-api-key"
# OPENAI_API_KEY = "your-api-key"
# OPENAI_COMPATIBLE_API_KEY = "your-api-key"
@ -67,6 +74,11 @@ MAX_MESSAGE_CONTENT_CHARS = 2000 # Max chars per message in tool results
# VLLM_API_KEY = "your-api-key"
# VLLM_BASE_URL = "your-base-url"
# Current limitation: non-embedding LLM features choose PROVIDER/MODEL in their
# own sections, but "custom" and "vllm" connection settings come from these
# shared [llm] keys. You cannot configure two different custom OpenAI-compatible
# endpoints for two different features at the same time.
# Deriver settings
[deriver]
ENABLED = true
@ -121,6 +133,7 @@ MODEL = "claude-haiku-4-5"
THINKING_BUDGET_TOKENS = 1024
MAX_TOOL_ITERATIONS = 2
# MAX_OUTPUT_TOKENS = 8192 # Optional: override global default
# TOOL_CHOICE = "any" # Optional: null/auto, "any", or "required"
[dialectic.levels.high]
PROVIDER = "anthropic"
@ -185,7 +198,7 @@ INCLUDE_LEVELS = ["explicit", "deductive"]
# Webhook settings
[webhook]
SECRET = ""
# SECRET = "your-webhook-signing-secret"
MAX_WORKSPACE_LIMIT = 10
# Prometheus metrics settings (pull-based metrics)
@ -219,7 +232,7 @@ DEFAULT_LOCK_TTL_SECONDS = 5
TYPE = "pgvector"
# Migration flag: set to true when migration from pgvector is complete
MIGRATED = false
NAMESPACE = "honcho"
# NAMESPACE = "honcho" # Inherits from app.NAMESPACE if not set
DIMENSIONS = 1536
# TURBOPUFFER_API_KEY = "your-turbopuffer-api-key"
# TURBOPUFFER_REGION = "us-east-1"

View File

@ -15,9 +15,15 @@ services:
volumes:
- .:/app
- venv:/app/.venv
# .env.template remains the canonical host/manual configuration.
# Compose overrides service-local addresses and enables stack-local features.
environment:
- DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres
- DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@database:5432/honcho
- CACHE_ENABLED=true
- CACHE_URL=redis://redis:6379/0?suppress=true
- METRICS_ENABLED=true
# Provide required LLM_* keys through .env or the shell environment when
# using the default provider configuration.
env_file:
- path: .env
required: false
@ -35,9 +41,12 @@ services:
- .:/app
- venv:/app/.venv
environment:
- DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/postgres
- DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@database:5432/honcho
- CACHE_ENABLED=true
- CACHE_URL=redis://redis:6379/0?suppress=true
- METRICS_ENABLED=true
# Provide required LLM_* keys through .env or the shell environment when
# using the default provider configuration.
env_file:
- path: .env
required: false
@ -48,16 +57,16 @@ services:
- 5432:5432
command: ["postgres", "-c", "max_connections=800"]
environment:
- POSTGRES_DB=postgres
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=postgres
- POSTGRES_DB=honcho
- POSTGRES_USER=testuser
- POSTGRES_PASSWORD=testpwd
- POSTGRES_HOST_AUTH_METHOD=trust
- PGDATA=/var/lib/postgresql/data/pgdata
volumes:
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
- pgdata:/var/lib/postgresql/data/
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres -d postgres"]
test: ["CMD-SHELL", "pg_isready -U testuser -d honcho"]
interval: 5s
timeout: 5s
retries: 5

View File

@ -11,6 +11,14 @@ Honcho uses a flexible configuration system that supports both TOML files and en
3. `config.toml` file (base configuration)
4. Default values
`.env.template` is the canonical source of truth for local/self-hosted defaults.
`config.toml.example` mirrors the same values in TOML form.
The shipped defaults currently require `LLM_ANTHROPIC_API_KEY` and
`LLM_GEMINI_API_KEY` to boot. `LLM_OPENAI_API_KEY` is also required if you keep
the default embedding behavior (`EMBED_MESSAGES=true` and
`LLM_EMBEDDING_PROVIDER=openai`). If you change provider settings, those key
requirements change with them.
## Recommended Configuration Approaches
### Option 1: Environment Variables Only (Production)
@ -44,7 +52,9 @@ Copy the example configuration file to get started:
cp config.toml.example config.toml
```
Then modify the values as needed. The TOML file is organized into sections:
Then modify the values as needed. Use `.env.template` for the canonical default
values and placeholders; `config.toml.example` mirrors those same settings in
TOML form. The TOML file is organized into sections:
- `[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)
@ -80,6 +90,14 @@ Examples:
- `DIALECTIC_LEVELS__minimal__PROVIDER` → `[dialectic.levels.minimal].PROVIDER`
- `DREAM_SURPRISAL__ENABLED` → `[dream.surprisal].ENABLED`
Canonical mappings used throughout the self-hosting docs:
- `DB_CONNECTION_URI` ↔ `[db].CONNECTION_URI`
- `CACHE_ENABLED` ↔ `[cache].ENABLED`
- `CACHE_URL` ↔ `[cache].URL`
- `METRICS_ENABLED` ↔ `[metrics].ENABLED`
- `LLM_*` env vars ↔ `[llm]` keys
### Configuration Priority
When a configuration value is set in multiple places, Honcho uses this priority:
@ -101,14 +119,14 @@ If you have this in `config.toml`:
```toml
[db]
CONNECTION_URI = "postgresql://localhost/honcho_dev"
CONNECTION_URI = "postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"
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.
@ -161,7 +179,7 @@ REASONING_TRACES_FILE=traces.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://testuser:testpwd@localhost:5432/honcho
# Example for production
DB_CONNECTION_URI=postgresql+psycopg://honcho_user:secure_password@db.example.com:5432/honcho_prod
@ -190,19 +208,23 @@ services:
database:
image: pgvector/pgvector:pg15
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_USER: testuser
POSTGRES_PASSWORD: testpwd
POSTGRES_DB: honcho
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
- ./database/init.sql:/docker-entrypoint-initdb.d/init.sql
volumes:
postgres_data:
```
When you use `docker-compose.yml.example`, keep `.env`/`config.toml` on the
host-style `localhost` URI. Compose overrides only the hostname to `database`
inside containers and enables stack-local caching/metrics there.
### Authentication Configuration
**JWT Authentication:**
@ -290,6 +312,41 @@ LLM_MAX_TOOL_OUTPUT_CHARS=10000 # ~2500 tokens at 4 chars/token
LLM_MAX_MESSAGE_CONTENT_CHARS=2000 # Max chars per message in tool results
```
### Current Provider Resolution Model
Honcho currently has two different configuration paths for LLM usage:
- Embeddings are configured through `[llm]` with `LLM_EMBEDDING_PROVIDER`.
- Other LLM-backed features such as `summary`, `deriver`, `dream`, and
`dialectic` choose `PROVIDER` and `MODEL` in their own sections.
This means the current behavior is:
- `LLM_EMBEDDING_PROVIDER=openai` uses `LLM_OPENAI_API_KEY`
- `LLM_EMBEDDING_PROVIDER=gemini` uses `LLM_GEMINI_API_KEY`
- `LLM_EMBEDDING_PROVIDER=openrouter` uses
`LLM_OPENAI_COMPATIBLE_API_KEY` and `LLM_OPENAI_COMPATIBLE_BASE_URL`
(defaulting to OpenRouter's API URL if the base URL is omitted)
- `SUMMARY.PROVIDER`, `DERIVER.PROVIDER`, `DREAM.PROVIDER`, and each
`DIALECTIC.LEVELS.*.PROVIDER` select from the shared provider pool built from
`[llm]`
There is an important current limitation:
- `custom` and `vllm` in feature-specific `PROVIDER` fields are not separate
per-feature providers. They are global OpenAI-compatible client slots backed
by one shared `[llm]` configuration each.
- As a result, you cannot configure two different custom OpenAI-compatible
endpoints for two different features at the same time.
- Similarly, if embeddings use `openrouter`, they consume the same
`LLM_OPENAI_COMPATIBLE_*` settings that a feature using `PROVIDER="custom"`
would use.
`SupportedProviders` therefore represents a mix of provider identities
(`anthropic`, `google`, `openai`, `groq`) and transport/client styles
(`custom`, `vllm`). That is the current implementation contract, even though it
is more constrained than a fully per-feature provider configuration model.
### Feature-Specific Model Configuration
Different features can use different providers and models:
@ -615,7 +672,7 @@ EMBED_MESSAGES = false
NAMESPACE = "honcho-dev"
[db]
CONNECTION_URI = "postgresql+psycopg://postgres:postgres@localhost:5432/honcho_dev"
CONNECTION_URI = "postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"
POOL_SIZE = 5
[auth]
@ -698,7 +755,7 @@ ENABLED = false
```bash
# .env.development
LOG_LEVEL=DEBUG
DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho_dev
DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@localhost:5432/honcho
AUTH_USE_AUTH=false
CACHE_ENABLED=false
@ -851,6 +908,10 @@ uv run alembic downgrade revision_id
uv run alembic revision --autogenerate -m "Description of changes"
```
Alembic uses Honcho's application settings for the database URL. Set
`DB_CONNECTION_URI` or `[db].CONNECTION_URI`; do not rely on the placeholder
value in `alembic.ini`.
## Troubleshooting
**Common Configuration Issues:**

View File

@ -51,15 +51,24 @@ Copy the example environment file and configure it:
cp .env.template .env
```
Edit `.env` and set your API keys (if using LLM features):
`.env.template` is the canonical self-hosting template. If you prefer TOML, you
can also copy `config.toml.example` to `config.toml`; it mirrors the same
settings in TOML form.
Edit `.env` and set the API keys required by the shipped defaults:
```bash
# Optional API keys (required for LLM features)
OPENAI_API_KEY=your-openai-api-key
ANTHROPIC_API_KEY=your-anthropic-api-key
# Required to boot with the shipped defaults
LLM_ANTHROPIC_API_KEY=your-anthropic-api-key
LLM_GEMINI_API_KEY=your-google-api-key
# Database will be created automatically by Docker
DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@database:5432/honcho
# Also required if you keep default embeddings enabled
LLM_OPENAI_API_KEY=your-openai-api-key
# Keep localhost here for host/manual runs.
# docker-compose.yml.example overrides the hostname to the internal "database"
# service automatically, so you do not need to edit this value for Docker.
DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@localhost:5432/honcho
# Disable auth for local development
AUTH_USE_AUTH=false
@ -86,10 +95,19 @@ docker compose ps
Test the Honcho API:
```bash
curl http://localhost:8000/health
curl http://localhost:8000/openapi.json
```
You should see a response indicating the service is healthy.
You should see the OpenAPI document for the running server.
If you change the default providers in `config.toml` or via environment
variables, the required LLM keys change with them.
Current limitation: embeddings use `LLM_EMBEDDING_PROVIDER`, but other LLM
features use per-feature `PROVIDER`/`MODEL` values backed by shared global
client settings in `[llm]`. That means `custom` and `vllm` each represent one
global OpenAI-compatible endpoint at a time, not a separate endpoint per
feature.
## Manual Setup
@ -135,23 +153,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 \
-e POSTGRES_USER=testuser \
-e POSTGRES_PASSWORD=testpwd \
-p 5432:5432 \
-d pgvector/pgvector:pg15
```
### 3. Create Database and Enable Extensions
Connect to PostgreSQL and set up the database:
If you used the Docker command above, the `honcho` database and `testuser`
role are created automatically. For a local PostgreSQL installation, create a
matching role/database first or update `.env.template` and `config.toml`
consistently. Then connect and enable extensions:
```bash
# Connect to PostgreSQL
psql -U postgres
# Create database and enable extensions
CREATE DATABASE honcho;
\c honcho
PGPASSWORD=testpwd psql -h localhost -p 5432 -U testuser -d honcho
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
\q
@ -165,15 +181,21 @@ Create a `.env` file with your settings:
cp .env.template .env
```
You can alternatively copy `config.toml.example` to `config.toml`; it mirrors
the same settings as `.env.template`.
Edit `.env` with your configuration:
```bash
# Database connection
DB_CONNECTION_URI=postgresql+psycopg://postgres:postgres@localhost:5432/honcho
DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@localhost:5432/honcho
# Optional API keys (required for LLM features)
OPENAI_API_KEY=your-openai-api-key
ANTHROPIC_API_KEY=your-anthropic-api-key
# Required to boot with the shipped defaults
LLM_ANTHROPIC_API_KEY=your-anthropic-api-key
LLM_GEMINI_API_KEY=your-google-api-key
# Also required if you keep default embeddings enabled
LLM_OPENAI_API_KEY=your-openai-api-key
# Development settings
AUTH_USE_AUTH=false
@ -187,6 +209,10 @@ LOG_LEVEL=DEBUG
uv run alembic upgrade head
```
> Honcho's Alembic environment reads `DB_CONNECTION_URI` or
> `[db].CONNECTION_URI` from the application config. `alembic.ini` is not the
> effective source of truth for the database URL.
### 6. Start the Server
```bash
@ -209,7 +235,8 @@ If you prefer to use a managed PostgreSQL service:
CREATE EXTENSION IF NOT EXISTS pg_trgm;
```
3. **Get your connection string** from Settings > Database
4. **Update your `.env` file** with the connection string
4. **Update your `.env` file** with the connection string or set the equivalent
`[db].CONNECTION_URI` value in `config.toml`
### Railway
@ -226,7 +253,7 @@ Once your Honcho server is running, verify everything is working:
### 1. Health Check
```bash
curl http://localhost:8000/health
curl http://localhost:8000/openapi.json
```
### 2. API Documentation

View File

@ -16,9 +16,9 @@ from pydantic_settings import (
from src.utils.types import SupportedProviders
# Load .env file for local development.
# Make sure this is called before AppSettings is instantiated if you rely on .env for AppSettings construction.
load_dotenv(override=True)
# Load .env file for local development without overriding explicit environment
# variables from the process (for example Docker Compose container overrides).
load_dotenv(override=False)
logger = logging.getLogger(__name__)
@ -156,7 +156,7 @@ class DBSettings(HonchoSettings):
model_config = SettingsConfigDict(env_prefix="DB_", extra="ignore") # pyright: ignore
CONNECTION_URI: str = (
"postgresql+psycopg://postgres:postgres@localhost:5432/postgres"
"postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"
)
SCHEMA: str = "public"
POOL_CLASS: str = "default"

View File

@ -0,0 +1,7 @@
import pytest
@pytest.fixture(autouse=True)
def mock_tracked_db():
"""Disable the DB-heavy tracked_db autouse fixture for setup example tests."""
yield

View File

@ -0,0 +1,116 @@
import json
import os
import subprocess
import sys
from pathlib import Path
REPO_ROOT = Path(__file__).resolve().parents[2]
def _load_db_connection_uri(tmp_path: Path, env_overrides: dict[str, str]) -> str:
env = os.environ.copy()
env["PYTHONPATH"] = str(REPO_ROOT)
env.pop("DB_CONNECTION_URI", None)
env.update(env_overrides)
result = subprocess.run(
[
sys.executable,
"-c",
(
"from src.config import settings; "
"import json; "
"print(json.dumps({'db_uri': settings.DB.CONNECTION_URI}))"
),
],
cwd=tmp_path,
env=env,
capture_output=True,
text=True,
check=True,
)
return json.loads(result.stdout)["db_uri"]
def test_env_var_overrides_dotenv_and_toml(tmp_path: Path) -> None:
(tmp_path / ".env").write_text(
"DB_CONNECTION_URI=postgresql+psycopg://dotenv:dotenv@localhost:5432/dotenv\n"
)
(tmp_path / "config.toml").write_text(
'[db]\nCONNECTION_URI = "postgresql+psycopg://toml:toml@localhost:5432/toml"\n'
)
db_uri = _load_db_connection_uri(
tmp_path,
{
"DB_CONNECTION_URI": "postgresql+psycopg://env:env@localhost:5432/env",
},
)
assert db_uri == "postgresql+psycopg://env:env@localhost:5432/env"
def test_dotenv_overrides_toml(tmp_path: Path) -> None:
(tmp_path / ".env").write_text(
"DB_CONNECTION_URI=postgresql+psycopg://dotenv:dotenv@localhost:5432/dotenv\n"
)
(tmp_path / "config.toml").write_text(
'[db]\nCONNECTION_URI = "postgresql+psycopg://toml:toml@localhost:5432/toml"\n'
)
db_uri = _load_db_connection_uri(tmp_path, {})
assert db_uri == "postgresql+psycopg://dotenv:dotenv@localhost:5432/dotenv"
def test_toml_overrides_builtin_defaults(tmp_path: Path) -> None:
(tmp_path / "config.toml").write_text(
'[db]\nCONNECTION_URI = "postgresql+psycopg://toml:toml@localhost:5432/toml"\n'
)
db_uri = _load_db_connection_uri(tmp_path, {})
assert db_uri == "postgresql+psycopg://toml:toml@localhost:5432/toml"
def test_examples_share_the_canonical_local_database_contract() -> None:
env_template = (REPO_ROOT / ".env.template").read_text()
config_example = (REPO_ROOT / "config.toml.example").read_text()
assert (
"DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"
in env_template
)
assert (
'CONNECTION_URI = "postgresql+psycopg://testuser:testpwd@localhost:5432/honcho"'
in config_example
)
def test_compose_example_matches_the_canonical_contract() -> None:
compose_example = (REPO_ROOT / "docker-compose.yml.example").read_text()
assert (
"DB_CONNECTION_URI=postgresql+psycopg://testuser:testpwd@database:5432/honcho"
in compose_example
)
assert "CACHE_ENABLED=true" in compose_example
assert compose_example.count("METRICS_ENABLED=true") == 2
assert (
"./database/init.sql:/docker-entrypoint-initdb.d/init.sql" in compose_example
)
assert (REPO_ROOT / "database" / "init.sql").exists()
def test_examples_surface_default_llm_requirements() -> None:
env_template = (REPO_ROOT / ".env.template").read_text()
config_example = (REPO_ROOT / "config.toml.example").read_text()
compose_example = (REPO_ROOT / "docker-compose.yml.example").read_text()
assert "LLM_OPENAI_API_KEY=your-openai-api-key-here" in env_template
assert "LLM_ANTHROPIC_API_KEY=your-anthropic-api-key-here" in env_template
assert "LLM_GEMINI_API_KEY=your-google-api-key-here" in env_template
assert "Required to boot with the shipped defaults:" in config_example
assert "two different custom OpenAI-compatible" in config_example
assert "Provide required LLM_* keys" in compose_example