Skip to content

feat(llmloop): add grace round after tool-request budget exhausted - #872

Merged
lizhengfeng101 merged 3 commits into
mainfrom
feat/grace-round-on-budget-exhausted
Aug 13, 2026
Merged

feat(llmloop): add grace round after tool-request budget exhausted#872
lizhengfeng101 merged 3 commits into
mainfrom
feat/grace-round-on-budget-exhausted

Conversation

@lizhengfeng101

Copy link
Copy Markdown
Collaborator

Summary

When the LLM tool-request budget (MaxToolRequestTimes) is exhausted during file review, the model may have identified issues but not yet submitted them via code_comment. Previously these findings were silently lost.

This PR adds a grace round: after the main loop exits on budget, one final LLM call is made with only code_comment and task_done available. The model can either submit pending findings or cleanly exit — preventing false-positive pressure since task_done provides an opt-out.

Changes

  • runGraceRound: new method on Runner that appends a budget-exhausted notice to the conversation and performs a single LLM call with restricted tools
  • graceRoundToolDefs: filters MainToolDefs to only code_comment + task_done
  • Token usage from the grace round is counted in the runner's totals
  • Only triggers on StopMaxRounds (not on empty-round or compression stops)

Test plan

  • go build ./... passes
  • go test ./... all green
  • Manual verification: set MAX_TOOL_REQUEST_TIMES to 3, confirmed grace round fires and comment is collected

When RunPerFile exits because MaxToolRequestTimes reaches zero, perform
one additional LLM call with only code_comment and task_done available.
This gives the model a final chance to submit findings it identified but
had not yet reported, preventing loss of review comments on budget stop.
@github-actions

github-actions Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

🔍 OpenCodeReview found 2 issue(s) in this PR.

  • ✅ Successfully posted inline: 2 comment(s)

Comment thread internal/llmloop/loop.go
Comment thread internal/llmloop/loop.go
- Check ctx.Err() before making the grace round LLM call to avoid
  wasted API calls when the context is already cancelled.
- Pass messages copy to AppendTaskRecord and call rec.SetResponse so
  the grace round interaction is visible in session/debug logs.
Cover three scenarios:
- Grace round fires and collects code_comment on budget exhaustion
- Grace round is skipped when context is already cancelled
- Grace round is NOT triggered on StopEmptyRounds
Comment thread internal/llmloop/loop.go
resp, err := r.deps.LLMClient.CompletionsWithCtx(ctx, llm.ChatRequest{
Model: r.deps.Model,
Messages: messages,
Tools: graceDefs,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restricting the tool list for this final call will likely cost us the whole KV cache prefix.

Placing the tool list in or next to the system prompt is the mainstream practice among current LLMs, precisely so that the prefix cache keeps hitting across a session. Swapping r.deps.MainToolDefs for the two-tool subset rewrites that part of the prefix, so everything behind it is invalidated.

The timing makes it expensive: runGraceRound only fires on StopMaxRounds, i.e. when the conversation has accumulated a full budget's worth of tool_result file contents and is at its longest. We re-read that prompt at full price and write a fresh cache entry that nothing downstream will ever read. The new totalCacheReadTokens/totalCacheWriteTokens counters should show it directly: read ≈ 0, write ≈ the whole prompt.

That said, there's a genuine trade-off here between effectiveness and cost. Narrowing the tool list is a hard constraint, whereas leaving MainToolDefs intact and relying on the prose instruction (optionally filtering resp.ToolCalls() on the response side) is only a soft one — the model could spend its last turn on a read tool. If the temporary override does measurably improve how often the grace round lands a real finding, then this may simply be a price we have to pay.

@lizhengfeng101
lizhengfeng101 merged commit da972b2 into main Aug 13, 2026
11 checks passed
@lizhengfeng101
lizhengfeng101 deleted the feat/grace-round-on-budget-exhausted branch August 13, 2026 07:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants