mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-21 09:28:14 +00:00
feat(agent): spawn_child 支持 max_turns + 并行策略引导
1. spawn_child 新增 max_turns 参数(1-30,默认 5) 子 Agent 工具轮数此前硬编码 5,复杂任务跑不完即截断。现可按任务 复杂度调整;返回消息带轮数上限提示。 2. 工具描述与 system prompt 增加并行策略引导 明确'多个互不依赖的子任务应并行 spawn 多个子 Agent,不要串行 逐个执行;长耗时任务交给子 Agent 避免阻塞对话'——针对生产实例 观察到的 agent 倾向自己串行处理所有子任务的问题。 小宅自定义 prompt 同步补充并行策略段。
This commit is contained in:
@ -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 — 识别图片中的文字
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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"},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user