diff --git a/cmd/homed/main.go b/cmd/homed/main.go index dfb4067..bab8949 100644 --- a/cmd/homed/main.go +++ b/cmd/homed/main.go @@ -391,7 +391,10 @@ func main() { - output_* — 输出通道管理(切换/发送消息) - timer_set — 设置定时提醒 - plgreload — 热重载插件 -- spawn_child — 生成子 Agent 执行独立任务 +- spawn_child — 生成子 Agent 异步执行独立任务(可传 max_turns 控制工具轮数,默认 5) + +并行策略:遇到多个互不依赖的子任务时,优先并行 spawn 多个子 Agent 而非自己串行逐个执行; +长耗时任务(批量处理、多轮搜索汇总)也应交给子 Agent,避免阻塞当前对话。 - describe_image — 描述用户上传的图片 - transcribe_audio — 转写用户上传的音频 - ocr_image — 识别图片中的文字 diff --git a/internal/agent/core/spawn.go b/internal/agent/core/spawn.go index ca809b8..b20ec82 100644 --- a/internal/agent/core/spawn.go +++ b/internal/agent/core/spawn.go @@ -13,6 +13,16 @@ func (a *Agent) executeSpawnChild(tc agentAPI.ToolCall) string { if task == "" { return "请提供 task 参数" } + maxTurns := 0 + if v, ok := tc.Arguments["max_turns"].(float64); ok { + maxTurns = int(v) + } + if maxTurns < 1 { + maxTurns = defaultChildMaxTurns + } + if maxTurns > 30 { + maxTurns = 30 + } a.childMu.Lock() a.childNextID++ @@ -26,12 +36,15 @@ func (a *Agent) executeSpawnChild(tc agentAPI.ToolCall) string { parentChannel = "cli" } - go a.runChildTask(taskID, task, parentChannel) + go a.runChildTask(taskID, task, parentChannel, maxTurns) - return fmt.Sprintf("子任务已启动(ID: %s),完成后会自动通知你,届时请使用 child_result 工具查看输出", taskID) + return fmt.Sprintf("子任务已启动(ID: %s,最多 %d 轮),完成后会自动通知你,届时请使用 child_result 工具查看输出", taskID, maxTurns) } -func (a *Agent) runChildTask(taskID, task string, parentChannel string) { +// defaultChildMaxTurns 子 Agent 默认工具轮数(可被 spawn_child 的 max_turns 参数覆盖)。 +const defaultChildMaxTurns = 5 + +func (a *Agent) runChildTask(taskID, task string, parentChannel string, maxTurns int) { if a.provider == nil { log.Printf("[child] %s failed: no LLM provider configured", taskID) return @@ -66,7 +79,7 @@ func (a *Agent) runChildTask(taskID, task string, parentChannel string) { } var finalResult string - for turn := 0; turn < 5; turn++ { + for turn := 0; turn < maxTurns; turn++ { req := &agentAPI.CompletionRequest{ Messages: msgs, MaxTokens: 4096, diff --git a/internal/agent/core/tooldefs.go b/internal/agent/core/tooldefs.go index b1b9973..d657cfc 100644 --- a/internal/agent/core/tooldefs.go +++ b/internal/agent/core/tooldefs.go @@ -460,7 +460,7 @@ func (a *Agent) buildToolDefs() []interface{} { "type": "function", "function": map[string]interface{}{ "name": "spawn_child", - "description": "启动一个异步子 Agent 执行独立任务。子 Agent 后台运行,不阻塞当前对话。完成后系统会自动通知你,届时请调用 child_result 工具查看输出。", + "description": "启动一个异步子 Agent 执行独立任务。子 Agent 后台运行,不阻塞当前对话。完成后系统会自动通知你,届时请调用 child_result 工具查看输出。\n使用时机:多个互不依赖的子任务(如同时查三个网站、分别处理多个文件)应并行 spawn 多个子 Agent,不要自己串行逐个执行;长耗时任务(批量处理、多轮搜索)也应交给子 Agent,避免阻塞对话。", "parameters": map[string]interface{}{ "type": "object", "properties": map[string]interface{}{ @@ -468,6 +468,10 @@ func (a *Agent) buildToolDefs() []interface{} { "type": "string", "description": "要子 Agent 完成的任务描述。请描述清晰、完整,包含所有必要背景。", }, + "max_turns": map[string]interface{}{ + "type": "integer", + "description": "子 Agent 最大工具轮数(默认 5,范围 1-30)。复杂任务可调高。", + }, }, "required": []string{"task"}, },