From 8bc8838b3ff3c81912d4a67531ab7e61763c8e8e Mon Sep 17 00:00:00 2001 From: dj-oyu <68707227+dj-oyu@users.noreply.github.com> Date: Fri, 20 Feb 2026 14:19:14 +0900 Subject: [PATCH] refactor(agent): relocate reminder to tail and update completion prompt Replace append-only reminder injection with delete-and-reappend so the reminder always sits at the tail of the messages slice, maximising LLM attention. Also change "respond with your summary" to "move on" to avoid premature stops on sub-task completion. Co-Authored-By: Claude Opus 4.6 --- pkg/agent/loop.go | 11 +++++++++-- pkg/agent/loop_test.go | 4 ++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/pkg/agent/loop.go b/pkg/agent/loop.go index 582eb9658..6733af05d 100644 --- a/pkg/agent/loop.go +++ b/pkg/agent/loop.go @@ -462,12 +462,12 @@ func buildTaskReminder(userMessage string, lastBlocker string) providers.Message if lastBlocker != "" { truncatedBlocker := utils.Truncate(lastBlocker, blockerMaxChars) content = fmt.Sprintf( - "[TASK REMINDER]\nOriginal task:\n---\n%s\n---\nLast blocker:\n---\n%s\n---\nDecide: fix the blocker if it's essential, or find an alternative approach to complete the original task.", + "[TASK REMINDER]\nOriginal task:\n---\n%s\n---\nLast blocker:\n---\n%s\n---\nFix the blocker if essential, or find an alternative. If all steps are complete, move on.", truncatedTask, truncatedBlocker, ) } else { content = fmt.Sprintf( - "[TASK REMINDER]\nOriginal task:\n---\n%s\n---\nContinue with the next step toward completing this task.", + "[TASK REMINDER]\nOriginal task:\n---\n%s\n---\nIf all steps of the original task are complete, move on. Otherwise, continue with the next step.", truncatedTask, ) } @@ -482,6 +482,7 @@ func buildTaskReminder(userMessage string, lastBlocker string) providers.Message func (al *AgentLoop) runLLMIteration(ctx context.Context, agent *AgentInstance, messages []providers.Message, opts processOptions) (string, int, error) { iteration := 0 var finalContent string + lastReminderIdx := -1 for iteration < agent.MaxIterations { iteration++ @@ -711,9 +712,15 @@ func (al *AgentLoop) runLLMIteration(ctx context.Context, agent *AgentInstance, } // Inject ephemeral task reminder to prevent focus drift. + // Remove previous reminder and re-append at the tail so it stays + // close to the LLM's attention window. if shouldInjectReminder(iteration, agent.TaskReminderInterval) && !opts.NoHistory { + if lastReminderIdx >= 0 && lastReminderIdx < len(messages) { + messages = append(messages[:lastReminderIdx], messages[lastReminderIdx+1:]...) + } reminderMsg := buildTaskReminder(opts.UserMessage, lastBlocker) messages = append(messages, reminderMsg) + lastReminderIdx = len(messages) - 1 logger.DebugCF("agent", "Injected task reminder", map[string]interface{}{ "agent_id": agent.ID, diff --git a/pkg/agent/loop_test.go b/pkg/agent/loop_test.go index bd7b82386..bbf74fc1f 100644 --- a/pkg/agent/loop_test.go +++ b/pkg/agent/loop_test.go @@ -669,8 +669,8 @@ func TestBuildTaskReminder_WithoutBlocker(t *testing.T) { if strings.Contains(msg.Content, "blocker") { t.Error("expected content NOT to contain 'blocker' when no blocker provided") } - if !strings.Contains(msg.Content, "Continue with the next step") { - t.Error("expected content to contain continuation prompt") + if !strings.Contains(msg.Content, "move on") { + t.Error("expected content to contain completion prompt") } }