[BUG] maxTurns frontmatter not enforced on sub-agents — agent runs 72+ turns with maxTurns: 10

Resolved 💬 6 comments Opened Mar 30, 2026 by ikolosov-qamadness Closed May 15, 2026

Description

The maxTurns field in agent frontmatter (.claude/agents/*.md) is documented as a hard limit that stops the sub-agent after N turns. In practice, it is not enforced — the agent runs freely past the declared limit.

Per Claude Code docs:

maxTurns — Maximum number of agentic turns before the subagent stops

Per Agent SDK docs:

You can cap the loop with max_turns / maxTurns, which counts tool-use turns only. When either limit is hit, the SDK returns a ResultMessage with subtype error_max_turns.

Reproduction

# 1. Create agent with maxTurns: 10
cat > .claude/agents/test-agent.md << 'EOF'
---
name: test-agent
description: Test agent for maxTurns enforcement
model: sonnet
maxTurns: 10
permissionMode: bypassPermissions
background: true
---
Execute the test scenarios provided.
EOF

# 2. Dispatch via Claude Code conversation:
#    Agent(subagent_type: "test-agent", prompt: "Execute 3 test scenarios against https://example.com", run_in_background: true)

# 3. Wait for completion, check output

Test Evidence (Run 1)

maxTurns: 10 (verified in file before dispatch)
Agent completed: 3/3 scenarios PASS
Assistant turns: 72
Tool uses: 47
Duration: 300s
Status: SUCCESS (not PARTIAL — agent was never stopped)

Test Evidence (Run 2 — with prompt-based self-monitoring added)

Added explicit instructions to the agent: "Count your tool calls. At 50+ calls, write results and return PARTIAL."

maxTurns: 10 (verified in file before dispatch)
Scenarios dispatched: 5
Tool calls: 75
Incremental JSON written: 0 files
PARTIAL status returned: NO
Agent ran freely past maxTurns with no enforcement

Expected Behavior

Agent should stop after 10 tool-use turns and return ResultMessage with subtype error_max_turns, as documented in the Agent SDK.

Actual Behavior

Agent runs 72-75 tool calls with no enforcement. No error_max_turns result. No interruption.

Environment

  • Claude Code CLI: 2.1.84
  • macOS 26.3.1 (also reproduced on macOS 24.6.0)
  • Node.js: v25.8.1 (also reproduced on v22.19.0)
  • Agent spawned with run_in_background: true

Impact

  • No hard safety net for runaway agents
  • Budget unpredictable — can't use maxTurns to cap token spend
  • Context window exhaustion is the only real limit
  • Documented feature doesn't work

Questions

  1. Does maxTurns in .claude/agents/*.md frontmatter get passed through to the underlying Agent SDK max_turns?
  2. Is there a difference in enforcement between foreground and run_in_background: true agents?
  3. Is this a known gap between CLI agent spawning and Agent SDK query() behavior?

View original on GitHub ↗

This issue has 6 comments on GitHub. Read the full discussion on GitHub ↗