CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-com-embabel-agent--embabel-agent-api

Fluent DSL and Kotlin DSL for building autonomous agents with planning capabilities on the JVM, featuring annotation-based and programmatic configuration for agentic flows with Spring Boot integration

Overview
Eval results
Files

agent-definition.mddocs/

Agent Definition

Agent definition in Embabel provides two approaches: annotation-based configuration (similar to Spring MVC) and an idiomatic Kotlin DSL. Both approaches offer full type safety and refactoring support.

Capabilities

Annotation-Based Agent Definition

Define agents by annotating classes with @Agent and methods with action/condition annotations.

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class Agent(
    val name: String = "",
    val provider: String = "",
    val description: String,
    val version: String = DEFAULT_VERSION,
    val planner: PlannerType = PlannerType.GOAP,
    val scan: Boolean = true,
    val beanName: String = "",  // Note: Uses @get:AliasFor annotation for Spring bean name aliasing
    val opaque: Boolean = false,
    val actionRetryPolicy: ActionRetryPolicy = ActionRetryPolicy.DEFAULT,
    val actionRetryPolicyExpression: String = ""
)

Usage Example (Kotlin):

@Agent(
    name = "order-processor",
    provider = "ecommerce",
    description = "Processes customer orders and manages fulfillment",
    version = "1.0.0",
    planner = PlannerType.GOAP
)
class OrderProcessorAgent {

    @Action(description = "Validate order contents")
    fun validateOrder(order: Order): ValidationResult {
        return validator.validate(order)
    }

    @Action(
        description = "Calculate shipping cost",
        pre = ["order_validated"],
        cost = 0.1
    )
    fun calculateShipping(order: Order): ShippingCost {
        return shippingService.calculate(order)
    }

    @Condition(name = "order_validated")
    fun isOrderValid(): Boolean {
        return context.last(ValidationResult::class.java)?.isValid == true
    }
}

Usage Example (Java):

@Agent(
    name = "inventory-manager",
    provider = "warehouse",
    description = "Manages inventory levels and stock allocation"
)
public class InventoryManagerAgent {

    @Action(description = "Check stock availability")
    public StockLevel checkStock(String productId) {
        return stockRepository.getLevel(productId);
    }

    @Action(
        description = "Reserve inventory",
        pre = {"stock_available"},
        post = {"inventory_reserved"}
    )
    public Reservation reserveStock(String productId, int quantity) {
        return inventoryService.reserve(productId, quantity);
    }

    @Condition(name = "stock_available")
    public boolean hasStock() {
        StockLevel level = context.last(StockLevel.class);
        return level != null && level.getAvailable() > 0;
    }
}

DSL-Based Agent Definition

Define agents using the Kotlin DSL with agent {} function.

fun agent(
    name: String,
    provider: String,
    description: String,
    block: AgentBuilder.() -> Unit
): Agent

interface AgentBuilder {
    var name: String
    var provider: String
    var version: String
    var description: String

    fun action(block: ActionBuilder.() -> Unit)
    fun condition(block: ConditionBuilder.() -> Unit)
    fun goal(block: GoalBuilder.() -> Unit)
    fun <I, O> localAgentAction(agent: Agent)
    fun <I, O> referencedAgentAction(agentName: String)
    fun registerPromptContributors(vararg contributors: PromptContributor)
    fun overridePromptContributors()
}

Usage Example:

val dataProcessorAgent = agent(
    name = "data-processor",
    provider = "analytics",
    description = "Processes and analyzes datasets"
) {
    version = "2.0.0"

    action<DataSet, Report> {
        name = "analyze-dataset"
        description = "Analyze dataset and generate comprehensive report"
        pre = listOf("dataset_valid", "schema_verified")
        post = listOf("report_generated")
        cost = 0.5

        execute { dataset, context ->
            // Access LLM for analysis
            val insights = context.promptRunner()
                .creating(AnalysisInsights::class.java)
                .fromPrompt("""
                    Analyze this dataset:
                    Rows: ${dataset.rowCount}
                    Columns: ${dataset.columns.joinToString()}
                    Summary: ${dataset.summary}
                """)

            // Generate report
            Report(
                datasetId = dataset.id,
                insights = insights,
                timestamp = Instant.now()
            )
        }
    }

    action<Report, Unit> {
        name = "publish-report"
        description = "Publish generated report"
        pre = listOf("report_generated")

        execute { report, context ->
            context.updateProgress("Publishing report ${report.id}")
            reportService.publish(report)
        }
    }

    condition {
        name = "dataset_valid"
        cost = 0.1

        evaluate { context ->
            val dataset = context.last(DataSet::class.java)
            dataset != null && dataset.isValid()
        }
    }

    condition {
        name = "schema_verified"

        evaluate { context ->
            val dataset = context.last(DataSet::class.java)
            dataset?.schema?.isVerified() == true
        }
    }

    goal {
        name = "data_processed"
        description = "Dataset has been processed and report published"
        value = 1.0
        conditions = listOf("report_generated")
    }
}

Embabel Component Definition

Define reusable components that expose actions, goals, and conditions without being full agents.

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class EmbabelComponent(
    val scan: Boolean = true
)

Usage Example:

@EmbabelComponent
class CustomerServiceCapabilities {

    @Action(description = "Send email notification to customer")
    fun sendEmail(
        @LlmTool.Param(description = "Customer email address")
        email: String,
        @LlmTool.Param(description = "Email subject line")
        subject: String,
        @LlmTool.Param(description = "Email body content")
        body: String
    ): EmailReceipt {
        return emailService.send(email, subject, body)
    }

    @Action(description = "Create support ticket")
    fun createTicket(issue: String, priority: Priority): Ticket {
        return ticketSystem.create(issue, priority)
    }

    @Condition(name = "email_validated")
    fun isEmailValid(email: String): Boolean {
        return emailValidator.validate(email)
    }
}

Deprecated Agent Capabilities

@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@Deprecated("Use @EmbabelComponent instead")
annotation class AgentCapabilities

The @AgentCapabilities annotation is deprecated. Use @EmbabelComponent for defining reusable agent capabilities.

Types

/** Type alias for values constrained to 0.0-1.0 range */
typealias ZeroToOne = Double

interface Agent {
    val name: String
    val description: String
    val provider: String
    val version: String
    val planner: PlannerType
    val actions: List<Action>
    val goals: List<Goal>
    val conditions: List<Condition>
}

enum class PlannerType(val needsGoals: Boolean) {
    GOAP(needsGoals = true),
    UTILITY(needsGoals = false),
    SUPERVISOR(needsGoals = true)
}

enum class ActionRetryPolicy {
    /** Fire only once (maxAttempts = 1) */
    FIRE_ONCE,
    /** Default retry policy using ActionQos defaults */
    DEFAULT
}

interface PromptContributor {
    fun contribute(context: OperationContext): String
}

Install with Tessl CLI

npx tessl i tessl/maven-com-embabel-agent--embabel-agent-api@0.3.0

docs

actions-goals.md

agent-definition.md

builtin-tools.md

chat.md

conditions.md

events.md

human-in-the-loop.md

index.md

invocation.md

io-binding.md

llm-interaction.md

models.md

planning-workflows.md

platform-management.md

runtime-context.md

state-management.md

streaming.md

subagents.md

tools.md

type-system.md

typed-operations.md

validation.md

tile.json