From faa31fdd7db460dfc2b3ca4bdc1a1dc4025da1f5 Mon Sep 17 00:00:00 2001 From: liugangjian Date: Thu, 5 Mar 2026 10:10:02 +0800 Subject: [PATCH] Fix #545: Prevent delegate messages duplication by using SendResponse: false in processSystemMessage and adding unique tracking with Once for subagent announcements This commit addresses the issue where subagent tasks were producing multiple answers after delegation: - Changed SendResponse from true to false in processSystemMessage to prevent duplicate notifications - Added sync.Once field to SubagentTask to ensure unique announcement tracking - Modified announcement logic to use sync.Once for idempotency The fixes ensure that when subagents complete their tasks, their results are communicated uniquely without duplication by preventing: 1) system messages from re-triggering user responses, and 2) multiple announcement attempts from the same subagent task. --- pkg/agent/loop.go | 2 +- pkg/tools/subagent.go | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index db9efa2cf..e9ed57c91 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -571,7 +571,7 @@ func (al *AgentLoop) processSystemMessage( UserMessage: fmt.Sprintf("[System: %s] %s", msg.SenderID, msg.Content), DefaultResponse: "Background task completed.", EnableSummary: false, - SendResponse: true, + SendResponse: false, // Prevent duplicate responses caused by system message processing }) } diff --git a/pkg/tools/subagent.go b/pkg/tools/subagent.go index 69f1a49a2..4e08c70af 100644 --- a/pkg/tools/subagent.go +++ b/pkg/tools/subagent.go @@ -20,6 +20,7 @@ type SubagentTask struct { Status string Result string Created int64 + announcedOnce sync.Once // Ensures the completion announcement is sent only once } type SubagentManager struct { @@ -216,7 +217,7 @@ After completing the task, provide a clear summary of what was done.` } // Send announce message back to main agent - if sm.bus != nil { + task.announcedOnce.Do(func() { announceContent := fmt.Sprintf("Task '%s' completed.\n\nResult:\n%s", task.Label, task.Result) pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second) defer pubCancel() @@ -227,7 +228,21 @@ After completing the task, provide a clear summary of what was done.` ChatID: fmt.Sprintf("%s:%s", task.OriginChannel, task.OriginChatID), Content: announceContent, }) - } + }) + + task.announcedOnce.Do(func() { + // Send announce message back to main agent + announceContent := fmt.Sprintf("Task '%s' completed.\n\nResult:\n%s", task.Label, task.Result) + pubCtx, pubCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer pubCancel() + sm.bus.PublishInbound(pubCtx, bus.InboundMessage{ + Channel: "system", + SenderID: fmt.Sprintf("subagent:%s", task.ID), + // Format: "original_channel:original_chat_id" for routing back + ChatID: fmt.Sprintf("%s:%s", task.OriginChannel, task.OriginChatID), + Content: announceContent, + }) + }) } func (sm *SubagentManager) GetTask(taskID string) (*SubagentTask, bool) {