Skip to content

[Bug]: PendingToolRecoveryHook skips recovery when input contains unrelated ToolResultBlock IDs #1406

@dragondyt

Description

@dragondyt

PendingToolRecoveryHook skips recovery when input contains unrelated ToolResultBlock IDs

Describe the bug

PendingToolRecoveryHook treats any incoming ToolResultBlock as user-provided tool results, without checking whether the tool result IDs match the current pending tool call IDs.

In PendingToolRecoveryHook.handlePreCall, the current logic only checks whether any ToolResultBlock exists:

boolean userProvidedResults =
        inputMessages.stream().anyMatch(m -> m.hasContentBlocks(ToolResultBlock.class));
if (userProvidedResults) {
    return Mono.just(event);
}

This means that if the input contains a ToolResultBlock with an unrelated, stale, or invalid ID, the hook skips auto-recovery even though the actual pending tool calls are still unresolved.

Later, ReActAgent#doCall validates the provided tool result IDs against pendingIds and may throw an exception, instead of letting PendingToolRecoveryHook recover the real pending calls.

To Reproduce

  1. Enable pending tool recovery:
ReActAgent agent = ReActAgent.builder()
        // other builder config
        .enablePendingToolRecovery(true)
        .build();
  1. Let the agent memory contain a pending tool call, for example pending ID tool_call_1.

  2. Call the agent with an input message that contains a ToolResultBlock, but its ID does not match the pending tool call ID, for example tool_call_old.

  3. PendingToolRecoveryHook sees that a ToolResultBlock exists and returns without patching tool_call_1.

  4. ReActAgent#doCall then validates the result IDs and fails because tool_call_old is not in pendingIds.

Expected behavior

PendingToolRecoveryHook should check the IDs of incoming ToolResultBlocks against pendingIds.

It should only treat input tool results as user-provided results for the current pending calls when their IDs match the current pending tool call IDs.

For example, the hook could collect provided result IDs and compare them with pendingIds before deciding whether to skip auto-recovery.

Error messages

Possible error from ReActAgent#doCall / validateAndAddToolResults:

Invalid tool result IDs: [tool_call_old]. Expected: [tool_call_1]

Environment

  • AgentScope-Java Version: [please fill in]
  • Java Version: [please fill in]
  • OS: Windows

Additional context

The current implementation checks only for the existence of ToolResultBlock:

m.hasContentBlocks(ToolResultBlock.class)

but it does not check whether those ToolResultBlock IDs are related to the pending tool calls found by:

Set<String> pendingIds = findPendingToolUseIds(memory);

This can cause pending tool recovery to be skipped incorrectly.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    In progress

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions