Skip to content

Commit 4b057b3

Browse files
metiu1claude
andcommitted
Fix agentic tool loop: force final answer, raise round cap
Small models could call tools repeatedly and never produce a final response (empty answer). Now the last tool round omits tools so the model must answer, and the round cap is raised 5→8. Verified: agent calls list_directory and finalizes with a correct answer. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent b356b15 commit 4b057b3

1 file changed

Lines changed: 5 additions & 2 deletions

File tree

vortelio/internal/runtime/llm_runner.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,8 +1088,11 @@ func (r *LLMRunner) StreamWithOpts(sopts StreamOpts, emit func(string), toolEmit
10881088
effectiveEmit = splitter.feed
10891089
}
10901090

1091-
maxToolRounds := 5
1091+
maxToolRounds := 8
10921092
for round := 0; round < maxToolRounds; round++ {
1093+
// On the final round, force a text answer (no tools) so the model can't
1094+
// keep calling tools forever and return an empty response.
1095+
lastRound := round == maxToolRounds-1
10931096
payload := map[string]interface{}{
10941097
"model": "local",
10951098
"messages": messages,
@@ -1152,7 +1155,7 @@ func (r *LLMRunner) StreamWithOpts(sopts StreamOpts, emit func(string), toolEmit
11521155
payload["tools"] = clientTools
11531156
payload["tool_choice"] = "auto"
11541157
}
1155-
} else if sopts.ToolsEnabled {
1158+
} else if sopts.ToolsEnabled && !lastRound {
11561159
// Server-side tools via the request's provider (defaults to builtins).
11571160
tp := sopts.ToolProvider
11581161
if tp == nil {

0 commit comments

Comments
 (0)