usestrix/strix · warning · SubagentBudgetReservedError
Sub-agent budget reserve reached: spent ${cost:.4f} of ${sel
Error message
Sub-agent budget reserve reached: spent ${cost:.4f} of ${self._max_budget_usd:.2f} (>= {round(_SUBAGENT_BUDGET_RESERVE * 100)}% reserve); stopping this sub-agent so the root agent can finish the scan. What it means
Raised by the budget hook (strix/core/hooks.py:268) when a non-root (sub-agent) LLM call pushes total scan cost to or past 90% of max_budget_usd (_SUBAGENT_BUDGET_RESERVE = 0.90) while running headless (non-interactive). The last 10% of the budget is reserved so the root agent can still finish, write its report, and shut down cleanly. It subclasses RuntimeError and is caught internally in strix/core/execution.py, where it marks the sub-agent as stopped rather than aborting the whole scan.
Source
Thrown at strix/core/hooks.py:268
except Exception:
logger.exception("failed to record SDK usage for agent %s", agent_id)
if self._max_budget_usd is not None:
cost = report_state.get_total_llm_cost()
if cost >= self._max_budget_usd:
if self._interactive:
raise BudgetPausedError(
f"Scan budget of ${self._max_budget_usd:.2f} reached "
f"(spent ${cost:.4f}); pausing until the user continues"
)
raise BudgetExceededError(
f"Token budget of ${self._max_budget_usd:.2f} exceeded (spent ${cost:.4f})"
)
is_root = ctx.get("parent_id") is None
if not self._interactive and not is_root:
reserve_limit = self._max_budget_usd * _SUBAGENT_BUDGET_RESERVE
if cost >= reserve_limit:
raise SubagentBudgetReservedError(
f"Sub-agent budget reserve reached: spent ${cost:.4f} of "
f"${self._max_budget_usd:.2f} "
f"(>= {round(_SUBAGENT_BUDGET_RESERVE * 100)}% reserve); stopping this "
"sub-agent so the root agent can finish the scan."
)
View on GitHub (pinned to 8551339130)
Solutions
- No action needed for the scan itself: the root agent finishes and still produces a report; check run.json and penetration_test_report.md for coverage.
- Increase the ceiling: rerun with a larger --max-budget so sub-agents are not cut off at 90% of it.
- Switch to interactive mode (drop -n) — the reserve check is skipped when interactive, and the full budget raises BudgetPausedError instead so the user can continue.
- Use a cheaper model (STRIX_LLM / model=) to keep sub-agent spend under the reserve.
- Resume the scan (strix resume / is_resume path) with a higher budget to continue where sub-agents stopped.
Example fix
# before strix -n -t https://example.com --max-budget 2 # sub-agents stop at $1.80 # after strix -n -t https://example.com --max-budget 10 # reserve is $9.00, sub-agents finish
Defensive patterns
Strategy: try-catch
Validate before calling
from strix.core.hooks import SubagentBudgetReservedError # subclass of RuntimeError
# Pre-check before spawning more sub-agent work:
spent = report_state.get_total_llm_cost()
if max_budget_usd is not None and spent >= max_budget_usd * 0.90:
print('sub-agent reserve reached; root agent should wrap up') Type guard
def is_subagent_budget_reserve(exc: BaseException) -> bool:
return isinstance(exc, RuntimeError) and 'Sub-agent budget reserve' in str(exc) Try / catch
try:
await run_strix_scan(...)
except SubagentBudgetReservedError:
# non-fatal: root agent still finishes and writes the report
logging.warning('sub-agents stopped at budget reserve; report still produced') Prevention
- Size --max-budget so 90% of it covers expected sub-agent spend.
- Prefer cheaper models for deep multi-sub-agent scans.
- Treat this as a warning, not a failure: always read the produced report and run.json.
When it happens
Trigger: Running strix headless (-n) with --max-budget N while sub-agents burn tokens; on each SDK response the hook compares report_state.get_total_llm_cost() against max_budget_usd * 0.90 and raises when a sub-agent (ctx parent_id is not None) crosses that reserve threshold.
Common situations: Deep scan modes that fan out many sub-agents; cheap max-budget values (e.g. $1-5) with expensive models; cost spikes from large tool outputs inflating token usage.
Related errors
AI-assisted analysis of usestrix/strix@8551339130 (2026-08-15).
Data as JSON: /api/errors/ee49c7a903b26ddb.
Report an issue: GitHub.