"""Subagent configuration definitions.""" from dataclasses import dataclass, field from typing import TYPE_CHECKING 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 load. If None, inherits all enabled skills. If an empty list, no skills are loaded. model: Model to use - 'inherit' uses parent's model. max_turns: Maximum number of agent turns before stopping. timeout_seconds: Maximum execution time in seconds (default: 900 = 15 minutes). """ 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" max_turns: int = 50 timeout_seconds: int = 900 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)