Files
command-center/omp-docs/pi/subagent-limits.md
T
Frank 48f6163a02 docs: record omp subagent fan-out caps and per-endpoint in-flight ceilings
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.

Refs #11
2026-10-19 00:22:10 -07:00

98 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
type: reference
title: OMP Subagent Limits & Fan-out Policy
description: 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.
tags:
- omp
- subagents
- config
- fleet
timestamp: 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) have `task` stripped. **This is
"no nested subagents".**
- `n = 0` → `0 < 0` fails → **not even the main session can spawn anything.** Don't.
- `n < 0` → cap disabled.
## Per-endpoint in-flight ceilings
```yaml
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/searxng` intentionally 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_spawn` hook — 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](/pi/statusline.md) — the omp-era bundle-audit page pattern this page follows
- [/pi/packages/pi-subagents.md](/pi/packages/pi-subagents.md) — retired pi-era subagent system (historical)
- [/system/index.md](/system/index.md) — fleet endpoints these ceilings target