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 <noreply@anthropic.com>
This commit is contained in:
CrazyBoyM 2026-01-25 00:15:12 +08:00
parent 8f4a130371
commit bb232a5316
2 changed files with 17 additions and 10 deletions

View File

@ -89,11 +89,17 @@ NAG_REMINDER = "<reminder>10+ turns without todo. Please update.</reminder>"
Injected as context, not commands: Injected as context, not commands:
```python ```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: if rounds_without_todo > 10:
inject_reminder(NAG_REMINDER) 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 ## The Feedback Loop

View File

@ -414,7 +414,7 @@ def agent_loop(messages: list) -> list:
Same core loop as v1, but now we track whether the model Same core loop as v1, but now we track whether the model
is using todos. If it goes too long without updating, 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 global rounds_without_todo
@ -464,6 +464,12 @@ def agent_loop(messages: list) -> list:
rounds_without_todo += 1 rounds_without_todo += 1
messages.append({"role": "assistant", "content": response.content}) 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}) messages.append({"role": "user", "content": results})
@ -478,9 +484,8 @@ def main():
Key v2 addition: We inject "reminder" messages to encourage Key v2 addition: We inject "reminder" messages to encourage
todo usage without forcing it. This is a soft constraint. todo usage without forcing it. This is a soft constraint.
Reminders are injected as part of the user message, not as - INITIAL_REMINDER: injected at conversation start
separate system prompts. The model sees them but doesn't - NAG_REMINDER: injected inside agent_loop when 10+ rounds without todo
respond to them directly.
""" """
global rounds_without_todo global rounds_without_todo
@ -500,16 +505,12 @@ def main():
break break
# Build user message content # Build user message content
# May include reminders as context hints
content = [] content = []
if first_message: if first_message:
# Gentle reminder at start # Gentle reminder at start of conversation
content.append({"type": "text", "text": INITIAL_REMINDER}) content.append({"type": "text", "text": INITIAL_REMINDER})
first_message = False 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}) content.append({"type": "text", "text": user_input})
history.append({"role": "user", "content": content}) history.append({"role": "user", "content": content})