Skip to content
GitHub

YAML Configuration

Lexigram merges user-defined YAML files, environment variables, and code defaults into a single typed configuration object. This page covers the mechanics; for a task-oriented walkthrough see Configuration.

The primary file is application.yaml in the project root. Core settings are top-level; each extension reads its own named section:

application.yaml
app_name: "order-service"
debug: false
env: "production"
db: # lexigram-sql (config_key: "db")
backend:
url: "${DATABASE_URL:sqlite+aiosqlite:///./dev.db}"
pool:
min_size: 2
max_size: 10
cache: # lexigram-cache (config_key: "cache")
backends:
- name: redis
type: redis
default: true
redis_url: "${REDIS_URL}"
from lexigram import LexigramConfig
config = LexigramConfig.from_yaml() # auto-discovers application.yaml
config = LexigramConfig.from_yaml("config/application.yaml")

Lexigram resolves ${VAR} placeholders inside YAML values at load time:

  • ${PORT} — resolves to the PORT env var; fails fast if unset.
  • ${PORT:8080} — resolves to PORT, or 8080 if unset.
db:
backend:
url: "${DATABASE_URL:sqlite+aiosqlite:///./dev.db}"

Beyond interpolation, any key can be overridden by an environment variable using the LEX_ prefix and double underscores (__) for nesting. This is the highest-priority source:

db.backend.url → LEX_SQL__BACKEND__URL
web.server.port → LEX_WEB__SERVER__PORT
ai_llm.providers[0].api_key → LEX_AI_LLM__PROVIDERS__0__API_KEY
Terminal window
LEX_WEB__SERVER__PORT=9000 lexigram run

Override base settings per environment with profile files. Activate a profile with LEX_PROFILE:

Terminal window
LEX_PROFILE=production lexigram run
  • Base: application.yaml
  • Overlay: application.{profile}.yaml (e.g. application.production.yaml)

When resolving a key, Lexigram applies sources in this order (highest priority wins):

  1. LEX_ environment variablesLEX_WEB__SERVER__PORT=9000 overrides everything
  2. Profile YAML — values from application.{profile}.yaml
  3. Base YAML — values from application.yaml
  4. Code defaults — defined in each config model

LexigramConfig exposes typed top-level fields and resolves extension sections on demand:

config = LexigramConfig.from_yaml()
# Typed top-level
config.app_name # "order-service"
config.debug # False
config.environment # Environment.PRODUCTION
# Extension sections — pass the config model to get a typed object back
db_config = config.get_section("db", DatabaseConfig)
# Dotted paths
rag_config = config.get_section("ai_rag", RAGConfig)
# Existence check
config.has_section("web") # True

Providers rarely call get_section() themselves — declaring config_key and config_model makes the framework inject the typed section automatically. See Configuration → auto-injection.


application.development.yaml
debug: true
logging:
level: DEBUG
format: text
db:
backend:
url: "sqlite+aiosqlite:///./dev.db"
application.production.yaml
debug: false
logging:
level: WARNING
format: json
cache:
backends:
- name: redis
type: redis
default: true
redis_url: "${REDIS_URL}"