agentscope-ai / agentscope-ai/agentscope-java

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

Ouverte
#1,406 0 commentaires 0 réactions 0 personnes assignées Voir sur GitHub
area/core/agent bug
Langage dominant
Java
Étoiles
5.6k
Forks
1.3k
Merge moyen
4 j 12 h
PR mergées (30 j)
77

Description

# 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:

```java
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:

```java
ReActAgent agent = ReActAgent.builder()
// other builder config
.enablePendingToolRecovery(true)
.build();
```

2. Let the agent memory contain a pending tool call, for example pending ID `tool_call_1`.

3. 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`.

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

5. `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 `ToolResultBlock`s 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`:

```text
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`:

```java
m.hasContentBlocks(ToolResultBlock.class)
```

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

```java
Set pendingIds = findPendingToolUseIds(memory);
```

This can cause pending tool recovery to be skipped incorrectly.

Guide de contribution

Ouvrir le guide de contribution

Évaluation

Cette issue n'a pas encore été évaluée.

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.