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.
This commit is contained in:
liugangjian 2026-03-05 10:10:02 +08:00
parent 028605cfd0
commit faa31fdd7d
2 changed files with 18 additions and 3 deletions

View file

@ -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
})
}

View file

@ -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) {