feat: Enhance error handling with AgentErrorType and Exception tracking

This commit is contained in:
extio-de
2026-03-14 14:41:26 +01:00
parent b47380ec89
commit 0da1b3c78b
5 changed files with 133 additions and 10 deletions

View File

@@ -22,7 +22,9 @@ public final class AgentContext {
private volatile boolean streaming;
private volatile boolean error;
private volatile AgentErrorType errorType;
private volatile Exception errorException;
private volatile boolean skipNextCompletion;
@@ -74,7 +76,8 @@ public final class AgentContext {
this.requestStatistic = other.requestStatistic;
this.lastCompletion = other.lastCompletion;
this.agentContextUpdateConsumer = other.agentContextUpdateConsumer;
this.error = other.error;
this.errorType = other.errorType;
this.errorException = other.errorException;
this.skipNextCompletion = other.skipNextCompletion;
this.skipCache = other.skipCache;
this.streaming = other.streaming;
@@ -190,11 +193,29 @@ public final class AgentContext {
}
public boolean isError() {
return this.error;
return this.errorType != null;
}
public void setError(final boolean error) {
this.error = error;
public AgentErrorType getErrorType() {
return this.errorType;
}
public Exception getErrorException() {
return this.errorException;
}
public void setError(final AgentErrorType errorType, final Exception errorException) {
if (errorType == null) {
this.clearError();
return;
}
this.errorType = errorType;
this.errorException = errorException;
}
public void clearError() {
this.errorType = null;
this.errorException = null;
}
public boolean isSkipNextCompletion() {

View File

@@ -0,0 +1,6 @@
package de.extio.lmlib.agent;
public enum AgentErrorType {
PARSING,
GENERAL
}

View File

@@ -111,6 +111,8 @@ public class AgentExecutorService implements InitializingBean, DisposableBean {
}
catch (final Exception e) {
LOGGER.error("Error executing agent", e);
branchContext.setError(AgentErrorType.GENERAL, e);
responses.add(branchContext);
}
}, this.branchExecutorService));
}

View File

@@ -80,10 +80,18 @@ public interface BaseAgent {
final var splits = new ArrayList<Split>();
context.setNextAgent(null);
context.clearError();
this.preProcess(context);
if (context.getAgentContextUpdateConsumer() != null) {
context.getAgentContextUpdateConsumer().accept(context);
try {
this.preProcess(context);
if (context.getAgentContextUpdateConsumer() != null) {
context.getAgentContextUpdateConsumer().accept(context);
}
}
catch (final Exception ex) {
LOGGER.error("Error during agent execution", ex);
context.setError(AgentErrorType.GENERAL, ex);
return List.of(context);
}
splits.addAll(this.applyTemplate(context));
@@ -91,6 +99,7 @@ public interface BaseAgent {
for (final var split : splits) {
tasks.add(CompletableFuture.runAsync(() -> {
try {
split.context().clearError();
final boolean skipCompletion = split.context().isSkipNextCompletion() || this.agentType(split.context()) == AgentType.PROCESSING_ONLY;
if (skipCompletion) {
split.context().setSkipNextCompletion(false);
@@ -108,6 +117,7 @@ public interface BaseAgent {
final var conversation = this.setupConversation(split);
boolean parseable = false;
Exception parseException = null;
for (int i = 0; i < 2; i++) {
LOGGER.debug("Conversation: {}", conversation);
@@ -162,6 +172,7 @@ public interface BaseAgent {
break;
}
catch (final Exception e) {
parseException = e;
split.context().getGraph().add("⚠");
LOGGER.warn("{} Cannot parse response: {}", this.name(), completion.response(), e);
split.context().setSkipCache(true);
@@ -171,7 +182,7 @@ public interface BaseAgent {
if (!parseable) {
LOGGER.warn("{} Response is still not parseable after last attempt", this.name());
split.context().getGraph().add("☢");
split.context().setError(true);
split.context().setError(AgentErrorType.PARSING, parseException);
return;
}
}
@@ -183,7 +194,7 @@ public interface BaseAgent {
}
catch (final Exception ex) {
LOGGER.error("Error during agent execution", ex);
split.context().setError(true);
split.context().setError(AgentErrorType.GENERAL, ex);
}
}, agentExecutorService));
}