Bug
When a user sends a new message while the agent is processing a long-running tool call (e.g., a terminal command), the gateway enters an infinite recursion loop that spams the user with repeated (No response generated)\n---\n[Interrupted - processing your new message] messages on Telegram.
Reproduction
- Send a message to the Telegram bot that triggers a long-running tool call (e.g., a command that takes 10+ seconds)
- While the agent is processing, send a second message like "whats happening"
- The bot starts spamming
(No response generated) --- [Interrupted - processing your new message] indefinitely
Root Cause
Two bugs in the interrupt handling create an infinite loop:
Bug 1: get_pending_message uses .get() instead of .pop() (gateway/platforms/base.py:289)
def get_pending_message(self, session_key: str) -> Optional[MessageEvent]:
"""Get and clear any pending message for a session."""
return self._pending_messages.get(session_key) # ← never actually clears!
The docstring says "Get and clear" but it only gets — the pending message stays in the dict forever.
Bug 2: _active_sessions interrupt Event is never reset (gateway/platforms/base.py:213)
When a new message arrives during processing, _active_sessions[chat_id].set() is called but the Event is never cleared between recursive _run_agent calls. Since has_pending_interrupt() checks _active_sessions[session_key].is_set(), it returns True on every subsequent check.
The Loop
1. User sends "whats happening" during processing
2. Adapter stores in _pending_messages[chat_id], sets _active_sessions[chat_id].set()
3. monitor_for_interrupt detects it → calls agent.interrupt()
4. Agent breaks out → final_response = None → "(No response generated)"
5. run.py:567 calls adapter.get_pending_message(chat_id) → returns event
⚠ Message stays in _pending_messages (.get not .pop)
6. Sends "(No response generated)\n---\n[Interrupted]" to Telegram
7. Recursively calls _run_agent("whats happening")
8. New monitor_for_interrupt starts → has_pending_interrupt still True!
9. Immediately interrupts new agent before it makes any API call
10. GOTO step 4 — infinite loop, each iteration sends a Telegram message
Proposed Fix
gateway/platforms/base.py:289 — use .pop():
def get_pending_message(self, session_key: str) -> Optional[MessageEvent]:
"""Get and clear any pending message for a session."""
return self._pending_messages.pop(session_key, None)
gateway/run.py — clear the adapter's interrupt state before recursing into _run_agent:
# After getting the pending message, clear interrupt state
if pending:
# Clear the interrupt event so the next _run_agent call doesn't immediately re-trigger
if hasattr(adapter, '_active_sessions') and source.chat_id in adapter._active_sessions:
adapter._active_sessions[source.chat_id].clear()
Affected Files
gateway/platforms/base.py — get_pending_message(), handle_message()
gateway/run.py — _run_agent() interrupt handling and recursive call (lines 560-592)
Impact
Every interrupt during a long tool call triggers an infinite message spam to the user's Telegram chat. The only way to stop it is to kill the gateway process.
Bug
When a user sends a new message while the agent is processing a long-running tool call (e.g., a terminal command), the gateway enters an infinite recursion loop that spams the user with repeated
(No response generated)\n---\n[Interrupted - processing your new message]messages on Telegram.Reproduction
(No response generated) --- [Interrupted - processing your new message]indefinitelyRoot Cause
Two bugs in the interrupt handling create an infinite loop:
Bug 1:
get_pending_messageuses.get()instead of.pop()(gateway/platforms/base.py:289)The docstring says "Get and clear" but it only gets — the pending message stays in the dict forever.
Bug 2:
_active_sessionsinterrupt Event is never reset (gateway/platforms/base.py:213)When a new message arrives during processing,
_active_sessions[chat_id].set()is called but the Event is never cleared between recursive_run_agentcalls. Sincehas_pending_interrupt()checks_active_sessions[session_key].is_set(), it returnsTrueon every subsequent check.The Loop
Proposed Fix
gateway/platforms/base.py:289— use.pop():gateway/run.py— clear the adapter's interrupt state before recursing into_run_agent:Affected Files
gateway/platforms/base.py—get_pending_message(),handle_message()gateway/run.py—_run_agent()interrupt handling and recursive call (lines 560-592)Impact
Every interrupt during a long tool call triggers an infinite message spam to the user's Telegram chat. The only way to stop it is to kill the gateway process.