fix(agent): answer sibling tool calls when the exit validator rejects finish - #70
Merged
Merged
Conversation
process_tool_results returned as soon as a rejected finish set skip_call, before the loop that records tool_result observations for any other tool calls made in the same assistant turn. Those siblings had already run (their output sat in tool_results), so the next prompt rebuild carried tool_use ids the API never saw answered, and Anthropic's messages API rejected the whole request. Only a genuine completion (task_complete) should skip the loop; a rejected finish must fall through so siblings still get recorded.
wolfy-j
force-pushed
the
fix/exit-validation-sibling-tool-results
branch
from
August 10, 2026 21:34
a88a707 to
5723b80
Compare
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.
Symptom
When an assistant turn contains the
finishexit call plus other tool calls (e.g. parallel KB searches), andarena_config.exit_func_idrejects the finish (missing declared outputs), the workflow permanently stalls on the next iteration with:Observed in production: a digest whose exit validator enforces complete outputs failed every scheduled run for four days with exactly this error.
Root cause
node/agent/node.lua,process_tool_results: on validator rejection the code records the rejection observation, setsskip_call = true, and returns early viaif task_complete or skip_call then return ... end— skipping the loop below that recordstool_resultobservations for the sibling tool calls in the same turn. Those siblings already executed (their output sits intool_results); they only lack recorded observations. The next prompt rebuild therefore carries orphanedtool_useblocks and the LLM provider rejects the whole request.Fix
Drop
skip_call; gate the early return ontask_completealone, so a rejected finish falls through into the existing sibling-observation loop. The loop already no-ops for the exit call itself (it is never intool_results—split_exit_tool_callskeeps it out ofexecute_tools), so nothing is double-recorded, and the genuine-completion path is unchanged.Tests
process_tool_resultsexposed via the existing_testtable; newprocess_tool_results_test.luawith a stub always-rejecting exit validator:task_complete == false;exit_func_id) → early return, sibling results untouched.Full suite: 952 passed.