agentscope-ai / agentscope-ai/agentscope-java

[Feature]: **Title**: `BaseReActAgentRunner.stream()` returns deprecated coarse-grained `Flux<Event>` and does not surface the fine-grained `AgentEvent` stream **Labels**: `bug` / `enhancement` / `a2a`

Abierto
#2,552 1 comentario 0 reacciones 0 asignados Ver en GitHub
area/build area/core/agent area/core/tool area/ext/integration enhancement
Lenguaje dominante
Java
Estrellas
5.6k
Forks
1.3k
Merge medio
4 d 12 h
PR fusionados (30 d)
77

Descripción

## Description

The A2A server's `BaseReActAgentRunner.stream(...)` currently delegates to the **deprecated** `ReActAgent.stream(List)` which returns `Flux` (the coarse-grained v1 event type). As a result, A2A sub-agents cannot emit / consume the fine-grained `AgentEvent` hierarchy (`Flux`) that covers the full agent lifecycle (reasoning chunks, tool calls/results, HITL `RequireUserConfirmEvent`, `AgentResultEvent`, etc.).

### Location

`agentscope-extensions/.../a2a/.../server/executor/runner/BaseReActAgentRunner.java`

```java
@Override
public Flux stream(List requestMessages, AgentRequestOptions options) {
...
ReActAgent agent = buildReActAgent();
agentCache.put(options.getTaskId(), agent);
return agent.stream(requestMessages) // <-- deprecated coarse-grained API
.doFinally(signal -> agentCache.remove(options.getTaskId()));
}
```

`ReActAgent` itself already provides the replacement API:

- `Flux stream(...)` — `@Deprecated(since = "2.0.0", forRemoval = true)`
- `Flux streamEvents(List)` / `streamEvents(List, RuntimeContext)` — the recommended fine-grained stream

### Impact / Why it matters

1. **Lost observability & control**: `AgentEvent` carries the full lifecycle (reasoning chunks, tool invocations, `RequireUserConfirmEvent` for human-in-the-loop, final `AgentResultEvent`). With only `Flux`, A2A handlers (e.g. `AgentScopeAgentExecutor`'s streaming/blocking `FluxEventHandler`) cannot distinguish event semantics reliably and must rely on the legacy `EventType` mapping.
2. **HITL breakage**: When a tool requires confirmation, the fine-grained `RequireUserConfirmEvent` is the only typed signal. The coarse `Event` stream does not expose it cleanly, so A2A callers cannot implement human-in-the-loop approval flows properly.
3. **Forward-compat**: `stream(...)` is marked `forRemoval = true`, so this runner will break once it is removed.

### Proposed fix

Make `BaseReActAgentRunner` (or its `AgentRunner` contract) support `AgentEvent`, e.g.:

```java
@Override
public Flux streamEvents(List requestMessages, AgentRequestOptions options) {
if (agentCache.containsKey(options.getTaskId())) {
throw new IllegalStateException("Agent already exists for taskId: " + options.getTaskId());
}
ReActAgent agent = buildReActAgent();
agentCache.put(options.getTaskId(), agent);
return agent.streamEvents(requestMessages) // fine-grained, full lifecycle
.doFinally(signal -> agentCache.remove(options.getTaskId()));
}
```

and optionally keep a backward-compatible `stream(...)` that adapts `AgentEvent` → `Event` for callers still on the v1 API.

### Environment

- agentscope-java (agentscope-examples/boba-tea-shop A2A setup)
- ReActAgent `streamEvents` available since 2.0.0; `stream(...)` deprecated for removal.

### Reproduction (conceptual)

1. Implement an `AgentRunner` extending `BaseReActAgentRunner`.
2. Subscribe to `runner.stream(msgs, options)`.
3. Observe that emitted elements are `io.agentscope.core.agent.Event`, never `io.agentscope.core.event.AgentEvent` — so lifecycle/HITL events are unavailable to the A2A executor.

Guía de contribución

Abrir la guía de contribución

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.