Agent-loop controls
Agent-loop controls
Kill-switches (opt out of next-gen defaults)
Next-gen behavior is enabled by default. Each DISABLE_* env below reverts a single feature when set to 1 / true / yes / on. Use them for regression bisection, not day-to-day operation.
DISABLE_STRICT_PLAYBOOK
1 reverts buildPlaybookBlock to the soft-advisory header ("Follow the playbooks below…") instead of the default imperative checklist ("The playbook below is the AUTHORITATIVE specification for this turn — not guidance. …"). Useful if the stricter tone over-constrains the LLM on a given scenario or if an operator wants to A/B the difference.
- Consumed by: src/skills/scenarios/session.ts (buildPlaybookBlock).
- Format:
1/true/yes/onto disable (default unset). - Setting home: Settings → Preferences (schema key)
DISABLE_METHODOLOGY_INJECTION
1 suppresses every on-demand methodology path: scenario placeholder resolution ({{methodology:key|default:val}} falls back to default:), tool- output <methodology_reminder> fusion, and methodology_lookup tool hits. Default behavior (unset): all three paths query the store at the graduated tier (Wilson ≥ 0.55).
- Consumed by: src/skills/scenarios/methodology-placeholder.ts,
- src/core/tool-output-hints.ts, src/tools/methodology-lookup.ts.
- Format:
1/true/yes/onto disable (default unset). - Compat: legacy
METHODOLOGY_INJECTION_MODE=offis still honored as - an alias (emits a one-time deprecation warning at boot). The
- legacy
readonly/fullvalues map to the new default (enabled) - since they were both "on" states under the old tri-state.
- Setting home: Settings → Preferences (schema key)
DISABLE_METHODOLOGY_CASE_RECORDING
1 short-circuits the case recorder write path (recordHint / finalizeTurn become no-ops). Narrower than DISABLE_METHODOLOGY_INJECTION — read paths continue to work. Use when the case schema is suspected and you want to stop learning without losing LLM-visible methodology hints.
- Consumed by: src/learning/case-recorder.ts via
- src/learning/methodology-kill-switches.ts.
- Format:
1/true/yes/onto disable (default unset). - Also reachable from web-UI Settings → Preferences →
safety.methodologyCaseRecording(positive form).- Setting home: Settings → Preferences (schema key)
DISABLE_METHODOLOGY_MUTATIONS
1 short-circuits ALL methodology mutations: recordUsage / recordOutcome / requantize / synthesis cron / case-attribution all become no-ops. Reads (retrieve / findByKey / fusion / lookup) continue to work. Broadest kill switch — for incident response when the learning write path itself is suspect.
- Consumed by: src/learning/methodology-store.ts,
- src/learning/case-attribution.ts, src/learning/methodology-synthesis.ts
- via src/learning/methodology-kill-switches.ts.
- Format:
1/true/yes/onto disable (default unset). - Also reachable from web-UI Settings → Preferences →
safety.methodologyMutations(positive form).- Setting home: Settings → Preferences (schema key)
MINARA_RETRIEVAL_ENGINE
selects the retrieval engine for memory recall. bm25 (default) is the keyword full-text engine that has always shipped; hybrid combines BM25 with the vector cache for better recall on paraphrased queries at the cost of latency + memory. Unknown values fall back to bm25.
- Consumed by: src/learning/contracts/learning-services.ts (Phase 5C
- scaffolding; wiring lands in a follow-up PR).
- Format:
bm25/hybrid(defaultbm25). - Setting home: Not a user-facing setting
PROMPT_COMPOSER_ENABLED
when true the new provider-registry-based PromptComposer is used to assemble the system prompt. Phase 5B ships the composer in shadow mode (output byte-identical to the legacy assembler), so this flag is opt-in for ops who want to stress-test the composer before it becomes the default. Disabled default keeps golden snapshots stable.
- Consumed by: src/core/prompt-composer.ts.
- Format:
1/true/yes/onto enable (default unset). - Setting home: Not a user-facing setting
Methodology audit subsystem
Passive, read-only observer over the methodology learning loop. Runs SQL aggregations over the existing learning tables on a daily cadence and writes a composite health report to methodology_audit_reports. NEVER mutates learning state. Cooperative with the agent loop: skips ticks while a user turn is in flight, yields between SQL stages mid-pass. See src/learning/methodology-audit.ts and docs-site env-vars docs.
METHODOLOGY_AUDIT_CRON_ENABLED
opt-in switch for the in-process audit scheduler. Default 0 (off) — the scheduler must be explicitly enabled by an operator once the learning loop has accumulated enough data to score (typically a week or two after enabling METHODOLOGY_LEARNING_CRON_ENABLED). On a multi-worker deployment, only the worker with IS_PRIMARY_WORKER=1 runs the scheduler — replicas no-op silently.
- Consumed by: src/learning/methodology-audit-cron.ts.
- Format:
1/true/yes/onto enable. - Setting home: Settings → Preferences (schema key)
METHODOLOGY_AUDIT_CRON_INTERVAL_MS
tick interval for the audit scheduler. Default 86400000 (24h). Clamped at runtime to [5min, 30d] so a typo can't either spam the agent process or silently disable the audit.
- Consumed by: src/learning/methodology-audit-cron.ts.
- Setting home: Settings → Preferences (schema key)
METHODOLOGY_AUDIT_WINDOW_DAYS
lookback window for the window-bounded scoring dimensions (synthesis_quality, attribution_integrity, quarantine_churn). Default 30. Range clamped to [1, 365] at runtime. Larger windows smooth the trend but slow the system's reaction to a sudden degradation.
- Consumed by: src/learning/methodology-audit-cron.ts.
- Setting home: Settings → Preferences (schema key)
METHODOLOGY_AUDIT_RETENTION_DAYS
how long to keep audit reports. Default 90. Range clamped to [7, 3650]. The audit cron prunes at most once per local day after the daily tick.
- Consumed by: src/learning/methodology-audit-cron.ts.
- Setting home: Not a user-facing setting
METHODOLOGY_AUDIT_SKIP_BUSY_THRESHOLD_MS
idle threshold for the busy preflight check. Default 180000 (3min). When the BusyTracker reports inFlight > 0 OR idleSinceMs < threshold, the audit tick is deferred and deferred_count increments. Range clamped to [0, 1h]. Set to 0 to disable the preflight gate (audit runs immediately on every tick regardless of agent state) — useful for tests, not recommended in production.
- Consumed by: src/learning/methodology-audit-cron.ts.
- Setting home: Not a user-facing setting
METHODOLOGY_AUDIT_MAX_DEFERRED_TICKS
starvation guard. After this many consecutive deferred ticks the audit pass runs even if the agent is still busy, so a permanently busy installation doesn't lose audit coverage. Default 4 (≈ 4 days at the 24h default interval). Clamped to [0, 100]. Set to 0 to force every tick to run regardless of busy state.
- Consumed by: src/learning/methodology-audit-cron.ts.
- Setting home: Not a user-facing setting
METHODOLOGY_AUDIT_YIELD_TIMEOUT_MS
between each SQL stage the audit orchestrator yields to the event loop and waits for the BusyTracker to report idle. This caps that wait so a turn that never ends doesn't starve the audit indefinitely. Default 60000 (60s). Clamped to [0, 10min]. After the timeout the audit resumes regardless of busy state.
- Consumed by: src/learning/methodology-audit-cron.ts,
- src/learning/methodology-audit.ts.
- Setting home: Not a user-facing setting
DISABLE_METHODOLOGY_AUDIT
top-level kill switch for the audit subsystem. 1 short-circuits both the cron pass and the audit run CLI: a placeholder report with band=disabled is returned and NOT persisted. CLI read paths (audit show, audit trend, audit findings) are unaffected. Mirrors the existing DISABLE_METHODOLOGY_MUTATIONS kill switch.
- Consumed by: src/learning/methodology-audit.ts.
- Format:
1/true/yes/onto disable. - Setting home: Not a user-facing setting
DISABLE_METHODOLOGY_INSTANCE_DISPATCH
1 forces MethodologyInstanceStore.resolveThresholds to always return template defaults, ignoring BO-tuned per-asset-class instance overrides. Default behavior (unset): instance overrides are merged onto template defaults when present.
- Consumed by: src/learning/methodology-instance-store.ts.
- Format:
1/true/yes/onto disable (default unset). - Setting home: Not a user-facing setting
Proactive Wealth Agent
The background supervisor loop that runs each activated mandate: mark positions to market, take-profit / cut-loss / rebalance, snapshot PnL for the curve, and write the work log. Both knobs are also editable live at Settings → Proactive and inside the Proactive module's own settings tab (they map to the proactive.* preferences).
PROACTIVE_SUPERVISOR_ENABLED
master switch for the background supervisor. Default 1 (on): an activated mandate keeps working on its own within the limits you set. Set to 0 to pause every mandate's autonomous activity — the mandates stay activated, they just stop acting until you turn this back on. On a multi-worker deployment only IS_PRIMARY_WORKER=1 runs the loop; replicas no-op.
- Consumed by: src/proactive/supervisor-cron.ts.
- Format:
1/true/yes/onto enable (default on). - Setting home: Settings → Preferences (schema key)
PROACTIVE_SUPERVISOR_INTERVAL_SEC
how often each mandate checks its positions, in seconds. Default 900 (15min). Clamped at runtime to [10s, 1h] so a typo can't either spam the process or stall the loop. A shorter interval reacts faster but does more work.
- Consumed by: src/proactive/supervisor-cron.ts.
- Setting home: Settings → Preferences (schema key)
PROACTIVE_REDISCOVER_INTERVAL_SEC
how often a mandate hunts for fresh opportunities (the paid re-plan step), in seconds. Default 1800 (30min). Clamped at runtime to [1min, 24h]. This is read live each cycle, so a change applies without a restart. Re-discovery runs on top of the faster supervisor pass; less often costs less in LLM calls. Skipped gracefully when no model is configured.
- Consumed by: src/app.ts (runProactiveMandateCycle).
- Setting home: Settings → Preferences (schema key)
DISABLE_KNOWLEDGE_BUDGET
1 bypasses the Knowledge Budget negotiator entirely; scenario playbook + memory snapshot + role hints emit at full length, subject only to the Anthropic context limit. Default behavior (unset): trim if combined size exceeds KNOWLEDGE_BUDGET_TOKENS (default 15000 ≈ 60k chars).
- Consumed by: src/core/knowledge-budget.ts via src/core/agent-loop.ts.
- Format:
1/true/yes/onto disable (default unset). - Setting home: Settings → Preferences (schema key)
ROLE_MEMORY_MODE
boot-time role-case learning and injection mode.
- What it controls:
offkeeps existing role cases available to audit APIs but creates, evaluates, recalls, and injects nothing new;shadow(default) stores and evaluates cases only after a matching manual trade executes, without registering recall or changing model prompts;activeadditionally recalls reflected manual cases into the matching analysis skill and institution Trader / PM prompts. Autopilot, Strategy Studio, workflow, and unknown-origin perps never enter this path. Execution tools never receive role-memory text. - When to set: keep
shadowwhile validating case quality; useactiveonly after reviewing reflections, oroffto stop new role learning. - When unset or invalid:
shadow(invalid values emit a startup warning). - Changes are read once at startup and require an agent restart.
- Format: exactly
off,shadow, oractive. - Setting home: Settings → Preferences (schema key)
DISABLE_PARALLEL_TOOL_CALLS
DISABLE_PARALLEL_TOOL_CALLS controls the per-turn tool scheduler. Set it to 1 to force every tool call to run serially. When it is unset, READ_ONLY tools share a bounded FIFO concurrency window by default. Tools that opt out, writes, fund-moving tools, unknown tools, dynamic tools, tool_invoke, and META_UNSAFE tools remain exclusive.
- Consumed by: the turn-scoped tool execution scheduler.
- Format:
1/true/yes/onto disable (default unset). - Changes take effect on the next turn.
- Setting home: Settings → Preferences (schema key)
MAX_PARALLEL_TOOL_CALLS
MAX_PARALLEL_TOOL_CALLS sets the maximum number of safe read-only tools that may run together within one turn.
- Default:
16. - Format: a decimal integer from
1to32. - Invalid values fall back to
16and emit one structured startup warning. A user preference override takes precedence over this value. - Changes take effect on the next turn. The limit is ignored when parallel tool calls are disabled.
- Setting home: Settings → Preferences (schema key)
MINARA_SUBAGENT_FOREGROUND_MAX_CONCURRENT
MINARA_SUBAGENT_FOREGROUND_MAX_CONCURRENT limits foreground Subagents without using the ordinary tool-call pool.
- Default:
8. - Format: an integer from
1to16. - Additional foreground delegations wait in their own FIFO queue. A user preference override takes precedence; changes apply on the next turn.
- Setting home: Settings → Preferences (schema key)
MINARA_SUBAGENT_BACKGROUND_MAX_CONCURRENT
MINARA_SUBAGENT_BACKGROUND_MAX_CONCURRENT limits detached Subagents in a queue independent from foreground work.
- Default:
8. - Format: an integer from
1to16. - Additional background delegations wait in their own FIFO queue. A user preference override takes precedence; changes apply on the next turn.
- Setting home: Settings → Preferences (schema key)
MINARA_SUBAGENT_TIMEOUT_SECONDS
MINARA_SUBAGENT_TIMEOUT_SECONDS sets the default wall-clock limit for each Subagent after execution starts.
- Default:
600seconds. - Format: an integer from
30to3600; queue time is excluded. - The
subagent.timeout_sargument can override this value for one delegation. A user preference override takes precedence. - Setting home: Settings → Preferences (schema key)
Shadow Mode (A/B observation logger)
Lightweight recorder that writes (current-behavior, proposed-behavior) variant pairs at instrumented decision points to the shadow_runs SQLite table for offline analysis. No LLM double-runs. Intended to validate Sprint 2+ optimizations (memory snapshot bucketing, cache hit rate, role hint injection) against real traffic.
SHADOW_MODE
recorder mode. off — no recording. Zero overhead. sampled — random sample at SHADOW_SAMPLE_RATE. Default. on — record every call. Use only for short audit windows.
- Format:
off/sampled/on. - Setting home: Not a user-facing setting
SHADOW_SAMPLE_RATE
fraction of eligible calls to record when SHADOW_MODE=sampled. Default 0.1 (10%). Range [0, 1].
- Format: float between 0 and 1.
- Setting home: Not a user-facing setting
SHADOW_RETENTION_DAYS
how many days of shadow_runs rows to keep. A one-shot prune runs at each boot to drop rows older than this threshold, preventing unbounded table growth on long-lived deploys. Default 30. Lower for high-traffic / disk-constrained environments.
- Format: positive integer.
- Setting home: Not a user-facing setting
Memory Snapshot bucketing
MemoryStore.loadSnapshot() runs once at session start and injects a FIFO 50-row memory list into the system prompt. Before Sprint 2, a burst of recent observation rows could evict long-lived preference / strategy rows. Sprint 2 replaces FIFO with per-category quotas; unused slots from the high-priority buckets overflow into observations so the total stays at 50 on sparse profiles. Emit order: preference → strategy → trade_note → observation. Consumed by: src/memory/memory-store.ts via app.ts wiring. Tuning guidance: raise preference / strategy for profile-heavy users; raise observation for noisy short-term analysis workflows.
MEMORY_SNAPSHOT_PREF_LIMIT
user-preference slots. Core profile data.
- Setting home: Not a user-facing setting
MEMORY_SNAPSHOT_STRAT_LIMIT
user's long-term strategy notes.
- Setting home: Not a user-facing setting
MEMORY_SNAPSHOT_TRADE_LIMIT
trade-complaint / post-mortem notes.
- Setting home: Not a user-facing setting
MEMORY_SNAPSHOT_OBS_LIMIT
rolling observations quota, plus the rollover pool for unused pref / strategy / trade slots.
- Setting home: Not a user-facing setting
Memory Snapshot soft refresh (P1-2)
The snapshot loaded at session start normally stays frozen for the whole session (preserves prompt prefix cache). Long sessions lose information freshness — a preference the user declared in turn 10 never reaches the prompt until the next session. Soft refresh rebuilds the snapshot mid-session when BOTH thresholds are met (write-count AND turn-count) since the last rebuild. Setting MEMORY_REFRESH_TURNS=0 restores the legacy session-frozen behavior.
MEMORY_REFRESH_WRITES
memory_write calls since last snapshot rebuild. Default 3.
- Setting home: Not a user-facing setting
MEMORY_REFRESH_TURNS
turns since last snapshot rebuild. Default 10. Set to 0 to disable soft refresh entirely (snapshot stays session- frozen). Both this AND MEMORY_REFRESH_WRITES must be reached for a rebuild — protects against cache thrash from a single big write.
- Setting home: Not a user-facing setting
MEMORY_WRITE_MAX_LEN
max characters kept when the agent saves a memory via the memory_write tool (observation / preference / trade_note / strategy categories). Longer content is trimmed to this length before it is stored, so a single oversized or poisoned entry cannot flood the system prompt or the FTS index. The stricter personalization-fact path keeps its own shorter limit and is unaffected. Consumed by src/tools/memory-tool.ts; also surfaced as the Settings preference memory.writeMaxLen. Default 2000 when unset. Accepted range 200–8000 (positive integer, characters).
- Setting home: Settings → Preferences (schema key)
Memory consolidation (FactLayer, Phase 1)
MEMORY_CONSOLIDATION_ENABLED
contradiction resolution for the chat-extracted personalization facts the background rebuilder learns.
- ON by default: the rebuilder runs one extra background LLM call per
- memory rebuild to decide, per fact, whether it duplicates / refines /
- supersedes an existing fact, so the memory snapshot stops accumulating
- stale or contradictory rows. Set to
0/false/no/offto opt - back out — then each extracted fact is appended as a new row (the
- long-standing behavior). Superseded facts are soft-deleted (recoverable)
- and every decision is logged to the memory_consolidation_events audit
- table. Consumed by memory/consolidation-config.ts +
- memory/fact-consolidation.ts. Also drives the near-duplicate arbitration
- for agent-recorded facts (memory/general-fact-service.ts).
- Format: unset /
1/true/yes/onenables; only an explicit 0/false/no/offdisables. Surfaced as the Settings →- Experimental "Tidy duplicate and outdated memories" toggle.
- Setting home: Settings → Preferences (schema key)
MEMORY_CONSOLIDATION_GUIDANCE
optional free-text steer for how consolidation merges or retires facts (e.g. "prefer my most recent statement", "keep separate notes per asset"). Injected into the resolver prompt as a NON-authoritative preference: it never overrides the hard safety rules (a hard constraint the user set is never dropped except by an explicit newer user statement; a user-stated fact always outranks an assistant-inferred one). Capped at 500 characters. No effect when MEMORY_CONSOLIDATION_ENABLED is off.
- Format: plain text, default empty (use the built-in policy).
- Setting home: Settings → Preferences (schema key)
FACT_LIFECYCLE_ENABLED
opt into the fact staleness lifecycle. When off (the default) every stored fact stays at full weight forever (the long-standing behavior). When on, the background memory rebuild runs a deterministic, no-LLM sweep that ages facts by type: a market view (observation.market_view) demotes to warm after ~14 days and drops out of the injected profile (cold) after ~45, a trade note after ~90 / ~270, while a hard constraint the user set (constraint.hard) and goals never age. Demotion is reversible — nothing is deleted, cold facts stay searchable, and a fresh mention (a consolidation update) promotes a fact back to hot. Consumed by memory/consolidation-config.ts + memory/fact-lifecycle.ts via the personalization rebuilder. Format: 1 / true / yes / on to enable; unset / anything else leaves it off. Surfaced as the Settings → Experimental "Let old memories fade" toggle.
- Setting home: Settings → Preferences (schema key)
FACT_LIFECYCLE_AGE_MULTIPLIER
global scale on every fact-lifecycle age threshold. 1 (default) uses the built-in per-type ages; 2 makes every fact last twice as long before demotion; 0.5 half as long. Lets an operator move the whole decay curve without exposing a knob per fact type. Clamped to [0.25, 10]; a non-positive / unparseable value falls back to 1. No effect when FACT_LIFECYCLE_ENABLED is off. Consumed by memory/consolidation-config.ts. Format: a positive number.
- Setting home: Settings → Preferences (schema key)
Side-task concurrency
Side-task sessions remain unlimited, while their model turns share a bounded in-process scheduler. Main-session turns bypass this limit.
MINARA_SIDE_TASK_MAX_CONCURRENT_TURNS
maximum number of side-task agent turns that may run at once across the Gateway. Additional turns wait in a fair queue; open or idle tabs consume no slot.
- Consumed by: src/gateway/side-task-concurrency.ts.
- When to set: lower it when the model provider repeatedly rate-limits concurrent side tasks.
- When unset: defaults to 8 concurrent side-task turns.
- Format: integer from 1 through 32; invalid values fall back to 8. Restart the Gateway after changing it.
- Setting home: Not a user-facing setting
Knowledge budget (dynamic-block cap)
KNOWLEDGE_BUDGET_TOKENS
Numeric cap (in tokens) for the combined size of the three dynamic knowledge blocks in the system prompt (scenario playbook + memory context + role hints). When combined size exceeds this, the negotiator trims from lowest priority first: roleHints → memoryContext → scenarioPlaybook.
- Default 15000 tokens (~60k chars ≈ 7.5% of a 200k context) — enough
- headroom for most turns. Explicit override via this env. To disable
- the negotiator entirely (let blocks emit at full length), set
DISABLE_KNOWLEDGE_BUDGET=1— see the kill-switch block above.- Format: non-negative integer.
0disables. - Setting home: Not a user-facing setting
KNOWLEDGE_SOURCE_TAGS
prepend an HTML-comment provenance tag to each dynamic knowledge block (<!-- source: memory:snapshot -->, <!-- source: role:case-memory -->). Purely for human / log-based prompt audit — LLMs treat HTML comments as noise. Default off.
- Format:
true/false. - Setting home: Not a user-facing setting