813d3c94ef
* fix(subagents): consolidate system_prompt and skills into single SystemMessage Some LLM APIs (vLLM, Xinference, Chinese LLM providers) reject multiple system messages with \”System message must be at the beginning.\” The subagent executor was sending separate SystemMessages for the configured system_prompt and each loaded skill, which caused failures when calling task tool with sub-agents. Merge system_prompt and all skill content into one SystemMessage in the initial state, and pass system_prompt=None to create_agent() so the factory doesn't prepend a second one. Fixes #2693 * fix(subagents): update SubagentConfig.system_prompt to str | None and add astream regression test Agent-Logs-Url: https://github.com/bytedance/deer-flow/sessions/2ee03a26-e19b-4106-abc5-c76a2906383b Co-authored-by: WillemJiang <219644+WillemJiang@users.noreply.github.com> * fixed the lint error * fix the lint error in the backend * fix the unit test error of test_subagent_executor --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
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 | 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)
|