487c1d939f
* fix(subagents): use model override for tools and middleware * fix(config): resolve effective subagent model * fix(subagents): defer app config loading * fix(subagents): fully defer config.yaml load in executor __init__ The previous attempt only relocated the explicit get_app_config() call, but left resolve_subagent_model_name(...) running eagerly in __init__. That helper has its own internal get_app_config() fallback, which still fired when both app_config and parent_model were None and config.model == "inherit" — exactly the path unit tests hit, breaking 21 tests in CI with FileNotFoundError: config.yaml. Skip the eager resolve in __init__ when it would require loading the config file, and defer to _create_agent (which already has the app_config or get_app_config() fallback).
57 lines
2.0 KiB
Python
57 lines
2.0 KiB
Python
"""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
|
|
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)
|