diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 89037d8dc..2117e2f39 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -584,6 +584,16 @@ func (al *AgentLoop) llmWorker(ctx context.Context, queue <-chan bus.InboundMess return } + // Reset per-round message-tool state so a previous round's + // tool-sent flag does not suppress this round's response. + if defaultAgent := al.registry.GetDefaultAgent(); defaultAgent != nil { + if tool, ok := defaultAgent.Tools.Get("message"); ok { + if mt, ok := tool.(*tools.MessageTool); ok { + mt.ResetSentInRound() + } + } + } + response, err := al.processMessage(ctx, msg) if err != nil { response = fmt.Sprintf("Error processing message: %v", err) diff --git a/pkg/tools/message_test.go b/pkg/tools/message_test.go index 05630972e..abd34448a 100644 --- a/pkg/tools/message_test.go +++ b/pkg/tools/message_test.go @@ -252,3 +252,29 @@ func TestMessageTool_Parameters(t *testing.T) { t.Error("Expected chat_id type to be 'string'") } } + +func TestMessageTool_ResetSentInRound(t *testing.T) { + tool := NewMessageTool() + tool.SetSendCallback(func(channel, chatID, content string) error { + return nil + }) + + ctx := WithToolContext(context.Background(), "ch", "cid") + + // First round: tool sends a message + tool.Execute(ctx, map[string]any{"content": "hello"}) + if !tool.HasSentInRound() { + t.Fatal("expected sentInRound=true after Execute") + } + + // Reset for second round + tool.ResetSentInRound() + if tool.HasSentInRound() { + t.Fatal("expected sentInRound=false after ResetSentInRound") + } + + // Second round: tool is NOT used (direct answer) → flag stays false + if tool.HasSentInRound() { + t.Error("expected sentInRound=false when tool was not used in this round") + } +}