ClassNotFoundException when using `void` as return type on `@Action` method
I created a simple agent in Java:
import com.embabel.agent.api.annotation.AchievesGoal;
import com.embabel.agent.api.annotation.Action;
import com.embabel.agent.api.annotation.Agent;
import com.embabel.agent.api.common.Ai;
@Agent(description = "Course")
public class CourseAgent {
private final CourseRepository courseRepository;
public CourseAgent(CourseRepository courseRepository) {this.courseRepository = courseRepository;}
@Action
public MarketingText generateText(Course course, Ai ai) {
var prompt = """
Create a catching marketing text for the following sport course:
Type: %s, Level: %s, Duration: %s, Location: %s
""".formatted(
course.sport(), course.level(), course.durationInHours(), course.location());
return ai
.withDefaultLlm()
.createObject(prompt, MarketingText.class);
}
@AchievesGoal(description = "Generate a marketing text for a sport course")
@Action
public void updateCourseMarketingText(Course course, MarketingText marketingText) {
courseRepository.updateMarketingText(course.id(), marketingText.text());
}
}
It looks to me like the void combined with @AchievesGoal results in a class not found exception:
java.lang.ClassNotFoundException: void
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:580)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:490)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:467)
at java.base/java.lang.Class.forName(Class.java:458)
at com.embabel.agent.core.JvmType.clazz_delegate$lambda$1(JvmType.kt:57)
at kotlin.SynchronizedLazyImpl.getValue(LazyJVM.kt:74)
at com.embabel.agent.core.JvmType.getClazz(JvmType.kt:56)
at com.embabel.agent.core.JvmType.infoString(JvmType.kt:205)
at com.embabel.agent.core.AgentScope.infoString$lambda$8(AgentScope.kt:68)
at kotlin.text.StringsKt__AppendableKt.appendElement(Appendable.kt:85)
at kotlin.collections.CollectionsKt___CollectionsKt.joinTo(_Collections.kt:3490)
at kotlin.collections.CollectionsKt___CollectionsKt.joinToString(_Collections.kt:3507)
at kotlin.collections.CollectionsKt___CollectionsKt.joinToString$default(_Collections.kt:3506)
at com.embabel.agent.core.AgentScope.infoString(AgentScope.kt:68)
at com.embabel.agent.core.Agent.infoString(Agent.kt:112)
at com.embabel.common.core.types.HasInfoString.infoString$default(HasInfoString.kt:28)
at com.embabel.agent.core.Agent.getPlanningSystem(Agent.kt:101)
at com.embabel.agent.core.support.BlackboardWorldStateDeterminer.<init>(BlackboardWorldStateDeterminer.kt:38)
at com.embabel.agent.core.support.SimpleAgentProcess.<init>(SimpleAgentProcess.kt:54)
at com.embabel.agent.core.support.SimpleAgentProcess.<init>(SimpleAgentProcess.kt:30)
at com.embabel.agent.core.support.DefaultAgentPlatform.createAgentProcess(DefaultAgentPlatform.kt:173)
It is not a big deal since it can be prevented by using Void as a return type, but that feels a bit clunky.
Maybe the user experience can be improved a bit here?
Thank you for the report. Will look into it.
The AchievesGoal annotation works by looking at the return type of the goal action method. Otherwise it would be impossible to determine which was the goal type if there were >1 parameters to the goal action.
This would not be an issue for the new utility planning style, but might be problematic for GOAP usage where you expect a particular type from the agent.
Will investigate. The answer may be to flag this as an error if it's in a configuration that doesn't make sense.