agentscope-ai / agentscope-ai/agentscope-java

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

オープン
#1,406 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る
area/core/agent bug
主要言語
Java
スター
5.6k
フォーク
1.3k
平均マージ
4日 12時間
マージ済み PR(30日)
77

説明

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

コントリビューションガイド

コントリビューションガイドを開く

評価

この issue はまだ評価されていません。

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。