mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-02 22:02:13 +08:00
feat: add configuration to enable/disable subagents
Add subagents.enabled flag in config.yaml to control subagent feature: - When disabled, task/task_status tools are not loaded - When disabled, system prompt excludes subagent documentation - Default is enabled for backward compatibility Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -268,6 +268,8 @@ Models, tools, sandbox providers, skills, and middleware settings are configured
|
||||
- `skills.container_path`: Container mount path (default: `/mnt/skills`)
|
||||
- `title`: Automatic thread title generation configuration
|
||||
- `summarization`: Automatic conversation summarization configuration
|
||||
- `subagents`: Subagent (task tool) configuration
|
||||
- `enabled`: Master switch to enable/disable subagents (boolean, default: true)
|
||||
- `memory`: Memory system configuration
|
||||
- `enabled`: Master switch (boolean)
|
||||
- `storage_path`: Path to memory.json file (relative to backend/)
|
||||
|
||||
@@ -2,6 +2,67 @@ from datetime import datetime
|
||||
|
||||
from src.skills import load_skills
|
||||
|
||||
SUBAGENT_SECTION = """<subagent_system>
|
||||
You can delegate tasks to specialized subagents using the `task` tool. Subagents run in isolated context and return concise results.
|
||||
|
||||
**Available Subagents:**
|
||||
- **general-purpose**: For complex, multi-step tasks requiring exploration and action
|
||||
- **bash**: For command execution (git, build, test, deploy operations)
|
||||
|
||||
**When to Use task:**
|
||||
✅ USE task when:
|
||||
- Output would be verbose (tests, builds, large file searches)
|
||||
- Multiple independent tasks can run in parallel (use `run_in_background=True`)
|
||||
- Exploring/researching codebase extensively with many file reads
|
||||
|
||||
❌ DON'T use task when:
|
||||
- Task is straightforward → execute directly for better user visibility
|
||||
- Need user clarification → subagents cannot ask questions
|
||||
- Need real-time feedback → main agent has streaming, subagents don't
|
||||
- Task depends on conversation context → subagents have isolated context
|
||||
|
||||
**Background Task Protocol (CRITICAL):**
|
||||
When you use `run_in_background=True`:
|
||||
1. **You MUST wait for completion** - Background tasks run asynchronously, but you are responsible for getting results
|
||||
2. **Poll task status** - Call `task_status(task_id)` to check progress
|
||||
3. **Check status field** - Status can be: `pending`, `running`, `completed`, `failed`
|
||||
4. **Retry if still running** - If status is `pending` or `running`, wait a moment and call `task_status` again
|
||||
5. **Report results to user** - Only respond to user AFTER getting the final result
|
||||
|
||||
**STRICT RULE: Never end the conversation with background tasks still running. You MUST retrieve all results first.**
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
# Synchronous - wait for result (preferred for most cases)
|
||||
task(
|
||||
subagent_type="general-purpose",
|
||||
prompt="Search all Python files for deprecated API usage and list them",
|
||||
description="Find deprecated APIs"
|
||||
)
|
||||
|
||||
# Background - run in parallel (MUST poll for results)
|
||||
task_id = task(
|
||||
subagent_type="bash",
|
||||
prompt="Run npm install && npm run build && npm test",
|
||||
description="Build and test frontend",
|
||||
run_in_background=True
|
||||
)
|
||||
# Extract task_id from the response
|
||||
# Then IMMEDIATELY start polling:
|
||||
while True:
|
||||
status_result = task_status(task_id)
|
||||
if "Status: completed" in status_result or "Status: failed" in status_result:
|
||||
# Task finished, use the result
|
||||
break
|
||||
# Task still running, continue polling
|
||||
|
||||
# Multiple parallel tasks
|
||||
task_id_1 = task(..., run_in_background=True)
|
||||
task_id_2 = task(..., run_in_background=True)
|
||||
# Poll BOTH tasks until complete before responding to user
|
||||
```
|
||||
</subagent_system>"""
|
||||
|
||||
SYSTEM_PROMPT_TEMPLATE = """
|
||||
<role>
|
||||
You are DeerFlow 2.0, an open-source super agent.
|
||||
@@ -103,66 +164,7 @@ You have access to skills that provide optimized workflows for specific tasks. E
|
||||
|
||||
</skill_system>
|
||||
|
||||
<subagent_system>
|
||||
You can delegate tasks to specialized subagents using the `task` tool. Subagents run in isolated context and return concise results.
|
||||
|
||||
**Available Subagents:**
|
||||
- **general-purpose**: For complex, multi-step tasks requiring exploration and action
|
||||
- **bash**: For command execution (git, build, test, deploy operations)
|
||||
|
||||
**When to Use task:**
|
||||
✅ USE task when:
|
||||
- Output would be verbose (tests, builds, large file searches)
|
||||
- Multiple independent tasks can run in parallel (use `run_in_background=True`)
|
||||
- Exploring/researching codebase extensively with many file reads
|
||||
|
||||
❌ DON'T use task when:
|
||||
- Task is straightforward → execute directly for better user visibility
|
||||
- Need user clarification → subagents cannot ask questions
|
||||
- Need real-time feedback → main agent has streaming, subagents don't
|
||||
- Task depends on conversation context → subagents have isolated context
|
||||
|
||||
**Background Task Protocol (CRITICAL):**
|
||||
When you use `run_in_background=True`:
|
||||
1. **You MUST wait for completion** - Background tasks run asynchronously, but you are responsible for getting results
|
||||
2. **Poll task status** - Call `task_status(task_id)` to check progress
|
||||
3. **Check status field** - Status can be: `pending`, `running`, `completed`, `failed`
|
||||
4. **Retry if still running** - If status is `pending` or `running`, wait a moment and call `task_status` again
|
||||
5. **Report results to user** - Only respond to user AFTER getting the final result
|
||||
|
||||
**STRICT RULE: Never end the conversation with background tasks still running. You MUST retrieve all results first.**
|
||||
|
||||
**Usage:**
|
||||
```python
|
||||
# Synchronous - wait for result (preferred for most cases)
|
||||
task(
|
||||
subagent_type="general-purpose",
|
||||
prompt="Search all Python files for deprecated API usage and list them",
|
||||
description="Find deprecated APIs"
|
||||
)
|
||||
|
||||
# Background - run in parallel (MUST poll for results)
|
||||
task_id = task(
|
||||
subagent_type="bash",
|
||||
prompt="Run npm install && npm run build && npm test",
|
||||
description="Build and test frontend",
|
||||
run_in_background=True
|
||||
)
|
||||
# Extract task_id from the response
|
||||
# Then IMMEDIATELY start polling:
|
||||
while True:
|
||||
status_result = task_status(task_id)
|
||||
if "Status: completed" in status_result or "Status: failed" in status_result:
|
||||
# Task finished, use the result
|
||||
break
|
||||
# Task still running, continue polling
|
||||
|
||||
# Multiple parallel tasks
|
||||
task_id_1 = task(..., run_in_background=True)
|
||||
task_id_2 = task(..., run_in_background=True)
|
||||
# Poll BOTH tasks until complete before responding to user
|
||||
```
|
||||
</subagent_system>
|
||||
{subagent_section}
|
||||
|
||||
<working_directory existed="true">
|
||||
- User uploads: `/mnt/user-data/uploads` - Files uploaded by the user (automatically listed in context)
|
||||
@@ -260,15 +262,17 @@ def apply_prompt_template() -> str:
|
||||
# Load only enabled skills
|
||||
skills = load_skills(enabled_only=True)
|
||||
|
||||
# Get skills container path from config
|
||||
# Get config
|
||||
try:
|
||||
from src.config import get_app_config
|
||||
|
||||
config = get_app_config()
|
||||
container_base_path = config.skills.container_path
|
||||
subagents_enabled = config.subagents.enabled
|
||||
except Exception:
|
||||
# Fallback to default if config fails
|
||||
# Fallback to defaults if config fails
|
||||
container_base_path = "/mnt/skills"
|
||||
subagents_enabled = True
|
||||
|
||||
# Generate skills list XML with paths (path points to SKILL.md file)
|
||||
if skills:
|
||||
@@ -282,11 +286,15 @@ def apply_prompt_template() -> str:
|
||||
# Get memory context
|
||||
memory_context = _get_memory_context()
|
||||
|
||||
# Include subagent section only if enabled
|
||||
subagent_section = SUBAGENT_SECTION if subagents_enabled else ""
|
||||
|
||||
# Format the prompt with dynamic skills and memory
|
||||
prompt = SYSTEM_PROMPT_TEMPLATE.format(
|
||||
skills_list=skills_list,
|
||||
skills_base_path=container_base_path,
|
||||
memory_context=memory_context,
|
||||
subagent_section=subagent_section,
|
||||
)
|
||||
|
||||
return prompt + f"\n<current_date>{datetime.now().strftime('%Y-%m-%d, %A')}</current_date>"
|
||||
|
||||
@@ -11,6 +11,7 @@ from src.config.memory_config import load_memory_config_from_dict
|
||||
from src.config.model_config import ModelConfig
|
||||
from src.config.sandbox_config import SandboxConfig
|
||||
from src.config.skills_config import SkillsConfig
|
||||
from src.config.subagents_config import SubagentsConfig
|
||||
from src.config.summarization_config import load_summarization_config_from_dict
|
||||
from src.config.title_config import load_title_config_from_dict
|
||||
from src.config.tool_config import ToolConfig, ToolGroupConfig
|
||||
@@ -26,6 +27,7 @@ class AppConfig(BaseModel):
|
||||
tools: list[ToolConfig] = Field(default_factory=list, description="Available tools")
|
||||
tool_groups: list[ToolGroupConfig] = Field(default_factory=list, description="Available tool groups")
|
||||
skills: SkillsConfig = Field(default_factory=SkillsConfig, description="Skills configuration")
|
||||
subagents: SubagentsConfig = Field(default_factory=SubagentsConfig, description="Subagents configuration")
|
||||
extensions: ExtensionsConfig = Field(default_factory=ExtensionsConfig, description="Extensions configuration (MCP servers and skills state)")
|
||||
model_config = ConfigDict(extra="allow", frozen=False)
|
||||
|
||||
|
||||
9
backend/src/config/subagents_config.py
Normal file
9
backend/src/config/subagents_config.py
Normal file
@@ -0,0 +1,9 @@
|
||||
"""Configuration for subagents."""
|
||||
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
|
||||
class SubagentsConfig(BaseModel):
|
||||
"""Configuration for subagents feature."""
|
||||
|
||||
enabled: bool = Field(default=True, description="Whether subagents are enabled")
|
||||
@@ -11,6 +11,9 @@ logger = logging.getLogger(__name__)
|
||||
BUILTIN_TOOLS = [
|
||||
present_file_tool,
|
||||
ask_clarification_tool,
|
||||
]
|
||||
|
||||
SUBAGENT_TOOLS = [
|
||||
task_tool,
|
||||
task_status_tool,
|
||||
]
|
||||
@@ -54,13 +57,19 @@ def get_available_tools(groups: list[str] | None = None, include_mcp: bool = Tru
|
||||
except Exception as e:
|
||||
logger.error(f"Failed to get cached MCP tools: {e}")
|
||||
|
||||
# Conditionally add view_image_tool only if the model supports vision
|
||||
# Conditionally add tools based on config
|
||||
builtin_tools = BUILTIN_TOOLS.copy()
|
||||
|
||||
# Add subagent tools only if enabled
|
||||
if config.subagents.enabled:
|
||||
builtin_tools.extend(SUBAGENT_TOOLS)
|
||||
logger.info("Including subagent tools (task, task_status)")
|
||||
|
||||
# If no model_name specified, use the first model (default)
|
||||
if model_name is None and config.models:
|
||||
model_name = config.models[0].name
|
||||
|
||||
# Add view_image_tool only if the model supports vision
|
||||
model_config = config.get_model_config(model_name) if model_name else None
|
||||
if model_config is not None and model_config.supports_vision:
|
||||
builtin_tools.append(view_image_tool)
|
||||
|
||||
@@ -282,6 +282,18 @@ summarization:
|
||||
#
|
||||
# For more information, see: https://modelcontextprotocol.io
|
||||
|
||||
# ============================================================================
|
||||
# Subagents Configuration
|
||||
# ============================================================================
|
||||
# Enable or disable the subagent (task tool) functionality
|
||||
# Subagents allow delegating complex tasks to specialized agents
|
||||
|
||||
subagents:
|
||||
enabled: true # Set to false to disable subagents
|
||||
|
||||
# ============================================================================
|
||||
# Memory Configuration
|
||||
# ============================================================================
|
||||
# Global memory mechanism
|
||||
# Stores user context and conversation history for personalized responses
|
||||
memory:
|
||||
|
||||
Reference in New Issue
Block a user