chroe(config):Increase subagent max-turn limits (#1852)

This commit is contained in:
Markus Corazzione 2026-04-05 04:41:00 -03:00 committed by GitHub
parent d3b59a7931
commit 0ffe5a73c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 161 additions and 42 deletions

View File

@ -15,6 +15,11 @@ class SubagentOverrideConfig(BaseModel):
ge=1, ge=1,
description="Timeout in seconds for this subagent (None = use global default)", description="Timeout in seconds for this subagent (None = use global default)",
) )
max_turns: int | None = Field(
default=None,
ge=1,
description="Maximum turns for this subagent (None = use global or builtin default)",
)
class SubagentsAppConfig(BaseModel): class SubagentsAppConfig(BaseModel):
@ -25,6 +30,11 @@ class SubagentsAppConfig(BaseModel):
ge=1, ge=1,
description="Default timeout in seconds for all subagents (default: 900 = 15 minutes)", description="Default timeout in seconds for all subagents (default: 900 = 15 minutes)",
) )
max_turns: int | None = Field(
default=None,
ge=1,
description="Optional default max-turn override for all subagents (None = keep builtin defaults)",
)
agents: dict[str, SubagentOverrideConfig] = Field( agents: dict[str, SubagentOverrideConfig] = Field(
default_factory=dict, default_factory=dict,
description="Per-agent configuration overrides keyed by agent name", description="Per-agent configuration overrides keyed by agent name",
@ -44,6 +54,15 @@ class SubagentsAppConfig(BaseModel):
return override.timeout_seconds return override.timeout_seconds
return self.timeout_seconds return self.timeout_seconds
def get_max_turns_for(self, agent_name: str, builtin_default: int) -> int:
"""Get the effective max_turns for a specific agent."""
override = self.agents.get(agent_name)
if override is not None and override.max_turns is not None:
return override.max_turns
if self.max_turns is not None:
return self.max_turns
return builtin_default
_subagents_config: SubagentsAppConfig = SubagentsAppConfig() _subagents_config: SubagentsAppConfig = SubagentsAppConfig()
@ -58,8 +77,26 @@ def load_subagents_config_from_dict(config_dict: dict) -> None:
global _subagents_config global _subagents_config
_subagents_config = SubagentsAppConfig(**config_dict) _subagents_config = SubagentsAppConfig(**config_dict)
overrides_summary = {name: f"{override.timeout_seconds}s" for name, override in _subagents_config.agents.items() if override.timeout_seconds is not None} overrides_summary = {}
for name, override in _subagents_config.agents.items():
parts = []
if override.timeout_seconds is not None:
parts.append(f"timeout={override.timeout_seconds}s")
if override.max_turns is not None:
parts.append(f"max_turns={override.max_turns}")
if parts:
overrides_summary[name] = ", ".join(parts)
if overrides_summary: if overrides_summary:
logger.info(f"Subagents config loaded: default timeout={_subagents_config.timeout_seconds}s, per-agent overrides={overrides_summary}") logger.info(
"Subagents config loaded: default timeout=%ss, default max_turns=%s, per-agent overrides=%s",
_subagents_config.timeout_seconds,
_subagents_config.max_turns,
overrides_summary,
)
else: else:
logger.info(f"Subagents config loaded: default timeout={_subagents_config.timeout_seconds}s, no per-agent overrides") logger.info(
"Subagents config loaded: default timeout=%ss, default max_turns=%s, no per-agent overrides",
_subagents_config.timeout_seconds,
_subagents_config.max_turns,
)

View File

@ -43,5 +43,5 @@ You have access to the sandbox environment:
tools=["bash", "ls", "read_file", "write_file", "str_replace"], # Sandbox tools only tools=["bash", "ls", "read_file", "write_file", "str_replace"], # Sandbox tools only
disallowed_tools=["task", "ask_clarification", "present_files"], disallowed_tools=["task", "ask_clarification", "present_files"],
model="inherit", model="inherit",
max_turns=30, max_turns=60,
) )

View File

@ -44,5 +44,5 @@ You have access to the same sandbox environment as the parent agent:
tools=None, # Inherit all tools from parent tools=None, # Inherit all tools from parent
disallowed_tools=["task", "ask_clarification", "present_files"], # Prevent nesting and clarification disallowed_tools=["task", "ask_clarification", "present_files"], # Prevent nesting and clarification
model="inherit", model="inherit",
max_turns=50, max_turns=100,
) )

