-
Notifications
You must be signed in to change notification settings - Fork 259
Open
Description
Description
When a reactive stream is stuck (e.g., LLM timeout, network issue), calling interrupt() does not reset the running state, causing the Agent to be permanently stuck in "Agent is still running" state.
Root Cause
In AgentBase.java:
- The
runningAtomicBoolean is set totrueat the start ofcall()(line 163) - It's only reset to
falseindoFinally()(line 180) - When the reactive stream freezes (e.g., waiting for LLM response that never comes),
doFinally()is never called interrupt()only setsinterruptFlag, it does NOT resetrunning
// Line 163: Set running to true
if (!running.compareAndSet(false, true) && checkRunning) {
return Mono.error(new IllegalStateException("Agent is still running..."));
}
// Line 180: Only reset in doFinally - never called if stream is frozen
.doFinally(signalType -> running.set(false));
// Line 297-299: interrupt() only sets flag, doesn't reset running
public void interrupt() {
interruptFlag.set(true);
}Steps to Reproduce
- Start an agent request
- Let it get stuck waiting for LLM response (simulate with a very slow/unresponsive API)
- Call
agent.interrupt()to cancel - Try to send a new request
- Result: Error "Agent is still running, please wait for it to finish"
- Expected: Agent should be ready to accept new requests
Suggested Fix
Add a public method to force reset the running state:
/**
* Force reset the running state.
* Use when the reactive stream is stuck and doFinally() won't be called.
*/
public void forceResetRunningState() {
running.set(false);
resetInterruptFlag();
}Or alternatively, add an option to interrupt() to also reset running state:
public void interrupt(boolean forceReset) {
interruptFlag.set(true);
if (forceReset) {
running.set(false);
}
}Workaround
Currently using reflection to reset the running state:
private void forceResetAgentRunningState(ReActAgent agent) {
try {
Class<?> agentBaseClass = agent.getClass();
while (agentBaseClass != null && !agentBaseClass.getName().endsWith("AgentBase")) {
agentBaseClass = agentBaseClass.getSuperclass();
}
if (agentBaseClass != null) {
Field runningField = agentBaseClass.getDeclaredField("running");
runningField.setAccessible(true);
AtomicBoolean running = (AtomicBoolean) runningField.get(agent);
running.set(false);
}
} catch (Exception e) {
// Handle error
}
}Environment
- agentscope-java version: latest main branch
- Java version: 21
Metadata
Metadata
Assignees
Labels
No labels
Type
Projects
Status
Backlog