feat(task): 增加子代理最大嵌套深度支持,更新相关文档和提示
This commit is contained in:
parent
631c61fea2
commit
879f5f243a
@ -242,7 +242,7 @@ fn default_task_ttl_hours() -> u64 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn default_task_max_nesting_depth() -> u32 {
|
fn default_task_max_nesting_depth() -> u32 {
|
||||||
1
|
2
|
||||||
}
|
}
|
||||||
|
|
||||||
fn default_task_allowed_tools() -> Vec<String> {
|
fn default_task_allowed_tools() -> Vec<String> {
|
||||||
|
|||||||
@ -17,7 +17,7 @@ use crate::storage::{
|
|||||||
};
|
};
|
||||||
use crate::tools::{
|
use crate::tools::{
|
||||||
DefaultSubAgentRuntime, InMemoryTaskRepository, NoopSessionMessageSender,
|
DefaultSubAgentRuntime, InMemoryTaskRepository, NoopSessionMessageSender,
|
||||||
SessionMessageSender, SubAgentRuntimeConfig, SubagentCatalog, ToolRegistry,
|
SessionMessageSender, SubAgentRuntimeConfig, SubagentCatalog, TaskTool, ToolRegistry,
|
||||||
};
|
};
|
||||||
use crate::tools::task::repository::TaskRepository;
|
use crate::tools::task::repository::TaskRepository;
|
||||||
use crate::tools::todo_write::TodoItem;
|
use crate::tools::todo_write::TodoItem;
|
||||||
@ -173,7 +173,7 @@ pub(crate) fn build_session_manager_with_sender(
|
|||||||
// Create SubAgentRuntime (if task tool is enabled)
|
// Create SubAgentRuntime (if task tool is enabled)
|
||||||
let (factory, task_repository): (_, Arc<dyn TaskRepository>) = if task_config.enabled {
|
let (factory, task_repository): (_, Arc<dyn TaskRepository>) = if task_config.enabled {
|
||||||
let task_repository = Arc::new(InMemoryTaskRepository::new());
|
let task_repository = Arc::new(InMemoryTaskRepository::new());
|
||||||
// Build subagent tools with MCP tools
|
// Build subagent tools with MCP tools (task tool registered separately below)
|
||||||
let subagent_tools = Arc::new(
|
let subagent_tools = Arc::new(
|
||||||
factory.build_subagent_tools(
|
factory.build_subagent_tools(
|
||||||
if mcp_tools_for_subagents.is_empty() {
|
if mcp_tools_for_subagents.is_empty() {
|
||||||
@ -200,20 +200,28 @@ pub(crate) fn build_session_manager_with_sender(
|
|||||||
runtime_config,
|
runtime_config,
|
||||||
task_repository.clone(),
|
task_repository.clone(),
|
||||||
conversations.clone(),
|
conversations.clone(),
|
||||||
subagent_tools,
|
subagent_tools.clone(),
|
||||||
provider_config.clone(),
|
provider_config.clone(),
|
||||||
catalog,
|
catalog,
|
||||||
bus.clone(),
|
bus.clone(),
|
||||||
store.clone(),
|
store.clone(),
|
||||||
));
|
));
|
||||||
|
|
||||||
|
// 注册 task 工具到子代理工具集(需在 runtime 创建之后,打破循环依赖)
|
||||||
|
if factory.is_enabled("task") {
|
||||||
|
subagent_tools.register(TaskTool::new_with_depth(
|
||||||
|
subagent_runtime.clone(),
|
||||||
|
task_config.max_nesting_depth,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
(factory.with_subagent_runtime(subagent_runtime), task_repository)
|
(factory.with_subagent_runtime(subagent_runtime), task_repository)
|
||||||
} else {
|
} else {
|
||||||
(factory, Arc::new(InMemoryTaskRepository::new()))
|
(factory, Arc::new(InMemoryTaskRepository::new()))
|
||||||
};
|
};
|
||||||
|
|
||||||
// Build base tools
|
// Build base tools
|
||||||
let mut tools = factory.build();
|
let tools = factory.build();
|
||||||
|
|
||||||
// Register MCP tools to main agent (async)
|
// Register MCP tools to main agent (async)
|
||||||
// Note: MCP tools for subagents are already collected above
|
// Note: MCP tools for subagents are already collected above
|
||||||
|
|||||||
@ -88,7 +88,7 @@ impl ToolRegistryFactory {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_enabled(&self, tool_name: &str) -> bool {
|
pub(crate) fn is_enabled(&self, tool_name: &str) -> bool {
|
||||||
!self.disabled_tools.contains(tool_name)
|
!self.disabled_tools.contains(tool_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,7 +99,7 @@ impl ToolRegistryFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build(&self) -> ToolRegistry {
|
pub(crate) fn build(&self) -> ToolRegistry {
|
||||||
let mut registry = ToolRegistry::new();
|
let registry = ToolRegistry::new();
|
||||||
|
|
||||||
if self.is_enabled("calculator") {
|
if self.is_enabled("calculator") {
|
||||||
registry.register(CalculatorTool::new());
|
registry.register(CalculatorTool::new());
|
||||||
@ -171,13 +171,14 @@ impl ToolRegistryFactory {
|
|||||||
registry
|
registry
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 构建子代理专用工具集(不包含 task 工具防止递归)
|
/// 构建子代理专用工具集
|
||||||
/// 可选地包含 MCP 工具(通过 mcp_tools 参数传递)
|
/// 可选地包含 MCP 工具(通过 mcp_tools 参数传递)
|
||||||
|
/// 注意:task 工具由调用方在 runtime 就绪后通过 registry.register() 单独注册
|
||||||
pub(crate) fn build_subagent_tools(
|
pub(crate) fn build_subagent_tools(
|
||||||
&self,
|
&self,
|
||||||
mcp_tools: Option<Vec<crate::mcp::tool_adapter::McpToolWrapper>>,
|
mcp_tools: Option<Vec<crate::mcp::tool_adapter::McpToolWrapper>>,
|
||||||
) -> ToolRegistry {
|
) -> ToolRegistry {
|
||||||
let mut registry = ToolRegistry::new();
|
let registry = ToolRegistry::new();
|
||||||
|
|
||||||
// 基础工具
|
// 基础工具
|
||||||
if self.is_enabled("calculator") {
|
if self.is_enabled("calculator") {
|
||||||
@ -243,16 +244,6 @@ impl ToolRegistryFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 注册 task 工具,允许子代理创建孙代理(深度由 TaskTool 运行时控制)
|
|
||||||
if self.is_enabled("task") && self.task_config.enabled {
|
|
||||||
if let Some(runtime) = &self.subagent_runtime {
|
|
||||||
registry.register(TaskTool::new_with_depth(
|
|
||||||
runtime.clone(),
|
|
||||||
self.task_config.max_nesting_depth,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
registry
|
registry
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,36 +1,51 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
use crate::domain::tools::{Tool, ToolFunction};
|
use crate::domain::tools::{Tool, ToolFunction};
|
||||||
|
|
||||||
use super::traits::Tool as ToolTrait;
|
use super::traits::Tool as ToolTrait;
|
||||||
|
|
||||||
pub struct ToolRegistry {
|
pub struct ToolRegistry {
|
||||||
tools: HashMap<String, Box<dyn ToolTrait>>,
|
tools: RwLock<HashMap<String, Arc<dyn ToolTrait>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToolRegistry {
|
impl ToolRegistry {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
tools: HashMap::new(),
|
tools: RwLock::new(HashMap::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register<T: ToolTrait + 'static>(&mut self, tool: T) {
|
pub fn register<T: ToolTrait + 'static>(&self, tool: T) {
|
||||||
self.tools.insert(tool.name().to_string(), Box::new(tool));
|
self.tools
|
||||||
|
.write()
|
||||||
|
.expect("ToolRegistry lock poisoned")
|
||||||
|
.insert(tool.name().to_string(), Arc::new(tool));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get(&self, name: &str) -> Option<&Box<dyn ToolTrait>> {
|
pub fn get(&self, name: &str) -> Option<Arc<dyn ToolTrait>> {
|
||||||
self.tools.get(name)
|
self.tools
|
||||||
|
.read()
|
||||||
|
.expect("ToolRegistry lock poisoned")
|
||||||
|
.get(name)
|
||||||
|
.cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get all registered tools.
|
/// Get all registered tools.
|
||||||
/// Used for concurrent tool execution when we need to look up tools by name.
|
/// Used for concurrent tool execution when we need to look up tools by name.
|
||||||
pub fn get_all(&self) -> Vec<&Box<dyn ToolTrait>> {
|
pub fn get_all(&self) -> Vec<Arc<dyn ToolTrait>> {
|
||||||
self.tools.values().collect()
|
self.tools
|
||||||
|
.read()
|
||||||
|
.expect("ToolRegistry lock poisoned")
|
||||||
|
.values()
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_definitions(&self) -> Vec<Tool> {
|
pub fn get_definitions(&self) -> Vec<Tool> {
|
||||||
self.tools
|
self.tools
|
||||||
|
.read()
|
||||||
|
.expect("ToolRegistry lock poisoned")
|
||||||
.values()
|
.values()
|
||||||
.map(|tool| Tool {
|
.map(|tool| Tool {
|
||||||
tool_type: "function".to_string(),
|
tool_type: "function".to_string(),
|
||||||
@ -44,11 +59,19 @@ impl ToolRegistry {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_tools(&self) -> bool {
|
pub fn has_tools(&self) -> bool {
|
||||||
!self.tools.is_empty()
|
!self.tools
|
||||||
|
.read()
|
||||||
|
.expect("ToolRegistry lock poisoned")
|
||||||
|
.is_empty()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tool_names(&self) -> Vec<String> {
|
pub fn tool_names(&self) -> Vec<String> {
|
||||||
self.tools.keys().cloned().collect()
|
self.tools
|
||||||
|
.read()
|
||||||
|
.expect("ToolRegistry lock poisoned")
|
||||||
|
.keys()
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -51,7 +51,7 @@ impl SubagentPromptBuilder {
|
|||||||
1. 专注于完成任务,不要偏离目标\n\
|
1. 专注于完成任务,不要偏离目标\n\
|
||||||
2. 使用可用的工具进行必要操作\n\
|
2. 使用可用的工具进行必要操作\n\
|
||||||
3. 完成后给出简洁的总结\n\
|
3. 完成后给出简洁的总结\n\
|
||||||
4. 不要尝试创建新的子代理任务\n\n\
|
4. 当任务复杂度较高时,可以使用 `task` 工具创建子代理来处理独立子任务\n\n\
|
||||||
任务追踪:\n\
|
任务追踪:\n\
|
||||||
你可以使用 `todo_write` 工具追踪子任务进度。规则:同一时间只有一个 in_progress,完成后再标记下一个,3步以上才使用。\n\n\
|
你可以使用 `todo_write` 工具追踪子任务进度。规则:同一时间只有一个 in_progress,完成后再标记下一个,3步以上才使用。\n\n\
|
||||||
注意: 你没有访问主对话历史的权限,这是一个独立的执行上下文。"
|
注意: 你没有访问主对话历史的权限,这是一个独立的执行上下文。"
|
||||||
|
|||||||
@ -10,7 +10,7 @@ use super::types::{TaskDefinition, TaskToolArgs};
|
|||||||
/// Task 工具 - 创建和管理子代理
|
/// Task 工具 - 创建和管理子代理
|
||||||
pub struct TaskTool {
|
pub struct TaskTool {
|
||||||
runtime: Arc<dyn SubAgentRuntime>,
|
runtime: Arc<dyn SubAgentRuntime>,
|
||||||
/// 最大嵌套深度(0 = 主 agent 不允许创建子代理,1 = 子 agent 可创建 1 层孙 agent)
|
/// 最大嵌套深度(0 = 无限制用于主 agent,>0 = 限制子代理最大嵌套层级)
|
||||||
max_nesting_depth: u32,
|
max_nesting_depth: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user