fix: only suppress auto-append when caller explicitly provides a tool result#1541
Closed
Echolonius wants to merge 1 commit into
Closed
fix: only suppress auto-append when caller explicitly provides a tool result#1541Echolonius wants to merge 1 commit into
Echolonius wants to merge 1 commit into
Conversation
… result Previously, any call to append_messages() — even adding a plain user instruction like "be concise" — set _messages_modified=True, which told the runner to skip its own auto-append of the assistant message and tool result. The next iteration would send a request with no tool result in history, Claude would see the original question unanswered, re-issue the same tool call, and the loop would never terminate. The fix makes the flag conditional: _messages_modified is only set when at least one appended message contains a tool_result content block — the clear signal that the caller is handling the tool result themselves. Appending other messages (extra instructions, context, etc.) leaves the flag untouched and the loop continues correctly. This also aligns with the inconsistency noted in the docs: the "Advanced usage" example appends a user message without a tool result, while the "Modifying tool results" example correctly passes both the assistant message and tool result together. After this fix, both patterns work. Fixes anthropics#1536.
Author
|
Closing in favour of #1538 by @Zelys-DFKH, which was submitted earlier and addresses both failure modes more completely — including the case where a manually-provided I should have checked for open PRs against this issue before opening a duplicate. Apologies for the noise. |
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
Fixes #1536.
Calling
runner.append_messages()with a plain user message inside the tool runner loop caused an infinite loop. Any call toappend_messages()unconditionally set_messages_modified = True, which the runner interpreted as the caller manually handling the tool result. It would skip its own auto-append of the assistant message and tool result, so the next iteration sent a request with no tool result in history — Claude saw the original question unanswered, re-issued the same tool call, and the loop never terminated.Root cause
_messages_modifiedwas serving two distinct purposes with no way to tell them apart:append_messages({"role": "user", "content": "be concise"})) — runner should still auto-append the tool resultappend_messages(assistant_msg, tool_result_msg)) — runner should skip auto-appendBoth paths set the flag, so the runner always skipped auto-append regardless of intent.
Fix
_messages_modifiedis now only set when at least one of the appended messages contains atool_resultcontent block — the unambiguous signal that the caller is handling the tool result themselves. Appending messages without tool results leaves the flag untouched and the loop continues correctly.What this affects
BetaToolRunner) ✅BetaAsyncToolRunner) ✅ — both share the sameappend_messages()on the base classset_messages_params()is unaffected — it never touches the flagTests
Added
test_append_messages_non_tool_result_does_not_suppress_auto_append— a pure unit test (no API calls required) that directly asserts the flag behaviour for both the plain-message case and the tool-result case.The existing
test_custom_message_handling(markedxfail) is a related but separate issue and remains untouched.