Configuration
Configure the Respondent community edition — database, server, AI, and LLM providers
All Respondent configuration lives in a single file: respondent.yaml. This page covers every section.
Database
database.path
string
required
default: ./respondent.db/data/respondent.db via the RESPONDENT_DATABASE_PATH environment variable so the database is persisted in a Docker volume.database:
path: "./respondent.db"
Retention (size-cap)
The observations table is append-only and grows without bound. The retention routine is opt-in: it stays disabled until database.retention.max_size is set. When enabled, it measures the on-disk size on an interval and, if the database exceeds max_size, prunes the oldest observations in batches down to max_size * low_water_ratio, then returns the freed space to the OS. Live ingestion is never throttled — the cap is chased by pruning.
database.retention.max_size
string50GB, 500MB). Empty disables retention (the default — retention is opt-in).database.retention.low_water_ratio
float
default: 0.90max_size. Pruning continues until the database is at or below max_size * low_water_ratio. The gap between the two is the hysteresis band. Must be between 0 and 1 (exclusive) when retention is enabled.database.retention.check_interval
string
default: 10mdatabase.retention.batch_size
integer
default: 5000database.retention.max_batches_per_tick
integer
default: 200database.retention.incremental_vacuum_pages
integer
default: 10000PRAGMA incremental_vacuum (~40MB at 4KB pages), bounding the reclaim lock window.database:
path: "./respondent.db"
retention:
max_size: "" # e.g. "50GB" / "500MB"; empty disables retention
low_water_ratio: 0.90
check_interval: "10m"
batch_size: 5000
max_batches_per_tick: 200
incremental_vacuum_pages: 10000
Server
server.port
integer
default: 8090server:
port: 8090
Ingest
ingest.sources_dir
string
required
default: ./sources.d.yaml file in this directory at startup.ingest.dev_mode
boolean
default: falsedry_run: true will fetch and parse data but skip database persistence. Useful for testing new source definitions without writing to the database.ingest:
sources_dir: "./sources.d"
# dev_mode: false
AI
Controls AI-powered enrichment and analysis features. Requires a configured LLM provider.
ai.enabled
boolean
default: falsetrue and configure the llm section to enable AI enrichment on sources that define ai.operations.ai.analysis_dir
string
default: ./analysis.dai.min_attention
string
default: lowinfo, low, medium, high, critical. low drops routine info-level observations platform-wide. A per-analysis output.min_attention overrides this value.ai.workers.enrichment
integer
default: 2ai.workers.analysis
integer
default: 1ai:
enabled: true
analysis_dir: "./analysis.d"
min_attention: "low"
workers:
enrichment: 2
analysis: 1
LLM
Configure the LLM provider used for AI enrichment. Set llm.provider to the provider name, then add the provider-specific block.
llm.provider
string
required
default: zaizai, openai, anthropic, gemini, xai, ollama, lmstudio. The shipped respondent.yaml defaults to zai (GLM).llm:
provider: "zai"
zai:
base_url: "https://api.z.ai/api/coding/paas/v4"
model: "glm-5.2"
max_tokens: 8192
timeout: "120s" # GLM latency headroom on large prompts
enable_thinking: false # structured JSON output: skip reasoning (faster, no truncation)
# api_key: set via RESPONDENT_LLM_ZAI_API_KEY env var
llm:
provider: "openai"
openai:
model: "gpt-4o"
max_tokens: 2048
# api_key: set via RESPONDENT_LLM_OPENAI_API_KEY env var
llm:
provider: "anthropic"
anthropic:
model: "claude-sonnet-4-20250514"
max_tokens: 2048
# api_key: set via RESPONDENT_LLM_ANTHROPIC_API_KEY env var
llm:
provider: "xai"
xai:
model: "grok-3"
max_tokens: 2048
# api_key: set via RESPONDENT_LLM_XAI_API_KEY env var
llm:
provider: "ollama"
ollama:
model: "llama3"
max_tokens: 2048
base_url: "http://host.docker.internal:11434"
llm:
provider: "lmstudio"
lmstudio:
base_url: "http://localhost:1234/v1"
# model is optional — LM Studio serves the currently loaded model when blank.
model: "qwen/qwen3.6-35b-a3b"
max_tokens: 4096
gemini is also a valid provider; configure a llm.gemini block with api_key, model, and optional base_url.
.env file. See Environment variable overrides below.Geocoder
Configures the geocoding service used by AI enrichment to resolve location names to coordinates.
geocoder.provider
string
default: nominatimnominatim (OpenStreetMap’s free geocoding service).geocoder.nominatim.base_url
string
default: https://nominatim.openstreetmap.orggeocoder.nominatim.user_agent
string
default: respondent/1.0 (geospatial-intelligence)geocoder.rate_limit.requests_per_second
float
default: 1.0geocoder.rate_limit.burst
integer
default: 5geocoder.cache.enabled
boolean
default: truegeocoder.cache.ttl
string
default: 168hgeocoder:
provider: "nominatim"
nominatim:
base_url: "https://nominatim.openstreetmap.org"
user_agent: "respondent/1.0 (geospatial-intelligence)"
rate_limit:
requests_per_second: 1.0
burst: 5
cache:
enabled: true
ttl: "168h"
Frontend
Client-safe values the server hands to the embedded SPA at runtime via GET /config.json, so per-deployment frontend config reaches the already-compiled bundle without a rebuild. Empty values are omitted from the payload so the frontend’s fallback chain (runtime config → build-time env → default) stays intact.
frontend.cesium_ion_token
stringfrontend:
cesium_ion_token: "" # set via RESPONDENT_FRONTEND_CESIUM_ION_TOKEN
frontend block is served to the browser via GET /config.json. Never put server secrets here — only client-safe values like the Cesium ion client token.Logging
logging.level
string
default: infodebug, info, warn, error.logging:
level: "info"
Environment variable overrides
Any respondent.yaml field can be overridden with an environment variable using the RESPONDENT_ prefix. Convert the YAML path to uppercase, replacing dots and nested keys with underscores.
| YAML path | Environment variable |
|---|---|
database.path | RESPONDENT_DATABASE_PATH |
database.retention.max_size | RESPONDENT_DATABASE_RETENTION_MAX_SIZE |
server.port | RESPONDENT_SERVER_PORT |
ingest.enabled | RESPONDENT_INGEST_ENABLED |
ai.enabled | RESPONDENT_AI_ENABLED |
ai.min_attention | RESPONDENT_AI_MIN_ATTENTION |
frontend.cesium_ion_token | RESPONDENT_FRONTEND_CESIUM_ION_TOKEN |
llm.openai.api_key | RESPONDENT_LLM_OPENAI_API_KEY |
llm.anthropic.api_key | RESPONDENT_LLM_ANTHROPIC_API_KEY |
llm.zai.api_key | RESPONDENT_LLM_ZAI_API_KEY |
logging.level | RESPONDENT_LOGGING_LEVEL |
The other database.retention.* sub-keys follow the same pattern (e.g. RESPONDENT_DATABASE_RETENTION_LOW_WATER_RATIO, RESPONDENT_DATABASE_RETENTION_CHECK_INTERVAL). Setting ingest.enabled to false (e.g. RESPONDENT_INGEST_ENABLED=false) serves a fully static instance with no source fetching.
Set these in a .env file in the same directory as compose.yaml:
RESPONDENT_LLM_OPENAI_API_KEY=sk-your-key-here
RESPONDENT_AI_ENABLED=true
compose.yaml from the installation guide already includes env_file with required: false, so the .env file is loaded automatically when it exists.Source-level credential expansion
Inside source YAML files (in sources.d/), you can reference environment variables with the ${VAR} syntax. At load time, ${VAR} is expanded by looking up RESPONDENT_VAR in the environment.
For example, if a source needs an API key:
# sources.d/my_source.yaml
transport:
type: http_poll
url: "https://api.example.com/data?key=${MY_API_KEY}"
Set the corresponding environment variable:
# .env
RESPONDENT_MY_API_KEY=your-api-key-here
You can also use the auth block for structured credential injection:
transport:
auth:
type: api_key
header: "X-API-Key"
env_var: "MY_API_KEY" # Resolved from RESPONDENT_MY_API_KEY
Complete example
A full respondent.yaml with AI enabled using OpenAI:
database:
path: "./respondent.db"
server:
port: 8090
ingest:
sources_dir: "./sources.d"
ai:
enabled: true
analysis_dir: "./analysis.d"
workers:
enrichment: 2
analysis: 1
llm:
provider: "openai"
openai:
model: "gpt-4o"
max_tokens: 2048
# api_key: set via RESPONDENT_LLM_OPENAI_API_KEY env var
geocoder:
provider: "nominatim"
nominatim:
base_url: "https://nominatim.openstreetmap.org"
user_agent: "respondent/1.0 (geospatial-intelligence)"
rate_limit:
requests_per_second: 1.0
burst: 5
cache:
enabled: true
ttl: "168h"
logging:
level: "info"