Cap chat iterations at 12 with graceful fallback (closes #84)#87
Open
vahid-ahmadi wants to merge 1 commit into
Open
Cap chat iterations at 12 with graceful fallback (closes #84)#87vahid-ahmadi wants to merge 1 commit into
vahid-ahmadi wants to merge 1 commit into
Conversation
The chat loop previously allowed up to 60 tool-use iterations, which let a stuck agent burn through the Vercel proxy timeout without ever emitting a final assistant message — surfacing as "Failed to fetch" in the UI. Now the loop caps at 12 iterations. When the cap is hit we emit a user-facing fallback chunk that summarises what was tried (tool counts + last tool error, kept short) and offers next steps (rephrase, enable Plan mode, or try a more specific scenario), then close the stream with a `done` event whose `stop_reason` is `iteration_cap`. Natural convergence is unchanged. Also adds per-session log lines for both convergence and cap-hit so we can see in metrics how often this fires. Closes #84 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Beta preview is ready.
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
chat_message'sgenerate_streamloop. Twelve givesrun_pythonenough rope to converge on real multi-step questions (capabilities check → simulation → reform → comparison → write-up) without leaving room for a stuck agent to silently exhaust the Vercel proxy timeout.chunkevent followed by adoneevent withstop_reason: "iteration_cap". Previously the cap branch emitted only*[Reached maximum iterations]*and adoneevent with nostop_reason, which often raced the Vercel proxy timeout and surfaced as "Failed to fetch".[CHAT] Session …: converged at N iterationsand[CHAT] Session …: iteration cap hit at N iterations — tool_counts={…}log lines so we can track convergence rates and cap-hit frequency in metrics.Exact fallback message
The
chunkevent payload (with leading newlines so it appends cleanly to any prior text):The error clause is dropped if no tool error was captured; the tool list reads "didn't complete any tool calls" if the cap was hit before any tool ran (rare — mostly indicates a runaway text generation loop).
Continue-turn budget decision
The "continue" affordance in the frontend (
ChatPage.tsx#continueMessage) re-sends the full conversation (including the partial assistant message and prior tool transcripts) to/chat/message. It therefore re-entersgenerate_streamwith a fresh 12-iteration budget — we don't track or thread per-turn budget across requests. Rationale:This is documented in the comment above the
MAX_ITERATIONSconstant.Plan mode
Plan mode omits tools from the Anthropic request, so it always exits the loop on iteration 1 (
not tool_usestriggers the natural-completion branch). No separate plan-mode cap is needed.Test plan
python -c "import ast; ast.parse(open('backend/routes/chatbot.py').read())"— passes locally.StructuralReformwith deliberately ambiguous parameters) and confirm the fallback message renders and the stream closes cleanly withstop_reason: "iteration_cap"in thedoneevent.converged at N/iteration cap hit at Nlines.Closes #84
Generated with Claude Code