Engine Thresholds
Warden’s engines use configurable thresholds to control intervention timing and sensitivity. All of them have compiled defaults — configuration is optional.
Every section on this page belongs in rules.toml, either the global ~/.warden/rules.toml or a project’s .warden/rules.toml. None of them are read from config.toml.
Loopbreaker
Controls retry and thrash detection.
| Setting | Default | Description |
|---|---|---|
max_retries | 3 | Consecutive failures of the same command before an advisory fires |
semantic_threshold | 0.5 | Jaccard similarity above which two differently-worded commands count as the same intent |
read_spiral_min | 7 | Consecutive reads without an edit before the spiral advisory fires |
[loopbreaker]
max_retries = 4
semantic_threshold = 0.6
read_spiral_min = 8
Compass
Controls drift detection.
| Setting | Default | Description |
|---|---|---|
drift_threshold | 0.7 | Drift score above which the advisory can fire |
Focus
Controls when a low focus score becomes an advisory.
| Setting | Default | Description |
|---|---|---|
advisory_threshold | 40 | Focus score below which the focus advisory can fire |
Dream
Controls the background learning worker and how much it retains.
| Setting | Default | Description |
|---|---|---|
enabled | true | Enable background dream processing |
max_sequences | 50 | Action sequences retained |
max_repair_patterns | 30 | Error-to-fix patterns retained |
max_conventions | 20 | Learned project conventions retained |
Oversight
Tracks how much Warden auto-approves without a prompt, and how much of that is mutating work.
| Setting | Default | Description |
|---|---|---|
enabled | true | Enable oversight quality tracking |
fatigue_window_turns | 12 | Turns to look back for fatigue signals |
Session and I/O thresholds
These live under [thresholds] rather than a per-engine section.
| Setting | Default | Description |
|---|---|---|
max_read_size_kb | 50 | Largest file Read governance will serve, in kilobytes |
max_mcp_output_kb | 15 | Budget for one MCP result, in kilobytes — see below |
max_string_len | 2000 | Longest string in a Warden MCP response before trimming |
max_array_len | 30 | Longest array in a Warden MCP response before trimming |
doom_loop_threshold | 3 | Identical tool calls before a warning is injected |
offload_threshold_kb | 8 | Output size above which the result is written to a scratch file |
token_budget_advisory_k | 700 | Token budget advisory threshold, in thousands of tokens |
progressive_read_advisory_turn | 50 | Turn at which read tightening starts advising |
progressive_read_deny_turn | 80 | Turn at which read tightening starts denying |
error_slope_threshold | 0.5 | Error slope above which the heuristic advisory fires |
stale_milestone_turns | 10 | Turns without a milestone before the stale-session advisory |
token_burn_threshold_k | 15 | Tokens per turn, in thousands, above which burn is flagged |
stagnation_turns | 3 | Consecutive stagnation snapshots before an advisory |
[thresholds]
max_read_size_kb = 100 # this project has large generated files
doom_loop_threshold = 6
stagnation_turns = 8
Note that max_read_size_kb is in kilobytes, not bytes. 50 means 50KB.
How the MCP budget is enforced
A hook cannot rewrite another server’s tool result — no supported host exposes
a field for it, so a result that has already run is already in the context
window. max_mcp_output_kb is therefore enforced at the two points that do
work:
- Before the call. When a request carries a bounding argument —
limit,page_size,max_results,top_kand similar — and its value is larger than the budget allows, Warden clamps it down. An argument that is absent is never invented: MCP servers validate against their own schema, and an unknown property turns a large result into a failed call. - After the call. An over-budget result is written to a scratch file and the agent is told which argument would have bounded it, so the next call costs less. Nothing is reported as saved, because nothing was.
Warden’s own MCP responses are the exception — it owns those end to end, and
max_string_len and max_array_len trim them before they are returned.