agentscope-ai / agentscope-ai/agentscope-java

[Bug]:ToolResultEvictionMiddleware does not evict

未關閉
#1,695 0 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
area/core/agent bug
主要語言
Java
星號
5.6k
分支
1.3k
平均合併
4 天 12 小時
30 天內合併 PR
77

描述

# Bug: ToolResultEvictionMiddleware does not evict — `doOnComplete` fires before tool results are written to context

## Problem

`ToolResultEvictionMiddleware` never evicts oversized tool results. The `evictAddedToolResults()` callback always finds zero new messages and exits immediately.

## Root Cause

The `onActing` middleware hook wraps only `actingStream()`, which emits streaming events (`ToolResultEndEvent`, etc.) but does **not** write results to `AgentState.contextMutable()`.

Tool result messages are written to context in `notifyPostActingHook()` — which is called in `acting()`'s outer `.flatMap()`, **after** the middleware chain has already completed.

Execution order:

```
actingStream() Flux completes
→ doOnComplete(() -> evictAddedToolResults()) fires ← eviction runs HERE
→ contextMutable()[sizeBefore..end] is EMPTY ← nothing to evict
→ (outer flatMap) notifyPostActingHook() ← results written HERE (too late)
→ state.contextMutable().add(resultMsg)
```

Relevant lines in `ReActAgent.java`:
- **2129–2138**: middleware chain wraps only `actingCore = actingStream()`
- **2173–2174**: `notifyPostActingHook()` called outside the middleware chain
- **2728–2729**: `state.contextMutable().add(resultMsg)` — actual write point

## Fix Suggestion

Bring `notifyPostActingHook()` inside the middleware-wrapped scope so that tool results are in `contextMutable()` before the `onActing` Flux completes.

**Option A (minimal):** Extend `actingCore` to include the post-acting context write, then remove the duplicate call from the outer `flatMap`:

```java
Function> actingCore = ai ->
actingStream(ai.toolCalls(), replyId, resultHolder)
.thenMany(
Mono.defer(() -> Flux.fromIterable(resultHolder.get())
.concatMap(this::notifyPostActingHook)
.then(Mono.empty())));
```

**Option B (alternative):** Move eviction to the `onReasoning` hook's pre-step — check `contextMutable()` for oversized TOOL messages at the start of each reasoning round, before building the prompt. This avoids restructuring `actingCore` entirely.

貢獻指南

開啟貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。