Summary
SubagentBatchesConfig gives the durable subagent batch scheduler its own numeric knobs, but they accept YAML booleans. Pydantic coerces true to 1 before the constraint check, so with:
subagent_batches:
enabled: true
max_attempts: true # intended 3 - loads as 1
default_max_running_items: true # intended 3 - loads as 1
max_running_items_per_batch: true # intended 64 - loads as 1
...the config loads cleanly and, since the batch service captures these limits once at Gateway startup:
max_attempts: true -> every batch item gets a single attempt, so any transient failure is terminal;
default_max_running_items: true and max_running_items_per_batch: true -> batch execution serializes to one running item;
max_items_per_batch: true, default_max_live_items: true and max_live_items_per_batch: true -> the batch/live-item caps collapse to 1;
poll_interval_seconds: true -> loads as 1.0 on the float field - the same value as the default today, but a mistyped boolean silently accepted as a number.
Verified live on main (pydantic 2.13.3): the nine int fields accept True as 1; lease_seconds, max_result_chars and result_preview_max_chars reject it only via their higher ge floors, with a misleading "greater than or equal to" message.
Fix
Mirror the scheduler-config boolean guard (#6258): register the shared boolean guard (#6226) as before-validators rejecting booleans with a field-specific error across all ten numeric fields of SubagentBatchesConfig (split by wording: an integer for the int fields, a number for the float poll interval, the way the extensions config already does). PR follows immediately.
Summary
SubagentBatchesConfiggives the durable subagent batch scheduler its own numeric knobs, but they accept YAML booleans. Pydantic coercestrueto1before the constraint check, so with:...the config loads cleanly and, since the batch service captures these limits once at Gateway startup:
max_attempts: true-> every batch item gets a single attempt, so any transient failure is terminal;default_max_running_items: trueandmax_running_items_per_batch: true-> batch execution serializes to one running item;max_items_per_batch: true,default_max_live_items: trueandmax_live_items_per_batch: true-> the batch/live-item caps collapse to 1;poll_interval_seconds: true-> loads as1.0on the float field - the same value as the default today, but a mistyped boolean silently accepted as a number.Verified live on main (pydantic 2.13.3): the nine int fields accept
Trueas1;lease_seconds,max_result_charsandresult_preview_max_charsreject it only via their highergefloors, with a misleading "greater than or equal to" message.Fix
Mirror the scheduler-config boolean guard (#6258): register the shared boolean guard (#6226) as before-validators rejecting booleans with a field-specific error across all ten numeric fields of
SubagentBatchesConfig(split by wording:an integerfor the int fields,a numberfor the float poll interval, the way the extensions config already does). PR follows immediately.