From bb232a5316f9b671d2dbceb4cea5dab39c49c0ab Mon Sep 17 00:00:00 2001 From: CrazyBoyM Date: Sun, 25 Jan 2026 00:15:12 +0800 Subject: [PATCH] fix(v2): inject NAG_REMINDER inside agent_loop, not between tasks Previously NAG_REMINDER was only checked in main() after a task completed, meaning models never saw the reminder during long-running tasks. Now NAG_REMINDER is injected inside agent_loop when rounds_without_todo > 10, so models see it during task execution (matching Kode's behavior). Fixes #14 Co-Authored-By: Claude Opus 4.5 --- docs/v2-structured-planning.md | 8 +++++++- v2_todo_agent.py | 19 ++++++++++--------- 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/docs/v2-structured-planning.md b/docs/v2-structured-planning.md index f58837f..b850616 100644 --- a/docs/v2-structured-planning.md +++ b/docs/v2-structured-planning.md @@ -89,11 +89,17 @@ NAG_REMINDER = "10+ turns without todo. Please update." Injected as context, not commands: ```python +# INITIAL_REMINDER: at conversation start (in main) +if first_message: + inject_reminder(INITIAL_REMINDER) + +# NAG_REMINDER: inside agent_loop, during task execution if rounds_without_todo > 10: inject_reminder(NAG_REMINDER) ``` -The model sees them but doesn't respond to them. +Key insight: NAG_REMINDER is injected **inside the agent loop**, so the model +sees it during long-running tasks, not just between tasks. ## The Feedback Loop diff --git a/v2_todo_agent.py b/v2_todo_agent.py index 5da8f8f..1c022d5 100644 --- a/v2_todo_agent.py +++ b/v2_todo_agent.py @@ -414,7 +414,7 @@ def agent_loop(messages: list) -> list: Same core loop as v1, but now we track whether the model is using todos. If it goes too long without updating, - we'll inject a reminder in the main() function. + we inject a reminder into the next user message (tool results). """ global rounds_without_todo @@ -464,6 +464,12 @@ def agent_loop(messages: list) -> list: rounds_without_todo += 1 messages.append({"role": "assistant", "content": response.content}) + + # Inject NAG_REMINDER into user message if model hasn't used todos + # This happens INSIDE the agent loop, so model sees it during task execution + if rounds_without_todo > 10: + results.insert(0, {"type": "text", "text": NAG_REMINDER}) + messages.append({"role": "user", "content": results}) @@ -478,9 +484,8 @@ def main(): Key v2 addition: We inject "reminder" messages to encourage todo usage without forcing it. This is a soft constraint. - Reminders are injected as part of the user message, not as - separate system prompts. The model sees them but doesn't - respond to them directly. + - INITIAL_REMINDER: injected at conversation start + - NAG_REMINDER: injected inside agent_loop when 10+ rounds without todo """ global rounds_without_todo @@ -500,16 +505,12 @@ def main(): break # Build user message content - # May include reminders as context hints content = [] if first_message: - # Gentle reminder at start + # Gentle reminder at start of conversation content.append({"type": "text", "text": INITIAL_REMINDER}) first_message = False - elif rounds_without_todo > 10: - # Nag if model hasn't used todos in a while - content.append({"type": "text", "text": NAG_REMINDER}) content.append({"type": "text", "text": user_input}) history.append({"role": "user", "content": content})