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