From 9a255f186b875c4cea586e39d6730462c11f61cc Mon Sep 17 00:00:00 2001 From: RECTOR Date: Mon, 27 Jul 2026 13:39:23 +0700 Subject: [PATCH 1/2] feat(tools): expose maxTurns on the subagent tool params MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The subagent tool was hard-capped at 20 turns (DEFAULT_MAX_TURNS) with no way for the caller to raise it. Complex tasks (read a large file + plan + implement + test + commit) routinely hit the budget mid-task — Tasks 5/6/10 in the SPEC-6-1 dogfood all hit it. Claude Code's Task tool has no such tight cap. Expose maxTurns as an optional param (default 20 unchanged) so the model can raise it (e.g. 40) for complex multi-step tasks. Threaded through both the foreground delegate + lifecycle spawn paths. --- src/tools/subagent.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/tools/subagent.ts b/src/tools/subagent.ts index 290f960..07412ed 100644 --- a/src/tools/subagent.ts +++ b/src/tools/subagent.ts @@ -23,6 +23,7 @@ export const subagentParams = Type.Object({ auto: Type.Optional(Type.Boolean({ description: "Only relevant with `lifecycle`. Tool-driven is always auto; this flag is forward-compat. Panel-driven uses --auto on /fleet-implement." })), background: Type.Optional(Type.Boolean({ description: "Fire without awaiting. The run goes to the async/bg pool on an isolated git worktree; this returns { runId, status: 'background' } immediately. Foreground (default) awaits the result." })), schedule: Type.Optional(Type.String({ description: 'Schedule the run instead of firing now: a cron string ("0 9 * * 1-5"), an interval ("30m"/"2h"), or a one-shot ISO datetime ("2026-07-25T14:00"). Returns { scheduleId, nextFire }. Session-scoped (fires only while pi is open); no catch-up.' })), + maxTurns: Type.Optional(Type.Number({ description: 'Per-run turn budget (default 20). Raise for complex multi-step tasks (e.g. 40) so the subagent doesn\'t hit the budget mid-task; lower for trivial lookups.' })), }); export type SubagentInput = Static; @@ -87,6 +88,7 @@ export function createSubagentTool(deps: SubagentToolDeps) { skillsOverride: o.skills, backendOverride: o.backend, registry: deps.registry, todoSync: deps.todoSync, runRegistry: deps.runRegistry, lock: deps.lock, backendRegistry: deps.backendRegistry, parentModel: deps.parentModel, parentCwd: deps.parentCwd, runLog: deps.runLog, signal, + maxTurns: params.maxTurns, }), }; const res = await runLifecycle(params.task, params.lifecycle, { @@ -117,6 +119,7 @@ export function createSubagentTool(deps: SubagentToolDeps) { parentCwd: deps.parentCwd, runLog: deps.runLog, signal, + maxTurns: params.maxTurns, }); const isError = res.status === "failed" || res.status === "aborted"; return { From aeda8d8f5b5fe1ac5567c365df0fa8b615a051c3 Mon Sep 17 00:00:00 2001 From: RECTOR Date: Mon, 27 Jul 2026 13:42:35 +0700 Subject: [PATCH 2/2] =?UTF-8?q?chore:=20bump=20version=200.9.2=20=E2=86=92?= =?UTF-8?q?=200.9.3=20(subagent=20maxTurns=20param)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e35d04a..24e7b4b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@getpipher/armory-fleet", - "version": "0.9.2", + "version": "0.9.3", "private": false, "description": "The armory suite's subagent orchestrator for the pi coding agent \u2014 a cross-harness, superpowers-native fleet where every agent is armory-native from birth.", "license": "MIT",