View File

@ -28,9 +28,27 @@ def get_subagent_config(name: str) -> SubagentConfig | None:
app_config = get_subagents_app_config() app_config = get_subagents_app_config()
effective_timeout = app_config.get_timeout_for(name) effective_timeout = app_config.get_timeout_for(name)
effective_max_turns = app_config.get_max_turns_for(name, config.max_turns)
overrides = {}
if effective_timeout != config.timeout_seconds: if effective_timeout != config.timeout_seconds:
logger.debug(f"Subagent '{name}': timeout overridden by config.yaml ({config.timeout_seconds}s -> {effective_timeout}s)") logger.debug(
config = replace(config, timeout_seconds=effective_timeout) "Subagent '%s': timeout overridden by config.yaml (%ss -> %ss)",
name,
config.timeout_seconds,
effective_timeout,
)
overrides["timeout_seconds"] = effective_timeout
if effective_max_turns != config.max_turns:
logger.debug(
"Subagent '%s': max_turns overridden by config.yaml (%s -> %s)",
name,
config.max_turns,
effective_max_turns,
)
overrides["max_turns"] = effective_max_turns
if overrides:
config = replace(config, **overrides)
return config return config

View File

@ -1,8 +1,8 @@
"""Tests for subagent timeout configuration. """Tests for subagent runtime configuration.
Covers: Covers:
- SubagentsAppConfig / SubagentOverrideConfig model validation and defaults - SubagentsAppConfig / SubagentOverrideConfig model validation and defaults
- get_timeout_for() resolution logic (global vs per-agent) - get_timeout_for() / get_max_turns_for() resolution logic
- load_subagents_config_from_dict() and get_subagents_app_config() singleton - load_subagents_config_from_dict() and get_subagents_app_config() singleton
- registry.get_subagent_config() applies config overrides - registry.get_subagent_config() applies config overrides
- registry.list_subagents() applies overrides for all agents - registry.list_subagents() applies overrides for all agents
@ -24,9 +24,20 @@ from deerflow.subagents.config import SubagentConfig
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def _reset_subagents_config(timeout_seconds: int = 900, agents: dict | None = None) -> None: def _reset_subagents_config(
timeout_seconds: int = 900,
*,
max_turns: int | None = None,
agents: dict | None = None,
) -> None:
"""Reset global subagents config to a known state.""" """Reset global subagents config to a known state."""
load_subagents_config_from_dict({"timeout_seconds": timeout_seconds, "agents": agents or {}}) load_subagents_config_from_dict(
{
"timeout_seconds": timeout_seconds,
"max_turns": max_turns,
"agents": agents or {},
}
)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -38,22 +49,29 @@ class TestSubagentOverrideConfig:
def test_default_is_none(self): def test_default_is_none(self):
override = SubagentOverrideConfig() override = SubagentOverrideConfig()
assert override.timeout_seconds is None assert override.timeout_seconds is None
assert override.max_turns is None
def test_explicit_value(self): def test_explicit_value(self):
override = SubagentOverrideConfig(timeout_seconds=300) override = SubagentOverrideConfig(timeout_seconds=300, max_turns=42)
assert override.timeout_seconds == 300 assert override.timeout_seconds == 300
assert override.max_turns == 42
def test_rejects_zero(self): def test_rejects_zero(self):
with pytest.raises(ValueError): with pytest.raises(ValueError):
SubagentOverrideConfig(timeout_seconds=0) SubagentOverrideConfig(timeout_seconds=0)
with pytest.raises(ValueError):
SubagentOverrideConfig(max_turns=0)
def test_rejects_negative(self): def test_rejects_negative(self):
with pytest.raises(ValueError): with pytest.raises(ValueError):
SubagentOverrideConfig(timeout_seconds=-1) SubagentOverrideConfig(timeout_seconds=-1)
with pytest.raises(ValueError):
SubagentOverrideConfig(max_turns=-1)
def test_minimum_valid_value(self): def test_minimum_valid_value(self):
override = SubagentOverrideConfig(timeout_seconds=1) override = SubagentOverrideConfig(timeout_seconds=1, max_turns=1)
assert override.timeout_seconds == 1 assert override.timeout_seconds == 1
assert override.max_turns == 1
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -66,66 +84,86 @@ class TestSubagentsAppConfigDefaults:
config = SubagentsAppConfig() config = SubagentsAppConfig()
assert config.timeout_seconds == 900 assert config.timeout_seconds == 900
def test_default_max_turns_override_is_none(self):
config = SubagentsAppConfig()
assert config.max_turns is None
def test_default_agents_empty(self): def test_default_agents_empty(self):
config = SubagentsAppConfig() config = SubagentsAppConfig()
assert config.agents == {} assert config.agents == {}
def test_custom_global_timeout(self): def test_custom_global_runtime_overrides(self):
config = SubagentsAppConfig(timeout_seconds=1800) config = SubagentsAppConfig(timeout_seconds=1800, max_turns=120)
assert config.timeout_seconds == 1800 assert config.timeout_seconds == 1800
assert config.max_turns == 120
def test_rejects_zero_timeout(self): def test_rejects_zero_timeout(self):
with pytest.raises(ValueError): with pytest.raises(ValueError):
SubagentsAppConfig(timeout_seconds=0) SubagentsAppConfig(timeout_seconds=0)
with pytest.raises(ValueError):
SubagentsAppConfig(max_turns=0)
def test_rejects_negative_timeout(self): def test_rejects_negative_timeout(self):
with pytest.raises(ValueError): with pytest.raises(ValueError):
SubagentsAppConfig(timeout_seconds=-60) SubagentsAppConfig(timeout_seconds=-60)
with pytest.raises(ValueError):
SubagentsAppConfig(max_turns=-60)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# SubagentsAppConfig.get_timeout_for() # SubagentsAppConfig resolution helpers
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
class TestGetTimeoutFor: class TestRuntimeResolution:
def test_returns_global_default_when_no_override(self): def test_returns_global_default_when_no_override(self):
config = SubagentsAppConfig(timeout_seconds=600) config = SubagentsAppConfig(timeout_seconds=600)
assert config.get_timeout_for("general-purpose") == 600 assert config.get_timeout_for("general-purpose") == 600
assert config.get_timeout_for("bash") == 600 assert config.get_timeout_for("bash") == 600
assert config.get_timeout_for("unknown-agent") == 600 assert config.get_timeout_for("unknown-agent") == 600
assert config.get_max_turns_for("general-purpose", 100) == 100
assert config.get_max_turns_for("bash", 60) == 60
def test_returns_per_agent_override_when_set(self): def test_returns_per_agent_override_when_set(self):
config = SubagentsAppConfig( config = SubagentsAppConfig(
timeout_seconds=900, timeout_seconds=900,
agents={"bash": SubagentOverrideConfig(timeout_seconds=300)}, max_turns=120,
agents={"bash": SubagentOverrideConfig(timeout_seconds=300, max_turns=80)},
) )
assert config.get_timeout_for("bash") == 300 assert config.get_timeout_for("bash") == 300
assert config.get_max_turns_for("bash", 60) == 80
def test_other_agents_still_use_global_default(self): def test_other_agents_still_use_global_default(self):
config = SubagentsAppConfig( config = SubagentsAppConfig(
timeout_seconds=900, timeout_seconds=900,
agents={"bash": SubagentOverrideConfig(timeout_seconds=300)}, max_turns=140,
agents={"bash": SubagentOverrideConfig(timeout_seconds=300, max_turns=80)},
) )
assert config.get_timeout_for("general-purpose") == 900 assert config.get_timeout_for("general-purpose") == 900
assert config.get_max_turns_for("general-purpose", 100) == 140
def test_agent_with_none_override_falls_back_to_global(self): def test_agent_with_none_override_falls_back_to_global(self):
config = SubagentsAppConfig( config = SubagentsAppConfig(
timeout_seconds=900, timeout_seconds=900,
agents={"general-purpose": SubagentOverrideConfig(timeout_seconds=None)}, max_turns=150,
agents={"general-purpose": SubagentOverrideConfig(timeout_seconds=None, max_turns=None)},
) )
assert config.get_timeout_for("general-purpose") == 900 assert config.get_timeout_for("general-purpose") == 900
assert config.get_max_turns_for("general-purpose", 100) == 150
def test_multiple_per_agent_overrides(self): def test_multiple_per_agent_overrides(self):
config = SubagentsAppConfig( config = SubagentsAppConfig(
timeout_seconds=900, timeout_seconds=900,
max_turns=120,
agents={ agents={
"general-purpose": SubagentOverrideConfig(timeout_seconds=1800), "general-purpose": SubagentOverrideConfig(timeout_seconds=1800, max_turns=200),
"bash": SubagentOverrideConfig(timeout_seconds=120), "bash": SubagentOverrideConfig(timeout_seconds=120, max_turns=80),
}, },
) )
assert config.get_timeout_for("general-purpose") == 1800 assert config.get_timeout_for("general-purpose") == 1800
assert config.get_timeout_for("bash") == 120 assert config.get_timeout_for("bash") == 120
assert config.get_max_turns_for("general-purpose", 100) == 200
assert config.get_max_turns_for("bash", 60) == 80
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -139,54 +177,63 @@ class TestLoadSubagentsConfig:
_reset_subagents_config() _reset_subagents_config()
def test_load_global_timeout(self): def test_load_global_timeout(self):
load_subagents_config_from_dict({"timeout_seconds": 300}) load_subagents_config_from_dict({"timeout_seconds": 300, "max_turns": 120})
assert get_subagents_app_config().timeout_seconds == 300 assert get_subagents_app_config().timeout_seconds == 300
assert get_subagents_app_config().max_turns == 120
def test_load_with_per_agent_overrides(self): def test_load_with_per_agent_overrides(self):
load_subagents_config_from_dict( load_subagents_config_from_dict(
{ {
"timeout_seconds": 900, "timeout_seconds": 900,
"max_turns": 120,
"agents": { "agents": {
"general-purpose": {"timeout_seconds": 1800}, "general-purpose": {"timeout_seconds": 1800, "max_turns": 200},
"bash": {"timeout_seconds": 60}, "bash": {"timeout_seconds": 60, "max_turns": 80},
}, },
} }
) )
cfg = get_subagents_app_config() cfg = get_subagents_app_config()
assert cfg.get_timeout_for("general-purpose") == 1800 assert cfg.get_timeout_for("general-purpose") == 1800
assert cfg.get_timeout_for("bash") == 60 assert cfg.get_timeout_for("bash") == 60
assert cfg.get_max_turns_for("general-purpose", 100) == 200
assert cfg.get_max_turns_for("bash", 60) == 80
def test_load_partial_override(self): def test_load_partial_override(self):
load_subagents_config_from_dict( load_subagents_config_from_dict(
{ {
"timeout_seconds": 600, "timeout_seconds": 600,
"agents": {"bash": {"timeout_seconds": 120}}, "agents": {"bash": {"timeout_seconds": 120, "max_turns": 70}},
} }
) )
cfg = get_subagents_app_config() cfg = get_subagents_app_config()
assert cfg.get_timeout_for("general-purpose") == 600 assert cfg.get_timeout_for("general-purpose") == 600
assert cfg.get_timeout_for("bash") == 120 assert cfg.get_timeout_for("bash") == 120
assert cfg.get_max_turns_for("general-purpose", 100) == 100
assert cfg.get_max_turns_for("bash", 60) == 70
def test_load_empty_dict_uses_defaults(self): def test_load_empty_dict_uses_defaults(self):
load_subagents_config_from_dict({}) load_subagents_config_from_dict({})
cfg = get_subagents_app_config() cfg = get_subagents_app_config()
assert cfg.timeout_seconds == 900 assert cfg.timeout_seconds == 900
assert cfg.max_turns is None
assert cfg.agents == {} assert cfg.agents == {}
def test_load_replaces_previous_config(self): def test_load_replaces_previous_config(self):
load_subagents_config_from_dict({"timeout_seconds": 100}) load_subagents_config_from_dict({"timeout_seconds": 100, "max_turns": 90})
assert get_subagents_app_config().timeout_seconds == 100 assert get_subagents_app_config().timeout_seconds == 100
assert get_subagents_app_config().max_turns == 90
load_subagents_config_from_dict({"timeout_seconds": 200}) load_subagents_config_from_dict({"timeout_seconds": 200, "max_turns": 110})
assert get_subagents_app_config().timeout_seconds == 200 assert get_subagents_app_config().timeout_seconds == 200
assert get_subagents_app_config().max_turns == 110
def test_singleton_returns_same_instance_between_calls(self): def test_singleton_returns_same_instance_between_calls(self):
load_subagents_config_from_dict({"timeout_seconds": 777}) load_subagents_config_from_dict({"timeout_seconds": 777, "max_turns": 123})
assert get_subagents_app_config() is get_subagents_app_config() assert get_subagents_app_config() is get_subagents_app_config()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# registry.get_subagent_config timeout override applied # registry.get_subagent_config runtime overrides applied
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
@ -211,25 +258,29 @@ class TestRegistryGetSubagentConfig:
_reset_subagents_config(timeout_seconds=900) _reset_subagents_config(timeout_seconds=900)
config = get_subagent_config("general-purpose") config = get_subagent_config("general-purpose")
assert config.timeout_seconds == 900 assert config.timeout_seconds == 900
assert config.max_turns == 100
def test_global_timeout_override_applied(self): def test_global_timeout_override_applied(self):
from deerflow.subagents.registry import get_subagent_config from deerflow.subagents.registry import get_subagent_config
_reset_subagents_config(timeout_seconds=1800) _reset_subagents_config(timeout_seconds=1800, max_turns=140)
config = get_subagent_config("general-purpose") config = get_subagent_config("general-purpose")
assert config.timeout_seconds == 1800 assert config.timeout_seconds == 1800
assert config.max_turns == 140
def test_per_agent_timeout_override_applied(self): def test_per_agent_runtime_override_applied(self):
from deerflow.subagents.registry import get_subagent_config from deerflow.subagents.registry import get_subagent_config
load_subagents_config_from_dict( load_subagents_config_from_dict(
{ {
"timeout_seconds": 900, "timeout_seconds": 900,
"agents": {"bash": {"timeout_seconds": 120}}, "max_turns": 120,
"agents": {"bash": {"timeout_seconds": 120, "max_turns": 80}},
} }
) )
bash_config = get_subagent_config("bash") bash_config = get_subagent_config("bash")
assert bash_config.timeout_seconds == 120 assert bash_config.timeout_seconds == 120
assert bash_config.max_turns == 80
def test_per_agent_override_does_not_affect_other_agents(self): def test_per_agent_override_does_not_affect_other_agents(self):
from deerflow.subagents.registry import get_subagent_config from deerflow.subagents.registry import get_subagent_config
@ -237,11 +288,13 @@ class TestRegistryGetSubagentConfig:
load_subagents_config_from_dict( load_subagents_config_from_dict(
{ {
"timeout_seconds": 900, "timeout_seconds": 900,
"agents": {"bash": {"timeout_seconds": 120}}, "max_turns": 120,
"agents": {"bash": {"timeout_seconds": 120, "max_turns": 80}},
} }
) )
gp_config = get_subagent_config("general-purpose") gp_config = get_subagent_config("general-purpose")
assert gp_config.timeout_seconds == 900 assert gp_config.timeout_seconds == 900
assert gp_config.max_turns == 120
def test_builtin_config_object_is_not_mutated(self): def test_builtin_config_object_is_not_mutated(self):
"""Registry must return a new object, leaving the builtin default intact.""" """Registry must return a new object, leaving the builtin default intact."""
@ -249,24 +302,27 @@ class TestRegistryGetSubagentConfig:
from deerflow.subagents.registry import get_subagent_config from deerflow.subagents.registry import get_subagent_config
original_timeout = BUILTIN_SUBAGENTS["bash"].timeout_seconds original_timeout = BUILTIN_SUBAGENTS["bash"].timeout_seconds
load_subagents_config_from_dict({"timeout_seconds": 42}) original_max_turns = BUILTIN_SUBAGENTS["bash"].max_turns
load_subagents_config_from_dict({"timeout_seconds": 42, "max_turns": 88})
returned = get_subagent_config("bash") returned = get_subagent_config("bash")
assert returned.timeout_seconds == 42 assert returned.timeout_seconds == 42
assert returned.max_turns == 88
assert BUILTIN_SUBAGENTS["bash"].timeout_seconds == original_timeout assert BUILTIN_SUBAGENTS["bash"].timeout_seconds == original_timeout
assert BUILTIN_SUBAGENTS["bash"].max_turns == original_max_turns
def test_config_preserves_other_fields(self): def test_config_preserves_other_fields(self):
"""Applying timeout override must not change other SubagentConfig fields.""" """Applying runtime overrides must not change other SubagentConfig fields."""
from deerflow.subagents.builtins import BUILTIN_SUBAGENTS from deerflow.subagents.builtins import BUILTIN_SUBAGENTS
from deerflow.subagents.registry import get_subagent_config from deerflow.subagents.registry import get_subagent_config
_reset_subagents_config(timeout_seconds=300) _reset_subagents_config(timeout_seconds=300, max_turns=140)
original = BUILTIN_SUBAGENTS["general-purpose"] original = BUILTIN_SUBAGENTS["general-purpose"]
overridden = get_subagent_config("general-purpose") overridden = get_subagent_config("general-purpose")
assert overridden.name == original.name assert overridden.name == original.name
assert overridden.description == original.description assert overridden.description == original.description
assert overridden.max_turns == original.max_turns assert overridden.max_turns == 140
assert overridden.model == original.model assert overridden.model == original.model
assert overridden.tools == original.tools assert overridden.tools == original.tools
assert overridden.disallowed_tools == original.disallowed_tools assert overridden.disallowed_tools == original.disallowed_tools
@ -291,9 +347,10 @@ class TestRegistryListSubagents:
def test_all_returned_configs_get_global_override(self): def test_all_returned_configs_get_global_override(self):
from deerflow.subagents.registry import list_subagents from deerflow.subagents.registry import list_subagents
_reset_subagents_config(timeout_seconds=123) _reset_subagents_config(timeout_seconds=123, max_turns=77)
for cfg in list_subagents(): for cfg in list_subagents():
assert cfg.timeout_seconds == 123, f"{cfg.name} has wrong timeout" assert cfg.timeout_seconds == 123, f"{cfg.name} has wrong timeout"
assert cfg.max_turns == 77, f"{cfg.name} has wrong max_turns"
def test_per_agent_overrides_reflected_in_list(self): def test_per_agent_overrides_reflected_in_list(self):
from deerflow.subagents.registry import list_subagents from deerflow.subagents.registry import list_subagents
@ -301,15 +358,18 @@ class TestRegistryListSubagents:
load_subagents_config_from_dict( load_subagents_config_from_dict(
{ {
"timeout_seconds": 900, "timeout_seconds": 900,
"max_turns": 120,
"agents": { "agents": {
"general-purpose": {"timeout_seconds": 1800}, "general-purpose": {"timeout_seconds": 1800, "max_turns": 200},
"bash": {"timeout_seconds": 60}, "bash": {"timeout_seconds": 60, "max_turns": 80},
}, },
} }
) )
by_name = {cfg.name: cfg for cfg in list_subagents()} by_name = {cfg.name: cfg for cfg in list_subagents()}
assert by_name["general-purpose"].timeout_seconds == 1800 assert by_name["general-purpose"].timeout_seconds == 1800
assert by_name["bash"].timeout_seconds == 60 assert by_name["bash"].timeout_seconds == 60
assert by_name["general-purpose"].max_turns == 200
assert by_name["bash"].max_turns == 80
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------

View File

@ -456,13 +456,17 @@ sandbox:
# subagents: # subagents:
# # Default timeout in seconds for all subagents (default: 900 = 15 minutes) # # Default timeout in seconds for all subagents (default: 900 = 15 minutes)
# timeout_seconds: 900 # timeout_seconds: 900
# # Optional global max-turn override for all subagents
# # max_turns: 120
# #
# # Optional per-agent timeout overrides # # Optional per-agent overrides
# agents: # agents:
# general-purpose: # general-purpose:
# timeout_seconds: 1800 # 30 minutes for complex multi-step tasks # timeout_seconds: 1800 # 30 minutes for complex multi-step tasks
# max_turns: 160
# bash: # bash:
# timeout_seconds: 300 # 5 minutes for quick command execution # timeout_seconds: 300 # 5 minutes for quick command execution
# max_turns: 80
# ============================================================================ # ============================================================================
# ACP Agents Configuration # ACP Agents Configuration