Skip to content

fix(delegation): isolate subagent iteration budgets by default (fixes #2873)#2875

Closed
Mibayy wants to merge 1 commit intoNousResearch:mainfrom
Mibayy:fix/subagent-isolated-budget
Closed

fix(delegation): isolate subagent iteration budgets by default (fixes #2873)#2875
Mibayy wants to merge 1 commit intoNousResearch:mainfrom
Mibayy:fix/subagent-isolated-budget

Conversation

@Mibayy
Copy link
Copy Markdown
Contributor

@Mibayy Mibayy commented Mar 24, 2026

Problem

Subagents consistently exit with exit_reason: max_iterations before completing their task, even when max_iterations is set explicitly. This is especially bad in batch mode with 3 parallel subagents.

Root cause: _build_child_agent() passes the parent's IterationBudget object directly to each child. That budget is already partially consumed by the parent's own turns. In parallel batch mode, all 3 children share what's left and race to exhaust it.

# Parent used 30 of 90 turns → 60 remaining, shared by all children
# 3 subagents each requested max_iterations=50

Subagent 1: gets ~20 turns → exits mid-task  ✗
Subagent 2: gets ~20 turns → exits mid-task  ✗
Subagent 3: gets ~20 turns → exits mid-task  ✗

Fix

Introduce a budget_mode config option under delegation: in config.yaml.

isolated (new default)

Each child gets a fresh IterationBudget(max_iterations) starting at 0. max_iterations=50 means exactly 50 turns, independent of parent consumption or parallel siblings.

# Same scenario with budget_mode: isolated (default)
# Parent used 30 of 90 turns — irrelevant to children

Subagent 1:  0/50 fresh budget → uses all 50 turns  ✓
Subagent 2:  0/50 fresh budget → uses all 50 turns  ✓
Subagent 3:  0/50 fresh budget → uses all 50 turns  ✓

shared (legacy)

Preserves the old behaviour for users who explicitly want a session-wide cap across parent + all children combined. Not recommended but kept for backwards compatibility.

Changes

  • tools/delegate_tool.py — read budget_mode from config in _build_child_agent(); pass iteration_budget=None (isolated) or the parent's budget object (shared). Added module-level docstring explaining both modes with concrete examples.
  • website/docs/user-guide/features/delegation.md — new "Iteration Budget Modes" section with visual examples (bar charts), updated Configuration table.

Config

delegation:
  max_iterations: 50      # per-subagent cap
  budget_mode: isolated   # "isolated" (default) or "shared" (legacy)

Closes #2873

Previously, all subagents inherited the parent's shared IterationBudget
object. This caused two compounding problems:

1. The parent's already-consumed turns reduced the budget available to
   children before they even started.

2. In batch mode (3 parallel subagents), all children raced to consume
   the same depleted pool, each getting roughly 1/N of what remained.

Example of the bug:
  Parent uses 30 of 90 turns, then spawns 3 subagents with max_iterations=50.
  Only 60 turns remain in the shared budget.
  3 children race for 60 → each gets ~20 on average → all hit max_iterations
  mid-task and exit with exit_reason: max_iterations.

Fix: introduce budget_mode config option (delegation.budget_mode).

  isolated (default): each child gets a fresh IterationBudget(max_iterations)
    starting at 0.  max_iterations=50 means exactly 50 turns for that child,
    regardless of parent consumption or sibling activity.

  shared (legacy): preserves the old behaviour for users who explicitly
    want a session-wide hard cap across parent + all children.

After this change:
  Parent:     30/90 consumed (irrelevant to children in isolated mode)
  Subagent 1:  0/50  fresh budget → can use all 50 turns
  Subagent 2:  0/50  fresh budget → can use all 50 turns
  Subagent 3:  0/50  fresh budget → can use all 50 turns

Fixes NousResearch#2873
@teknium1
Copy link
Copy Markdown
Contributor

This was already fixed on main in commit 68ab37e (PR #3004), which sets iteration_budget=None so each subagent gets a fresh independent budget. The core bug is resolved. The additional budget_mode: shared config toggle for the old broken behavior isn't something we want to maintain. Thanks for the report and detailed writeup though — the problem description was spot-on.

@teknium1 teknium1 closed this Mar 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Subagents hit max_iterations prematurely — shared IterationBudget drains parent's remaining quota

2 participants