How Goals and the @AchievesGoal Annotation Function in Embabel
The @AchievesGoal annotation marks @Action methods as goal producers in Embabel, automatically converting method metadata into Goal objects that the runtime matches against user requests based on description, tags, and examples.
The embabel/embabel-agent repository implements a goal-oriented agent framework where the @AchievesGoal annotation transforms regular Java methods into trackable, selectable goals. When applied to methods also marked with @Action, this annotation captures metadata—such as description, utility value, and capability tags—that the Embabel runtime uses to construct Goal instances. Understanding how this annotation interacts with the core Goal class is essential for building agents that can autonomously select and execute the right capabilities based on natural language input.
Understanding the @AchievesGoal Annotation
The @AchievesGoal annotation, defined in embabel-agent-api/src/main/java/com/embabel/agent/api/annotation/AchievesGoal.java, serves as the bridge between developer-defined actions and the Embabel goal-selection engine. It decorates methods that produce tangible outcomes the agent can pursue to satisfy user requests.
Core Attributes and Metadata
Each attribute in the annotation maps directly to fields within the Goal class (com.embabel.agent.core.Goal):
- description: Human-readable explanation of what the goal accomplishes, used by the matching engine to understand intent.
- value: Numeric utility score (e.g.,
5.0) that influences priority when multiple goals could satisfy a request. - tags: String array categorizing capabilities (e.g.,
{"cooking", "recipes"}) for filtering by domain. - examples: Sample user utterances that should trigger this goal, improving the language model’s ability to map natural language to the goal.
- export: Configures whether the goal generates a remote tool via the nested
@Exportannotation.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface AchievesGoal {
String description();
double value() default 0.0;
String[] tags() default {};
String[] examples() default {};
Export export() default @Export(enabled = false);
}
The Goal Class Lifecycle
The lifecycle of a goal in Embabel follows a strict path from method discovery to execution, managed by the core runtime in embabel-agent-core.
Goal Construction and Discovery
At startup, Embabel scans the classpath for methods annotated with both @Action and @AchievesGoal. For each discovered method, the runtime instantiates a Goal object in embabel-agent-core/src/main/java/com/embabel/agent/core/Goal.java, populating it with the annotation's metadata plus optional cost data from the @Cost annotation if present. The constructor validates that the annotated method has a non-void return type; if the method returns void, the startup sequence fails with an exception, as verified by VoidAchievesGoalJavaTest.
// Valid goal construction
@Action
@AchievesGoal(
description = "Find a recipe for a requested dish",
tags = {"cooking", "recipes"},
examples = {"I need a recipe for lasagna"}
)
public String findRecipe(String dish) {
return "Recipe for " + dish;
}
Goal Matching and Execution
Once constructed, goals enter the matching phase implemented in GoalMatcher.java (com.embabel.agent.core.GoalMatcher). This engine compares incoming user requests against each Goal instance's description, tags, and examples fields to calculate relevance scores. The highest-scoring goal wins execution.
Upon selection, the Embabel runtime invokes the associated method and attaches the return value to the Goal object's result field. If export is enabled, the system additionally exposes the goal as a remote tool through Embabel's tool generation framework.
Practical Implementation Examples
The following patterns demonstrate correct usage of @AchievesGoal for different scenarios.
Basic Goal with Metadata
public class RecipeSkill {
@Action
@AchievesGoal(
description = "Find a recipe for a requested dish",
tags = {"cooking", "recipes"},
examples = {"I need a recipe for lasagna", "How do I bake a cake?"}
)
public String findRecipe(String dish) {
// Logic to retrieve recipe
return "Here is a recipe for " + dish;
}
}
High-Value Goal with Remote Export
public class BillingSkill {
@Action
@AchievesGoal(
description = "Create an invoice for a customer",
value = 5.0,
tags = {"billing", "finance"},
examples = {"Generate an invoice for client X"},
export = @Export(enabled = true)
)
public Invoice createInvoice(Customer cust, double amount) {
return new Invoice(cust, amount);
}
}
Invalid Void Return Pattern
public class InvalidGoal {
@Action
@AchievesGoal(description = "Do something but return nothing")
public void doNothing() {
// Startup error: goals must return a value
}
}
Source Code Architecture
The implementation spans the embabel-agent-api and embabel-agent-core modules:
AchievesGoal.java(com.embabel.agent.api.annotation): Defines the annotation interface with attributes for description, value, tags, examples, and export configuration.Goal.java(com.embabel.agent.core): Core entity class that stores metadata, execution state, timestamps, and method results.GoalMatcher.java(com.embabel.agent.core): Implements the matching logic that scores goals against user requests.Action.java(com.embabel.agent.api.annotation): Required companion annotation that marks methods as Embabel actions.VoidAchievesGoalJavaTest: Validates that methods returning void trigger initialization failures.
Summary
- The
@AchievesGoalannotation converts@Actionmethods into searchable goals by binding method metadata toGoalinstances. - Goals require non-void return types; void methods cause startup exceptions per
VoidAchievesGoalJavaTest. - The
GoalMatcherengine selects goals by comparing user input againstdescription,tags, andexamplesfields. - Setting
export = @Export(enabled = true)exposes goals as remote tools for external agent integration. - Core implementation resides in
embabel-agent-api(annotation) andembabel-agent-core(runtime logic).
Frequently Asked Questions
What happens if a method annotated with @AchievesGoal returns void?
The Embabel runtime detects void return types during the discovery phase and throws an exception at startup. The test class VoidAchievesGoalJavaTest explicitly verifies this validation behavior, ensuring all goals produce tangible results.
How does Embabel match user requests to specific goals?
The GoalMatcher class in com.embabel.agent.core implements the matching algorithm, scoring each Goal instance against the incoming request text using the description, tags, and examples metadata fields. The goal with the highest relevance score receives execution priority.
Can @AchievesGoal methods be exposed as external tools?
Yes. By setting the export attribute to @Export(enabled = true), the goal becomes available as a remote tool. This generates the necessary scaffolding for external agents or APIs to invoke the method through Embabel's tool interface.
Where is the Goal class defined in the Embabel source code?
The Goal class is defined in embabel-agent-core/src/main/java/com/embabel/agent/core/Goal.java within the com.embabel.agent.core package. It encapsulates all metadata from the @AchievesGoal annotation plus runtime state such as execution status, timestamps, and optional cost data from the @Cost annotation.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →