# Configs

Configs hold behaviour that can vary by house or thread, such as bot reply modes, model defaults, prompt overrides, and feature flags. Add a config key rather than a new column or table when a setting follows this scope hierarchy.

```text
DEFAULT_CONFIG (app, in code)
  └─ house patch
       └─ thread patch
            └─ per-agent dispatch override
```

`llm.model` picks a reply turn's model, most specific scope first: a bot's own model wins, then a thread's row override, then the resolved config (a thread patch over the house's), then `DEFAULT_BOT_MODEL`. `llm.systemPrompt` is shared instructions: the house's and the thread's both reach the bot, house first, between the Arbe guide and the bot's own persona.

Resolution deep-merges the applicable layers from broadest to narrowest. It returns both the final `ResolvedConfig` and the chain of patches that produced it, so callers can explain where a value came from. Arrays replace rather than merge.

`ConfigPatch` describes stored input, so every field is optional. `ResolvedConfig` describes what callers receive after defaults are applied, so baseline fields are present and non-null. App defaults are not stored in the database; `DEFAULT_CONFIG` is their source of truth.

Per-agent dispatch settings live under `dispatch.perAgent[agentId]`. Agents are shared across houses, so they are an override within the house/thread chain rather than another scope. `botTurnLimit` (default 3, any whole number) rides the same per-agent patch: consecutive bot turns before that bot rests. Zero disables the limit. The scope-wide `dispatch.settledBotTurnThreshold` (default 8, range 0–20) stops an exchange after that many consecutive short closing bot replies; zero disables it.

## Gotchas

- Omitted and `null` mean different things. Omit or unset a key to inherit from the next broader scope. Store `null` to ignore ancestor overrides and reset that key to `DEFAULT_CONFIG`.
- Adding a required resolved key can make a newer client reject responses from an older server. Deploy the server first, or give the resolved schema a temporary default when deployment order is not guaranteed.

The director's own model and thinking level are process settings, not config; see [backstage settings](../ops/debugging.md#backstage).

Code: `@arbe/core/schemas/config.ts` owns schemas, defaults, and merge semantics. `@arbe/core/configs.ts` owns resolution and writes. The common per-agent entry point is documented under [agent trigger modes](../chat/agent-trigger-mode.md).
