Summary
When the agent enters a repetitive loop, the system detects it via turn hash tracking but only displays a UI nudge ("You're looping.") to the user. The agent itself never receives feedback that it is stuck, so it continues looping.
Current Behavior
src/agent/react.js tracks turn hashes in a sliding window (default size 20)
- When a duplicate hash is found, it emits a
loop_detected event
- The TUI (
src/tui/app.js:349-359) handles this by appending "You're looping." to the last assistant message display
- The agent continues its loop — it never receives a message telling it to try a different approach
Desired Behavior
When a loop is detected, inject a nudge message into the conversation that the agent can see. This message should:
- Be sent to the agent (not just displayed to the user)
- Inform the agent it is in a repetitive loop
- Encourage the agent to try a different approach
Example nudge: "You are in a repetitive loop. Try a different approach."
Config Design
Two new fields under agent in config.yaml, with corresponding environment variable overrides:
loopMsg (string, optional) — The nudge message to inject when a loop is detected. If omitted, use a sensible default.
loopLimit (number, optional, default: 5) — Maximum number of loop nudge messages to inject before stopping. After this limit, the system should stop injecting nudges (but may still detect loops).
- Env var:
AGENT_LOOP_LIMIT
Example config:
agent:
recursionLimit: 1000
autoContinueLimit: 1000
nodeTimeout: 600000
turnHashWindow: 20
turnBufferMax: 64
loopMsg: "You are in a repetitive loop. Try a different approach."
loopLimit: 5
Technical Notes
- Loop detection lives in
src/agent/react.js (turn hash tracking, checkTurnHash function around line 265)
- The
loop_detected event is emitted via callback({ type: "loop_detected" }) at line 269
- The TUI currently only handles this for display purposes (line 349-359 in
src/tui/app.js)
- The nudge should be injected into the conversation messages before the next agent turn, not just displayed in the UI
- Consider whether the nudge should be a
user message or a system message
- The
turnHashWindow and turnBufferMax are configurable via config.agent.turnHashWindow and config.agent.turnBufferMax
- Env var resolution follows the existing pattern in
src/config/loader.js — container keys like agent are dropped, so agent.loopMsg resolves to AGENT_LOOP_MSG
Decisions
- Nudge message is configurable: Yes, via
agent.loopMsg / AGENT_LOOP_MSG
- Max nudge count: Yes, via
agent.loopLimit / AGENT_LOOP_LIMIT, default 5
- Include repetition context in nudge: No
Summary
When the agent enters a repetitive loop, the system detects it via turn hash tracking but only displays a UI nudge ("You're looping.") to the user. The agent itself never receives feedback that it is stuck, so it continues looping.
Current Behavior
src/agent/react.jstracks turn hashes in a sliding window (default size 20)loop_detectedeventsrc/tui/app.js:349-359) handles this by appending "You're looping." to the last assistant message displayDesired Behavior
When a loop is detected, inject a nudge message into the conversation that the agent can see. This message should:
Example nudge: "You are in a repetitive loop. Try a different approach."
Config Design
Two new fields under
agentin config.yaml, with corresponding environment variable overrides:loopMsg(string, optional) — The nudge message to inject when a loop is detected. If omitted, use a sensible default.AGENT_LOOP_MSGloopLimit(number, optional, default: 5) — Maximum number of loop nudge messages to inject before stopping. After this limit, the system should stop injecting nudges (but may still detect loops).AGENT_LOOP_LIMITExample config:
Technical Notes
src/agent/react.js(turn hash tracking,checkTurnHashfunction around line 265)loop_detectedevent is emitted viacallback({ type: "loop_detected" })at line 269src/tui/app.js)usermessage or asystemmessageturnHashWindowandturnBufferMaxare configurable viaconfig.agent.turnHashWindowandconfig.agent.turnBufferMaxsrc/config/loader.js— container keys likeagentare dropped, soagent.loopMsgresolves toAGENT_LOOP_MSGDecisions
agent.loopMsg/AGENT_LOOP_MSGagent.loopLimit/AGENT_LOOP_LIMIT, default 5