The kastel.config.yaml file tunes an entire deployment. Here it is exactly as the install writes it for you on day one, comments included.
A generated page
The file below is not an example written for the documentation: it is the real output of kastel init, published as it stands. Its comments are the ones you will read in your own file.
01
Where it lives, what it carries
The file sits at the root of your deployment, next to your governance rules and your content. It is versioned with everything else: it is a settings file, not a vault.
No key, no password, no secret goes into it. The blocks that need credentials name environment variables, and the values stay in your .env. The template says so on its very first line.
02
The file
Each block carries its own comment, written by the engine. Anything commented out with a hash is inactive: those are the shipped values, shown so you know what to uncomment.
kastel.config.yaml
# Kastel deployment config. Versioned; never put secrets here (use .env).
client:
name: "Your Company"
deployer: "set-deployer-id"
# Language of the Brain content and the onboarding interview: en | fr.
# Source documents can be in any language; the Brain is written in this one.
language: en
# Brain structure version (G-7). Set by `kastel init`; do not hand-edit. When a
# newer Kastel changes the Brain structure (folders, frontmatter, conventions),
# run `kastel upgrade` to migrate this deployment and bump this number.
brain_version: 3
server:
mode: self-hosted # self-hosted | managed
region: eu # any region in self-host; EU is the managed default
# ONE sovereignty flag (ADR-008). default = BYOK inference: your data never
# passes through Kastel (it goes straight to the provider you chose the key
# for; the search index is computed in-process either way). max =
# everything local (implies inference local; embeddings are in-process by
# default): nothing ever leaves your server. Setting max with a byok provider
# or a byok embedder is a config error.
sovereignty_profile: default # default | max
inference:
# The thin provider plug, used only by steps that need a model directly
# (ingest compile, onboarding synthesis). Kastel is not a runtime.
# byok = your own key, direct to the provider (sovereign default; key in .env)
# local = a local OpenAI-compatible server (maximum sovereignty)
default_provider: byok # byok | local
retrieval:
# Section-granular chunking of the Brain pages (kastel reindex).
chunk_max_tokens: 512
chunk_overlap_tokens: 32
embeddings:
# Shipped default: the packaged in-process model
# (multilingual-e5-small, int8 ONNX). No API key, no network call: the
# index is computed inside the engine, where your data lives.
# Deployer-level alternatives (both need `kastel reindex` to switch):
# provider: byok / model: mistral-embed / dim: 1024
# / base_url: https://api.mistral.ai/v1 (key in .env as
# KASTEL_EMBED_API_KEY; OpenAI: text-embedding-3-small / 1536 /
# https://api.openai.com/v1)
# provider: local / model: bge-m3 / dim: 1024 (Ollama-compatible
# endpoint on infrastructure YOU own; nomic-embed-text / 768 works too)
# Changing provider, model or dim = full `kastel reindex` (ADR-008:
# embedding spaces are never mixed or migrated).
provider: builtin # builtin | byok | local
model: multilingual-e5-small
dim: 384
budget:
monthly_eur_cap: 200
moderation:
require_human_validation_above_risk: medium
# Context score (docs/spec-context-score-addendum.md). The answer-fidelity leg
# asks your OWN provider (BYOK, the key already in .env) whether the retrieved
# context actually supports answering each probe question, and weighs the answer
# at 0.2 of the composite. It is the only leg that spends: `kastel score` costs a
# handful of judge calls, inside your monthly cap like everything else.
# SHIPPED ON since 2026-08-10 (D93-d, PF-D9): a score computed without it is a
# score of retrieval and structure, which is not what the number claims to mean.
# The ENGINE default stays off - an absent `score:` block disables the leg - so a
# deployment that predates this line, or one that deletes it, keeps the judge
# silent. Set false (the YAML boolean, never the string "false") to turn it off:
# a quoted value is refused at load time rather than parsed truthily.
score:
fidelity:
enabled: true
# The governed maintenance cycle (docs/spec-maintenance-cycle.md): periodic
# passes that keep the Brain healthy. Level 1 touches derived state only;
# level 2 only STAGES proposals in the moderation feed (a human approves);
# questions go through the freshness digest. The defaults below are the
# shipped values - uncomment to change a cadence, set enabled: false to
# disable the scheduler (kastel doctor --remediate keeps working).
# maintenance:
# enabled: true
# mechanical_cadence_hours: 24
# proposal_cadence_hours: 168
# compile_cadence_hours: 24
# pass_budget_seconds: 600
# max_proposals_per_cycle: 20
# stub_stale_days: 30
# orphan_link_candidates: 3
# duplicate_similarity_pct: 92
# Continuous connectors (optional; docs/spec-connector-web-oauth.md). Each
# block names the ENVIRONMENT VARIABLES holding the OAuth app credentials
# (names only - the values stay in .env, never in this file, ADR-009).
# Absent or empty = the connector is not configured; its connect routes
# answer 409 honestly. Uncomment and fill to enable Google Drive:
# connectors:
# gdrive:
# client_id_env: KASTEL_GDRIVE_CLIENT_ID
# client_secret_env: KASTEL_GDRIVE_CLIENT_SECRET
Generated from the engine's install template, refreshed on 2026-08-29 (engine c257fb6be277).
A question about installing?
Write to us: a question asked by email gets an answer the same day. Our network of partner integrators can also help.