Follow-up to #38 (which removes the trigger, not the loop shape).
When Ash's Bedrock stream stopped on </function_calls> with stopSequence missing (#38), the turn entered a continuation loop: each round re-sent ~172k input tokens, generated ~6 output tokens (\n</function_calls> — the model correctly closing the dangling block), advanced the accumulated text by 1 char, and repeated. 43 rounds in 17 minutes, ~7M input tokens, zero progress, no cap, no backoff, no operator signal. On an uncached substrate that's real money ($75/hr) burning silently — it only stopped because a human noticed the agent "seemed slow."
Any future trigger with the same shape (a stop that the tool gate doesn't recognize, an unclosed block, a model that deterministically re-emits the same stop) re-opens the same failure.
Proposed guards (defense in depth, any subset):
- No-progress abort: if a continuation round adds fewer than N chars (say 16) to the accumulated text and stops on the same stop sequence as the previous round, abort the turn with a distinct stop reason instead of continuing.
- Round cap for prefill continuation rounds per turn (native tools already effectively bound this via tool depth).
- Telemetry: log a warning with round count + input tokens when rounds exceed ~5, so a spin is visible in service logs before the bill is.
Observed-live details in #38's description and the keep ops notes (2026-07-26).
🤖 Generated with Claude Code
Follow-up to #38 (which removes the trigger, not the loop shape).
When Ash's Bedrock stream stopped on
</function_calls>withstopSequencemissing (#38), the turn entered a continuation loop: each round re-sent ~172k input tokens, generated ~6 output tokens (\n</function_calls>— the model correctly closing the dangling block), advanced the accumulated text by1 char, and repeated. 43 rounds in 17 minutes, ~7M input tokens, zero progress, no cap, no backoff, no operator signal. On an uncached substrate that's real money ($75/hr) burning silently — it only stopped because a human noticed the agent "seemed slow."Any future trigger with the same shape (a stop that the tool gate doesn't recognize, an unclosed block, a model that deterministically re-emits the same stop) re-opens the same failure.
Proposed guards (defense in depth, any subset):
Observed-live details in #38's description and the keep ops notes (2026-07-26).
🤖 Generated with Claude Code