Codifies the limits set in agent/config.yml 2026-10-19: task concurrency 2, no nested subagent spawns (maxRecursionDepth 1 - and why 0 must never be set), 30-min runtime / 120-request budgets, isolation opt-in enabled, completion probes off, 600s tool timeout ceiling, and per-provider in-flight caps (archon 3, dragoon 2, zealot 3) keyed by models.yml provider ids with their per-machine scope caveat. Small docs-only change; no issue opened per trunk-based small-fix exemption.
5.0 KiB
type, title, description, tags, timestamp
| type | title | description | tags | timestamp | ||||
|---|---|---|---|---|---|---|---|---|
| reference | OMP Subagent Limits & Fan-out Policy | The live caps on omp subagents — concurrency 2, no nested spawns, per-endpoint in-flight ceilings, 30-min runtime, soft request budget, and the isolated-workspace policy; includes the maxRecursionDepth=0 trap. |
|
2026-10-19 |
OMP Subagent Limits & Fan-out Policy
Enforced caps on subagents spawned through the task tool / eval agent()+workpool()
from this workstation (config root agent/config.yml, machine-live tier — the live-sync
heartbeat commits it). Set 2026-10-19; values verified against the live config and the
enforcement code in the installed bundle (@oh-my-pi/pi-coding-agent/dist/cli.js).
The caps in force
| Key | Value | Default | Effect |
|---|---|---|---|
task.maxConcurrency |
2 | 32 | Session-scoped semaphore; excess spawns queue, never drop. |
task.maxRecursionDepth |
1 | 2 | Subagents cannot spawn their own subagents. See depth semantics. |
task.maxRuntimeMs |
1800000 | 0 (off) | Hard 30-min wall clock per subagent; overrun = aborted. |
task.softRequestBudget |
120 | 200 | Wrap-up notice at 120 assistant requests; force-stopped to yield at 180 (1.5×). |
task.agentIdleTtlMs |
420000 | same | Finished subagents parked to disk after 7 min idle (revivable via agent://). |
task.enableEffort |
false | false | Per-spawn effort hint hidden from the schema. |
task.isolation.enabled |
true | false | isolated: true spawns run in a copy of the checkout; only successful patches land (merge=patch, apply). Opt-in per spawn. |
task.completionProbe |
false | true | No periodic completeness side-requests into running subagents. |
tools.maxTimeout |
600 | 0 (off) | No agent may request a tool timeout above 10 min; kills timeout: 0 runaways. |
providers.maxInFlightRequests |
see below | {} (unlimited) | Per-provider ceiling on concurrent LLM requests, shared across local omp processes. |
Depth semantics — never set maxRecursionDepth: 0
Bundle predicate (U_): a session at taskDepth s keeps the task tool iff
n < 0 || s < n where n = maxRecursionDepth. The preflight repeats the check
(Cannot spawn another agent at task depth s; maximum depth is n).
n = 1→ main (depth 0) spawns; children (depth 1) havetaskstripped. This is "no nested subagents".n = 0→0 < 0fails → not even the main session can spawn anything. Don't.n < 0→ cap disabled.
Per-endpoint in-flight ceilings
providers:
maxInFlightRequests:
"llamacpp (dankserver)": 3 # main session + up to 2 task/reviewer subagents
"llamacpp (dankclaw)": 2 # frank-dragoon: security-reviewer + fallbacks
"llamacpp (dankclaw-3090)": 3 # frank-zealot: scout/sonic/librarian/designer + smol/tiny/plan/commit/vision roles
- Keys are provider ids = the quoted block labels in
agent/models.yml(one provider per host:port). The consumer does a flat map lookup by provider id; absent or ≤0 = unlimited, otherwise clamped to ≥1. - Scope is per machine, per config root: it bounds what this workstation's omp processes put on each endpoint. Other workstations, OpenWebUI, and any non-omp client are not counted. Requests past the ceiling queue, never fail.
web/searxngintentionally uncapped.
Isolation note
task.isolation.enabled: true makes the per-spawn isolated flag available — it is
opt-in per spawn, not a blanket sandbox. Requires a git repo; unavailable in plan
mode; baseline snapshot capped at 1 GiB; backends resolve via isolation.backend: auto
(overlayfs/reflink/rcopy chain on this box). Given the checkout is the deployment,
prefer isolated: true for any subagent that edits tracked files.
Deliberately not set
bash.gitGuard— offered 2026-10-19, declined; destructive-git protection stays opt-in.task.disabledAgents— no bundled agent type warrants a ban.task.agentAccountPools,tier.subagent— no-op against keyless local endpoints.PI_TASK_MAX_OUTPUT_BYTES/PI_TASK_MAX_OUTPUT_LINES— 500 KB / 5000 line defaults are sane.before_subagent_spawnhook — programmable spawn policy; revisit if these caps prove insufficient.
Verification
cfg://task, cfg://providers/maxInFlightRequests reflect all rows above; persisted
copies in agent/config.yml. Depth semantics confirmed against the shipped bundle, not
just the setting description.
Citations
agent/config.yml(live config, this repo)agent/models.yml— provider id block labels@oh-my-pi/pi-coding-agent/dist/cli.js—U_depth predicate, in-flight map lookup- omp docs:
omp://tools/task.md§ Limits & Caps
See Also
- /pi/statusline.md — the omp-era bundle-audit page pattern this page follows
- /pi/packages/pi-subagents.md — retired pi-era subagent system (historical)
- /system/index.md — fleet endpoints these ceilings target