mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-11-08 20:10:34 +00:00
* feat(subagents): add thinking_enabled and reasoning_effort config for sub-agents (#4875) (cherry picked from commit b1083728b23504cb0f1d1a463f8db70c5ec1c5a7) * fix: resolve CI failures for subagent thinking config PR - Fix UnboundLocalError in task_tool.py: initialize parent_thinking_enabled and parent_reasoning_effort before the if runtime block - Remove unused imports from test_subagent_thinking_config.py (SimpleNamespace, pytest, resolve_subagent_model_name) - Fix import sorting in subagents_config.py and test file - Add reasoning_effort: None to executor test assertion (cherry picked from commit 187851e307b871937e48bb67ae1b34b8b69bf92d) * fix: address review comments - remove parent inheritance, supports_thinking clamp, Literal type - Remove parent_thinking_enabled/parent_reasoning_effort from metadata extraction in task_tool.py (backward compatible: subagents only think when explicitly configured) - Add supports_thinking clamp in _create_agent to prevent cross-model mismatch errors - Change SubagentConfig.reasoning_effort to Literal type - Fix sandbox_state assignment that was accidentally removed - Fix syntax errors in subagents_config.py (missing closing parens) - Update all docstrings/comments from "inherit" to "no override" - Simplify test helper and remove parent inheritance tests (cherry picked from commit 74f9c659ef4a98bd1756109929ab0748fab82317) * feat(subagents): adapt reasoning settings to current native workers * fix(subagents): retain model context on reasoning rejection * fix(subagents): preserve model-factory reasoning diagnostics --------- Co-authored-by: Neon549 <neon549@users.noreply.github.com> Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com>
78 lines
3.3 KiB
Python
78 lines
3.3 KiB
Python
"""Subagent configuration definitions."""
|
|
|
|
from dataclasses import dataclass, field
|
|
from typing import TYPE_CHECKING
|
|
|
|
from deerflow.config.prompt_overlay import PromptOverlay
|
|
|
|
if TYPE_CHECKING:
|
|
from deerflow.config.app_config import AppConfig
|
|
|
|
|
|
@dataclass
|
|
class SubagentConfig:
|
|
"""Configuration for a subagent.
|
|
|
|
Attributes:
|
|
name: Unique identifier for the subagent.
|
|
description: When Claude should delegate to this subagent.
|
|
system_prompt: The system prompt that guides the subagent's behavior.
|
|
tools: Optional list of tool names to allow. If None, inherits all tools.
|
|
disallowed_tools: Optional list of tool names to deny.
|
|
skills: Optional list of skill names to make discoverable and activatable.
|
|
If None, all enabled skills are available. If empty, skills are
|
|
disabled for this subagent. Skill bodies load lazily at runtime;
|
|
allowed-tools is compatibility metadata only and never restricts
|
|
this subagent's tools.
|
|
model: Model to use - 'inherit' uses parent's model.
|
|
thinking_enabled: Whether to enable thinking/reasoning for this subagent.
|
|
None means use default (False).
|
|
reasoning_effort: Selected model's reasoning effort or None for its default.
|
|
max_turns: Maximum agent turns — model call plus the tools it runs —
|
|
before stopping. Built-in agents use the value set here
|
|
(general-purpose=150, bash=60) unless the global
|
|
``subagents.max_turns`` is set. ``turn_budget.py`` converts this
|
|
into the LangGraph ``recursion_limit`` that buys that many turns
|
|
through the assembled middleware chain; it is not passed through as
|
|
a super-step count.
|
|
timeout_seconds: Bare fallback execution-time cap. For built-in agents the
|
|
effective limit is the global ``subagents.timeout_seconds`` (default
|
|
1800 = 30 min), layered on by the registry; this 900 only applies
|
|
when no differing global value exists.
|
|
prompt_overlay: Operator instructions around the complete system message.
|
|
"""
|
|
|
|
name: str
|
|
description: str
|
|
system_prompt: str | None = None
|
|
tools: list[str] | None = None
|
|
disallowed_tools: list[str] | None = field(default_factory=lambda: ["task"])
|
|
skills: list[str] | None = None
|
|
model: str = "inherit"
|
|
thinking_enabled: bool | None = None
|
|
reasoning_effort: str | None = None
|
|
max_turns: int = 50
|
|
timeout_seconds: int = 900
|
|
prompt_overlay: PromptOverlay = field(default_factory=PromptOverlay)
|
|
|
|
|
|
def _default_model_name(app_config: "AppConfig") -> str:
|
|
if not app_config.models:
|
|
raise ValueError("No chat models are configured. Please configure at least one model in config.yaml.")
|
|
return app_config.models[0].name
|
|
|
|
|
|
def resolve_subagent_model_name(config: SubagentConfig, parent_model: str | None, *, app_config: "AppConfig | None" = None) -> str:
|
|
"""Resolve the effective model name a subagent should use."""
|
|
if config.model != "inherit":
|
|
return config.model
|
|
|
|
if parent_model is not None:
|
|
return parent_model
|
|
|
|
if app_config is None:
|
|
from deerflow.config import get_app_config
|
|
|
|
app_config = get_app_config()
|
|
return _default_model_name(app_config)
|