Repository navigation
fix(llm): keep parallel tool results contiguous for OpenAI-compatible providers - #220
Open
macrocrazier wants to merge 1 commit into
Open
macrocrazier wants to merge 1 commit into
macrocrazier wants to merge 1 commit into
Conversation
… providers
With the "human" image carrier, each screenshot result is a ToolMessage
followed by a HumanMessage holding the image. Agent loops append results
once per tool call, so a parallel batch becomes Tool, Human, Tool, ...
OpenAI-compatible APIs require all tool results to directly follow the
assistant turn and reject that history with a 400 ("tool_call_ids did not
have response messages").
Reorder each tool batch to ToolMessages first, then the image carriers in
their original order, in RobustChatModelWrapper._traced_call so every
agent loop is covered.
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.
Problem
With an OpenAI-compatible model (
provider: "openai"), any agent turn that makes two or more tool calls, where at least one returns a screenshot, fails with:A typical trigger is a Checker turn that calls
get_step_screenshotthree times plusprobe_deviceonce.Cause
For providers that reject images inside tool messages,
tool_result_messages()returns the textualToolMessagefollowed by aHumanMessagecarrying the image (the"human"image carrier). The agent loops extend history once per tool call, so a parallel batch becomes:OpenAI requires every tool result to directly follow the assistant turn. The first interleaved
HumanMessageends that run, so calls 2–4 count as unanswered. Gemini and Anthropic use the"tool"carrier and never hit this.The same per-call pattern exists in the Checker, Operator, Flash runner, Outputter, Diagnoser, HistoryAnalyzer and committee loops.
Fix
order_tool_batch_messages()inartemis/tools/tool_wrapper.py: after each tool-callingAIMessage, emit that turn'sToolMessages first, then the image-carrierHumanMessages in their original order. Valid histories come back unchanged.RobustChatModelWrapper._traced_call, whichainvoke,completeandastreamall go through. This covers every loop above without touching each call site.Tests
Added to
tests/unit/tools/history/test_result_messages.py:I also confirmed it against a live OpenAI-compatible endpoint: the interleaved order returns 400, and the reordered order returns 200.
make test: no new failures compared withmain.mainitself currently has 80 failures withoutGOOGLE_API_KEYset.make lintandmake typecheckpass.