Skip to content

fix(agents): swap edge order in singleRunStrategy for nodeSendToolResult#2175

Open
rainbow7 wants to merge 1 commit into
JetBrains:developfrom
rainbow7:fix/single-run-strategy-edge-order
Open

fix(agents): swap edge order in singleRunStrategy for nodeSendToolResult#2175
rainbow7 wants to merge 1 commit into
JetBrains:developfrom
rainbow7:fix/single-run-strategy-edge-order

Conversation

@rainbow7

Copy link
Copy Markdown

Problem

When an LLM returns both Text and ToolCall simultaneously in the same response (common behavior with DeepSeek, and some other models), the singleRunStrategy fails to execute the tool calls after receiving tool results. Instead, it treats the intermediate text as the final answer.

Root Cause

The edge order for nodeSendToolResult was:

edge(nodeSendToolResult forwardTo nodeFinish onTextMessage { true })     // first — matches Text
edge(nodeSendToolResult forwardTo nodeExecuteTool onToolCalls { true })  // second — never reached

Since resolveEdge evaluates edges in definition order (FIFO) and returns the first match, onTextMessage always wins when both Text and ToolCall are present.

Notably, the edges for nodeCallLLM (lines 35-36) already have the correct order with onToolCalls first. This inconsistency suggests the nodeSendToolResult order was unintentional.

Fix

Swap the two edges so onToolCalls is evaluated first (matching the nodeCallLLM pattern):

edge(nodeSendToolResult forwardTo nodeExecuteTool onToolCalls { true })  // first — execute tools
edge(nodeSendToolResult forwardTo nodeFinish onTextMessage { true })     // second — finish on pure text

Test

Added test_SingleRunStrategy_SecondRoundMixedResponse_ExecutesAllTools which reproduces the bug:

  • First round: LLM returns a tool call (no text) → tool executes ✅
  • Second round (after tool result): LLM returns Text + ToolCall simultaneously → before fix, tools were skipped; after fix, all tools execute ✅

This test fails without the fix and passes with it.

The edge order for nodeSendToolResult was:
  onTextMessage (first) → nodeFinish
  onToolCalls (second) → nodeExecuteTool

When an LLM returns both Text and ToolCall simultaneously (common with
DeepSeek and other models), the onTextMessage edge matched first,
causing the agent to return the intermediate text as the final answer
instead of executing the tool calls.

This fix swaps the order so onToolCalls is evaluated first, matching
the same pattern already used for nodeCallLLM edges above.

Added test: test_SingleRunStrategy_SecondRoundMixedResponse_ExecutesAllTools
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.

1 participant