swarm-ui: per-agent cap on concurrently running subagents
Nothing capped how many subagents an agent runs at once; the operator wants to set that per agent from swarm-ui (#5234, shape (b)). AgentInference gains `max_subagents: Option<u32>`. An absent field decodes as None, so every stored value still parses and means "no cap", which is today's behaviour. swarm-controller accepts 1..=32 on PUT. 0 would refuse every start; 32 is far more concurrent claude sessions than one agent container has memory for, so anything above it is a typo, not a cap. The subagent daemon already read the agent's agent-inference key for subagent_models; it now reads it on every start and continue (not only those naming a model) and refuses a new run once the cap's worth of names is tracked, counted under the same lock as the name reservation. Every tracked slot counts: running, starting, a goal run between turns, and an interrupted one still exiting. A goal re-prompt never goes through the reservation, so it is never refused. A failed read applies no cap, as it falls back for models. swarmctl's `inference set` does GET, merge, PUT; its mirror type now carries the field so a set from the CLI keeps a cap set in swarm-ui instead of dropping it, and `get` prints it.
This commit is contained in:
parent
6d7fc0dd99
commit
9a71d1e094
10 changed files with 393 additions and 94 deletions
|
|
@ -337,6 +337,26 @@ happens until the daemon's first connection to the swarm queue succeeds.
|
|||
The match ignores case. On an ACP agent the names are the agent's own, such
|
||||
as `<provider>/<model>` on `opencode`.
|
||||
|
||||
## How many subagents may run at once
|
||||
|
||||
When the swarm sets `max_subagents` for the agent
|
||||
([`inference.md`](../swarm/inference.md)), the daemon refuses a `start`, or a
|
||||
`continue` of a session that isn't running, once that many subagents are
|
||||
running, before anything spawns:
|
||||
|
||||
```text
|
||||
3 subagents running, cap is 3 (set in swarm-ui → this agent → inference) — wait for one to finish, or `interrupt` one
|
||||
```
|
||||
|
||||
Every subagent the daemon tracks counts, whatever its role: one running a
|
||||
turn, one starting, a goal run between turns, and an interrupted one whose
|
||||
process hasn't exited yet. A goal run's next turn isn't a new start, and the
|
||||
cap never stops it. Lowering the cap stops nothing already running.
|
||||
|
||||
The daemon reads the cap with the model list, on every `start` and
|
||||
`continue`, so a change applies to the next call. Without a swarm value, or
|
||||
when the read fails, no cap applies.
|
||||
|
||||
## Runtime
|
||||
|
||||
A subagent runs on its parent agent's runtime
|
||||
|
|
|
|||
Loading…
Reference in a new issue