config/ — Application Configuration & Prompt Templates
All application configuration defined as Pydantic BaseModel schemas with hardcoded defaults. No YAML/TOML/JSON config files — the system boots with sane defaults and secrets come from Vault at runtime. The global config singleton is the canonical access point for all settings.
Files
__init__.py — Re-exports AppConfig and the config singleton. Also initializes tools.registry first (import order matters for circular dep avoidance)
config.py — Pure schema definitions (~800 lines of Pydantic BaseModel classes). Every config section lives here: ApiConfig, EmbeddingsConfig, LTMemoryConfig, PeanutGalleryConfig, etc. No logic, no side effects — just data shapes with defaults and descriptions
config_manager.py — Runtime orchestrator. Defines AppConfig (root config aggregating all sections), handles system prompt loading, provides config.get("api.max_tokens") dot-notation access, dynamic tool config via __getattr__, and creates the singleton via config = initialize_config() at module load
system_prompt.txt — Mira's core system prompt (identity, behavioral directives, output format). Loaded once at startup by AppConfig._load_system_prompt(). Template variables: {first_name}, {user_context}, {relative time since account creation} — substituted by working_memory/core.py at runtime
announcement.py — Announcement system module. Reads announcement.json once at startup into a module-level cache. load_announcement() called during lifespan, get_cached_announcement() used by cns/api/data.py to serve to frontend
announcement.json — Live announcement config. Set id + message to show a banner, set both to null to hide. Requires app restart
announcement.sample.json — Reference example for announcement format
vault.hcl — Local dev HashiCorp Vault config (file storage, TCP on 127.0.0.1:8200, no TLS). Consumed by Vault binary, not Python
Subdirectories
prompts/ — LLM prompt templates for all subsystems (extraction, feedback, synthesis, subcortical, etc.). See prompts/CLAUDE.md
Key Entry Points
| What |
Import |
Used by |
config singleton |
from config import config |
~60+ files — the universal config access pattern |
| Schema classes |
from config.config import ExtractionConfig |
Services accepting config sections as constructor params |
config.system_prompt |
Property on singleton |
Prompt composition layer |
config.<tool_name> |
Dynamic __getattr__ |
Auto-resolves tool configs via registry |
Config Sections
| Access path |
Schema class |
Scope |
config.api |
ApiConfig |
Anthropic API (default model, max_tokens, temperature, timeout), emergency fallback, thinking budgets, subcortical toggle |
config.api_server |
ApiServerConfig |
FastAPI host/port, CORS, rate limiting |
config.tools |
ToolConfig |
Essential tools list, idle thresholds |
config.system |
SystemConfig |
Logging, timezone, streaming, segments, manifest, session cache |
config.embeddings |
EmbeddingsConfig |
Fast model settings |
config.lt_memory |
LTMemoryConfig |
All LT_Memory subsystems (extraction, batching, linking, refinement, proactive, search, entity GC, scheduled jobs). ScheduledJobsConfig uses *_use_days fields — intervals measured in user activity days via modular arithmetic, not calendar days |
config.context |
ContextConfig |
Context window management, topic drift |
config.peanutgallery |
PeanutGalleryConfig |
Metacognitive observer settings |
config.lattice |
LatticeConfig |
Federation service URL/timeout |
Patterns to Follow
Accessing Config
Always use the singleton: from config import config. Then dot-access: config.api.max_tokens, config.lt_memory.extraction.fuzzy_dedup_threshold. For dynamic key access: config.get("api.max_tokens") or config.require("api.max_tokens") (raises on None).
Adding New Config
- Define a Pydantic
BaseModel in config.py with Field(default=..., description=...)
- Add it as a field on
AppConfig in config_manager.py
- Every field must have a default — no required fields (the system must boot without external config)
Secrets vs Config
- Config values (thresholds, model names, timeouts): Hardcoded defaults in Pydantic schemas
- Secrets (API keys, DB URLs, passwords): Lazy Vault lookups via properties on
AppConfig (e.g., config.api_key). These use deferred imports to avoid circular deps
Dynamic Tool Config
Accessing config.<tool_name>_tool triggers __getattr__ → registry lookup. If the tool registered a custom Pydantic config class, it's used; otherwise a default {ToolName}Config(enabled=True) is auto-generated.
System Prompt Template Variables
system_prompt.txt uses {first_name}, {user_context}, and {relative time since account creation} — substituted by the working memory composition layer (working_memory/core.py:_handle_compose_prompt), not by config itself. LoRA behavioral directives are injected as a separate system prompt section by LoraTrinket, not inline.
Prompt Loading Convention
Each service loads its own prompts from config/prompts/ via Path("config/prompts"). There is no centralized loader. See prompts/CLAUDE.md for the full catalog.
1---2name: 082-claude-9b18cc613description: config/ — Application Configuration & Prompt Templates4---5# config/ — Application Configuration & Prompt Templates67All application configuration defined as Pydantic BaseModel schemas with hardcoded defaults. No YAML/TOML/JSON config files — the system boots with sane defaults and secrets come from Vault at runtime. The global `config` singleton is the canonical access point for all settings.89## Files1011- **`__init__.py`** — Re-exports `AppConfig` and the `config` singleton. Also initializes `tools.registry` first (import order matters for circular dep avoidance)12- **`config.py`** — Pure schema definitions (~800 lines of Pydantic BaseModel classes). Every config section lives here: `ApiConfig`, `EmbeddingsConfig`, `LTMemoryConfig`, `PeanutGalleryConfig`, etc. No logic, no side effects — just data shapes with defaults and descriptions13- **`config_manager.py`** — Runtime orchestrator. Defines `AppConfig` (root config aggregating all sections), handles system prompt loading, provides `config.get("api.max_tokens")` dot-notation access, dynamic tool config via `__getattr__`, and creates the singleton via `config = initialize_config()` at module load14- **`system_prompt.txt`** — Mira's core system prompt (identity, behavioral directives, output format). Loaded once at startup by `AppConfig._load_system_prompt()`. Template variables: `{first_name}`, `{user_context}`, `{relative time since account creation}` — substituted by `working_memory/core.py` at runtime15- **`announcement.py`** — Announcement system module. Reads `announcement.json` once at startup into a module-level cache. `load_announcement()` called during lifespan, `get_cached_announcement()` used by `cns/api/data.py` to serve to frontend16- **`announcement.json`** — Live announcement config. Set `id` + `message` to show a banner, set both to `null` to hide. Requires app restart17- **`announcement.sample.json`** — Reference example for announcement format18- **`vault.hcl`** — Local dev HashiCorp Vault config (file storage, TCP on 127.0.0.1:8200, no TLS). Consumed by Vault binary, not Python1920## Subdirectories2122- **`prompts/`** — LLM prompt templates for all subsystems (extraction, feedback, synthesis, subcortical, etc.). See `prompts/CLAUDE.md`2324## Key Entry Points2526| What | Import | Used by |27|------|--------|---------|28| `config` singleton | `from config import config` | ~60+ files — the universal config access pattern |29| Schema classes | `from config.config import ExtractionConfig` | Services accepting config sections as constructor params |30| `config.system_prompt` | Property on singleton | Prompt composition layer |31| `config.<tool_name>` | Dynamic `__getattr__` | Auto-resolves tool configs via registry |3233## Config Sections3435| Access path | Schema class | Scope |36|-------------|-------------|-------|37| `config.api` | `ApiConfig` | Anthropic API (default model, max_tokens, temperature, timeout), emergency fallback, thinking budgets, subcortical toggle |38| `config.api_server` | `ApiServerConfig` | FastAPI host/port, CORS, rate limiting |39| `config.tools` | `ToolConfig` | Essential tools list, idle thresholds |40| `config.system` | `SystemConfig` | Logging, timezone, streaming, segments, manifest, session cache |41| `config.embeddings` | `EmbeddingsConfig` | Fast model settings |42| `config.lt_memory` | `LTMemoryConfig` | All LT_Memory subsystems (extraction, batching, linking, refinement, proactive, search, entity GC, scheduled jobs). `ScheduledJobsConfig` uses `*_use_days` fields — intervals measured in user activity days via modular arithmetic, not calendar days |43| `config.context` | `ContextConfig` | Context window management, topic drift |44| `config.peanutgallery` | `PeanutGalleryConfig` | Metacognitive observer settings |45| `config.lattice` | `LatticeConfig` | Federation service URL/timeout |4647## Patterns to Follow4849### Accessing Config50Always use the singleton: `from config import config`. Then dot-access: `config.api.max_tokens`, `config.lt_memory.extraction.fuzzy_dedup_threshold`. For dynamic key access: `config.get("api.max_tokens")` or `config.require("api.max_tokens")` (raises on None).5152### Adding New Config531. Define a Pydantic `BaseModel` in `config.py` with `Field(default=..., description=...)`542. Add it as a field on `AppConfig` in `config_manager.py`553. Every field must have a default — no required fields (the system must boot without external config)5657### Secrets vs Config58- **Config values** (thresholds, model names, timeouts): Hardcoded defaults in Pydantic schemas59- **Secrets** (API keys, DB URLs, passwords): Lazy Vault lookups via properties on `AppConfig` (e.g., `config.api_key`). These use deferred imports to avoid circular deps6061### Dynamic Tool Config62Accessing `config.<tool_name>_tool` triggers `__getattr__` → registry lookup. If the tool registered a custom Pydantic config class, it's used; otherwise a default `{ToolName}Config(enabled=True)` is auto-generated.6364### System Prompt Template Variables65`system_prompt.txt` uses `{first_name}`, `{user_context}`, and `{relative time since account creation}` — substituted by the working memory composition layer (`working_memory/core.py:_handle_compose_prompt`), not by config itself. LoRA behavioral directives are injected as a separate system prompt section by `LoraTrinket`, not inline.6667### Prompt Loading Convention68Each service loads its own prompts from `config/prompts/` via `Path("config/prompts")`. There is no centralized loader. See `prompts/CLAUDE.md` for the full catalog.