From 2d344e4f35170c4be2d3b0773fe8b3708c63b1a0 Mon Sep 17 00:00:00 2001 From: viettranx Date: Sat, 28 Mar 2026 17:35:51 +0700 Subject: [PATCH] fix(tools): block message tool self-send to prevent duplicate media delivery When a team member creates an image and completes a task, the announce flow already carries media to the leader agent, which dispatches it to the channel via ForwardMedia. If the leader also calls the message tool to send the same image to its own chat, the image appears twice. Block message tool calls where channel+target match the agent's own context, returning an error that guides the LLM to include content in its normal response instead. --- internal/tools/message.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/internal/tools/message.go b/internal/tools/message.go index 9bd2c899..14ef02b4 100644 --- a/internal/tools/message.go +++ b/internal/tools/message.go @@ -95,6 +95,15 @@ func (t *MessageTool) Execute(ctx context.Context, args map[string]any) *Result return ErrorResult("target chat ID is required (no current chat in context)") } + // Block self-send: agent should not use message tool to send to its own + // channel/chat — the response is already dispatched via normal outbound flow. + // This prevents duplicate media delivery when announce flow already carries media. + ctxChannel := ToolChannelFromCtx(ctx) + ctxChatID := ToolChatIDFromCtx(ctx) + if ctxChannel != "" && ctxChatID != "" && channel == ctxChannel && target == ctxChatID { + return ErrorResult("You are already responding to this chat. Your response (including any MEDIA: references) will be delivered automatically. Do not use the message tool to send to your own chat — just include the content in your response text.") + } + // Tenant isolation: validate channel belongs to current tenant. if err := t.validateChannelTenant(ctx, channel, target); err != nil { return err