CtrlK
CommunityDocumentationLog inGet started
Tessl Logo

tessl/maven-com-embabel-agent--embabel-agent-starter

Base starter module for the Embabel Agent Framework providing core dependencies for building agentic flows on the JVM with Spring Boot integration and GOAP-based intelligent path finding.

Overview
Eval results
Files

api-domain-model.mddocs/

Domain Model API Reference

Complete API reference for core domain types, enums, and concepts.

Planning and Strategy

PlannerType

Enum defining the planning algorithm used by agents.

package com.embabel.agent.api

enum class PlannerType {
    GOAP
}

Values:

  • GOAP - Goal-Oriented Action Planning (default)

Usage:

import com.embabel.agent.api.annotation.Agent;
import com.embabel.agent.api.annotation.PlannerType;

@Agent(
    description = "Task planner agent",
    planner = PlannerType.GOAP
)
public class TaskPlannerAgent { }
import com.embabel.agent.api.annotation.Agent
import com.embabel.agent.api.annotation.PlannerType

@Agent(
    description = "Workflow agent",
    planner = PlannerType.GOAP
)
class WorkflowAgent { }

ActionRetryPolicy

Configures retry behavior for actions that fail during execution.

package com.embabel.agent.api

data class ActionRetryPolicy(
    val maxAttempts: Int,
    val backoffMillis: Long,
    val backoffMultiplier: Double,
    val backoffMaxInterval: Long
) {
    companion object {
        val DEFAULT: ActionRetryPolicy
        val NO_RETRY: ActionRetryPolicy

        fun exponential(maxAttempts: Int, initialBackoffMillis: Long): ActionRetryPolicy
        fun fixed(maxAttempts: Int, backoffMillis: Long): ActionRetryPolicy
    }
}

Properties:

  • maxAttempts: Int - Maximum retry attempts
  • backoffMillis: Long - Initial backoff milliseconds
  • backoffMultiplier: Double - Backoff multiplier for exponential retry
  • backoffMaxInterval: Long - Maximum backoff interval

Factory Methods:

  • DEFAULT: ActionRetryPolicy - Default retry policy
  • NO_RETRY: ActionRetryPolicy - No retry policy
  • exponential(maxAttempts: Int, initialBackoffMillis: Long): ActionRetryPolicy - Exponential backoff
  • fixed(maxAttempts: Int, backoffMillis: Long): ActionRetryPolicy - Fixed backoff

Usage:

import com.embabel.agent.api.ActionRetryPolicy;
import com.embabel.agent.api.annotation.Agent;
import com.embabel.agent.api.annotation.Action;

@Agent(
    description = "Resilient agent",
    actionRetryPolicy = ActionRetryPolicy.exponential(3, 1000)
)
public class ResilientAgent {

    @Action(
        description = "Fetch data with retries",
        actionRetryPolicy = ActionRetryPolicy.exponential(5, 500)
    )
    public Data fetchData(String source) {
        return dataService.fetch(source);
    }

    @Action(
        description = "Critical operation - no retries",
        actionRetryPolicy = ActionRetryPolicy.NO_RETRY
    )
    public void criticalOperation() {
        // No retries - must succeed first time
    }
}
import com.embabel.agent.api.ActionRetryPolicy
import com.embabel.agent.api.annotation.Agent
import com.embabel.agent.api.annotation.Action

@Agent(
    description = "Data processor",
    actionRetryPolicy = ActionRetryPolicy.fixed(3, 2000)
)
class DataProcessor {

    @Action(
        description = "Process with exponential backoff",
        actionRetryPolicy = ActionRetryPolicy.exponential(10, 100)
    )
    fun processData(data: Input): Output {
        return processor.process(data)
    }
}

Multimodal Content

MultimodalContent

Supports multi-modal agent inputs including text, images, audio, and video.

package com.embabel.agent.api

sealed class MultimodalContent {
    data class Text(val content: String) : MultimodalContent()
    data class Image(val url: String, val mimeType: String) : MultimodalContent()
    data class Audio(val url: String, val mimeType: String) : MultimodalContent()
    data class Video(val url: String, val mimeType: String) : MultimodalContent()
    data class File(val path: String, val mimeType: String) : MultimodalContent()

    companion object {
        fun text(content: String): MultimodalContent.Text
        fun image(url: String, mimeType: String = "image/jpeg"): MultimodalContent.Image
        fun audio(url: String, mimeType: String = "audio/mpeg"): MultimodalContent.Audio
        fun video(url: String, mimeType: String = "video/mp4"): MultimodalContent.Video
        fun file(path: String, mimeType: String): MultimodalContent.File
    }
}

Types:

Text

  • content: String - Text content

Image

  • url: String - Image URL or path
  • mimeType: String - MIME type (default: "image/jpeg")

Audio

  • url: String - Audio URL or path
  • mimeType: String - MIME type (default: "audio/mpeg")

Video

  • url: String - Video URL or path
  • mimeType: String - MIME type (default: "video/mp4")

File

  • path: String - File path
  • mimeType: String - MIME type

Factory Methods:

  • text(content: String): MultimodalContent.Text - Create text content
  • image(url: String, mimeType: String = "image/jpeg"): MultimodalContent.Image - Create image content
  • audio(url: String, mimeType: String = "audio/mpeg"): MultimodalContent.Audio - Create audio content
  • video(url: String, mimeType: String = "video/mp4"): MultimodalContent.Video - Create video content
  • file(path: String, mimeType: String): MultimodalContent.File - Create file content

Usage:

import com.embabel.agent.api.MultimodalContent;
import com.embabel.agent.api.annotation.Action;

@Agent(description = "Multimodal agent")
public class MultimodalAgent {

    @Action(description = "Process multimodal input")
    public Result processMultimodal(List<MultimodalContent> inputs, @Provided Ai ai) {
        return ai.withLlm(GeminiModels.GEMINI_2_5_PRO)
                 .createObject(inputs);
    }

    public List<MultimodalContent> createMultimodalInput() {
        return List.of(
            MultimodalContent.text("Analyze this image:"),
            MultimodalContent.image("https://example.com/image.jpg", "image/jpeg"),
            MultimodalContent.text("and this audio:"),
            MultimodalContent.audio("https://example.com/audio.mp3", "audio/mpeg")
        );
    }
}
import com.embabel.agent.api.MultimodalContent
import com.embabel.agent.api.annotation.Action

@Agent(description = "Content analyzer")
class ContentAnalyzer {

    @Action(description = "Analyze multimedia content")
    fun analyzeContent(content: List<MultimodalContent>, @Provided ai: Ai): Analysis {
        return ai.withLlm(GeminiModels.GEMINI_2_5_PRO)
                 .createObject(content)
    }

    fun createContentList(): List<MultimodalContent> {
        return listOf(
            MultimodalContent.text("Process these files:"),
            MultimodalContent.image("file:///images/chart.png"),
            MultimodalContent.file("/data/report.pdf", "application/pdf")
        )
    }
}

Communication and Messaging

Message

Messages sent during agent execution for logging, progress, and communication.

package com.embabel.agent.api

sealed class Message {
    data class Info(val content: String) : Message()
    data class Warning(val content: String) : Message()
    data class Error(val content: String, val exception: Throwable?) : Message()
    data class Progress(val content: String, val percentage: Double?) : Message()
    data class User(val content: String) : Message()
    data class Assistant(val content: String) : Message()

    companion object {
        fun info(content: String): Message.Info
        fun warning(content: String): Message.Warning
        fun error(content: String, exception: Throwable? = null): Message.Error
        fun progress(content: String, percentage: Double? = null): Message.Progress
        fun user(content: String): Message.User
        fun assistant(content: String): Message.Assistant
    }
}

Types:

Info

  • content: String - Informational message

Warning

  • content: String - Warning message

Error

  • content: String - Error message
  • exception: Throwable? - Optional exception

Progress

  • content: String - Progress message
  • percentage: Double? - Optional percentage (0.0-100.0)

User

  • content: String - User message

Assistant

  • content: String - Assistant message

Factory Methods:

  • info(content: String): Message.Info - Create info message
  • warning(content: String): Message.Warning - Create warning message
  • error(content: String, exception: Throwable? = null): Message.Error - Create error message
  • progress(content: String, percentage: Double? = null): Message.Progress - Create progress message
  • user(content: String): Message.User - Create user message
  • assistant(content: String): Message.Assistant - Create assistant message

Usage:

import com.embabel.agent.api.Message;
import com.embabel.agent.api.ActionContext;

@Agent(description = "Reporting agent")
public class ReportingAgent {

    @Action(description = "Generate report with progress")
    public Report generateReport(Data data, @Provided ActionContext context) {
        context.sendMessage(Message.info("Starting report generation"));
        context.sendMessage(Message.progress("Analyzing data", 0.0));

        Analysis analysis = analyze(data);
        context.sendMessage(Message.progress("Data analyzed", 50.0));

        Report report = createReport(analysis);
        context.sendMessage(Message.progress("Report created", 100.0));
        context.sendMessage(Message.info("Report generation complete"));

        return report;
    }
}
import com.embabel.agent.api.Message
import com.embabel.agent.api.ActionContext

@Agent(description = "Data processor")
class DataProcessor {

    @Action(description = "Process with detailed logging")
    fun processData(input: Dataset, @Provided context: ActionContext): ProcessedData {
        context.sendMessage(Message.info("Processing ${input.size} records"))

        try {
            context.sendMessage(Message.progress("Validating", 25.0))
            val validated = validate(input)

            context.sendMessage(Message.progress("Transforming", 50.0))
            val transformed = transform(validated)

            context.sendMessage(Message.progress("Finalizing", 75.0))
            val result = finalize(transformed)

            context.sendMessage(Message.progress("Complete", 100.0))
            return result
        } catch (e: Exception) {
            context.sendMessage(Message.error("Processing failed", e))
            throw e
        }
    }
}

OutputChannel

Channel for sending structured output events during agent execution.

package com.embabel.agent.api

interface OutputChannel {
    fun send(event: OutputChannelEvent)
    fun sendAndSave(event: OutputChannelEvent)
    fun close()
}

data class OutputChannelEvent(
    val type: EventType,
    val content: Any,
    val metadata: Map<String, Any> = emptyMap()
)

enum class EventType {
    DATA, PROGRESS, LOG, ERROR, RESULT
}

OutputChannel Methods:

  • send(event: OutputChannelEvent) - Send event
  • sendAndSave(event: OutputChannelEvent) - Send and persist event
  • close() - Close channel

OutputChannelEvent Properties:

  • type: EventType - Event type
  • content: Any - Event content
  • metadata: Map<String, Any> - Event metadata (default: empty)

EventType Values:

  • DATA - Data event
  • PROGRESS - Progress event
  • LOG - Log event
  • ERROR - Error event
  • RESULT - Result event

Usage:

import com.embabel.agent.api.OutputChannel;
import com.embabel.agent.api.OutputChannelEvent;
import com.embabel.agent.api.EventType;

@Action(description = "Stream results")
public void streamResults(@Provided OutputChannel channel) {
    channel.send(new OutputChannelEvent(
        EventType.PROGRESS,
        Map.of("stage", "initialization", "percent", 0)
    ));

    channel.send(new OutputChannelEvent(
        EventType.DATA,
        processedData,
        Map.of("timestamp", Instant.now())
    ));

    channel.send(new OutputChannelEvent(
        EventType.RESULT,
        finalResult
    ));

    channel.close();
}

Event Handling

AgenticEventListener

Interface for listening to agent execution events for monitoring and observability.

package com.embabel.agent.api

interface AgenticEventListener {
    fun onAgentStart(agent: Agent, input: Any)
    fun onAgentComplete(agent: Agent, result: Any)
    fun onAgentError(agent: Agent, error: Throwable)
    fun onActionStart(action: Action, parameters: Map<String, Any>)
    fun onActionComplete(action: Action, result: Any)
    fun onActionError(action: Action, error: Throwable)
    fun onPlanningStart(agent: Agent)
    fun onPlanningComplete(agent: Agent, plan: Plan)
}

Methods:

  • onAgentStart(agent: Agent, input: Any) - Agent execution started
  • onAgentComplete(agent: Agent, result: Any) - Agent execution completed
  • onAgentError(agent: Agent, error: Throwable) - Agent execution error
  • onActionStart(action: Action, parameters: Map<String, Any>) - Action execution started
  • onActionComplete(action: Action, result: Any) - Action execution completed
  • onActionError(action: Action, error: Throwable) - Action execution error
  • onPlanningStart(agent: Agent) - Planning started
  • onPlanningComplete(agent: Agent, plan: Plan) - Planning completed

Usage:

import com.embabel.agent.api.AgenticEventListener;
import org.springframework.stereotype.Component;

@Component
public class MonitoringEventListener implements AgenticEventListener {

    @Override
    public void onAgentStart(Agent agent, Object input) {
        log.info("Agent started: {} with input: {}", agent.getName(), input);
        metrics.incrementCounter("agent.start");
    }

    @Override
    public void onAgentComplete(Agent agent, Object result) {
        log.info("Agent completed: {} with result: {}", agent.getName(), result);
        metrics.incrementCounter("agent.complete");
    }

    @Override
    public void onAgentError(Agent agent, Throwable error) {
        log.error("Agent error: {}", agent.getName(), error);
        metrics.incrementCounter("agent.error");
        alerts.sendAlert("Agent failure: " + agent.getName());
    }

    @Override
    public void onActionStart(Action action, Map<String, Object> parameters) {
        log.debug("Action started: {}", action.getDescription());
    }

    @Override
    public void onActionComplete(Action action, Object result) {
        log.debug("Action completed: {}", action.getDescription());
    }

    @Override
    public void onActionError(Action action, Throwable error) {
        log.warn("Action error: {}", action.getDescription(), error);
    }

    @Override
    public void onPlanningStart(Agent agent) {
        log.debug("Planning started for agent: {}", agent.getName());
    }

    @Override
    public void onPlanningComplete(Agent agent, Plan plan) {
        log.debug("Planning complete: {} steps", plan.getSteps().size());
    }
}

Safety and Constraints

GuardRail

Interface for implementing safety constraints and validation rules.

package com.embabel.agent.api

interface GuardRail {
    fun validate(operation: Operation): ValidationResult
    fun getName(): String
    fun getDescription(): String
}

data class ValidationResult(
    val passed: Boolean,
    val message: String? = null,
    val severity: Severity = Severity.ERROR
)

enum class Severity {
    INFO, WARNING, ERROR, CRITICAL
}

GuardRail Methods:

  • validate(operation: Operation): ValidationResult - Validate operation
  • getName(): String - Get guard rail name
  • getDescription(): String - Get guard rail description

ValidationResult Properties:

  • passed: Boolean - Validation passed flag
  • message: String? - Optional validation message
  • severity: Severity - Severity level (default: ERROR)

Severity Values:

  • INFO - Informational
  • WARNING - Warning
  • ERROR - Error
  • CRITICAL - Critical

Usage:

import com.embabel.agent.api.GuardRail;
import com.embabel.agent.api.ValidationResult;
import com.embabel.agent.api.Severity;
import org.springframework.stereotype.Component;

@Component
public class CostGuardRail implements GuardRail {

    private static final double MAX_COST = 1000.0;

    @Override
    public ValidationResult validate(Operation operation) {
        double cost = operation.estimateCost();

        if (cost > MAX_COST) {
            return new ValidationResult(
                false,
                String.format("Operation cost %.2f exceeds maximum %.2f", cost, MAX_COST),
                Severity.ERROR
            );
        } else if (cost > MAX_COST * 0.8) {
            return new ValidationResult(
                true,
                String.format("Operation cost %.2f is approaching maximum", cost),
                Severity.WARNING
            );
        }

        return new ValidationResult(true);
    }

    @Override
    public String getName() {
        return "cost-guard-rail";
    }

    @Override
    public String getDescription() {
        return "Prevents operations that exceed cost limits";
    }
}

Blackboard and State

ZeroToOne

Type-safe representation of values between 0.0 and 1.0.

package com.embabel.agent.api

data class ZeroToOne private constructor(val value: Double) {
    companion object {
        val ZERO: ZeroToOne
        val ONE: ZeroToOne

        fun of(value: Double): ZeroToOne
    }
}

Properties:

  • value: Double - Value between 0.0 and 1.0

Factory Methods:

  • ZERO: ZeroToOne - Zero value (0.0)
  • ONE: ZeroToOne - One value (1.0)
  • of(value: Double): ZeroToOne - Create from double (validates 0.0-1.0 range)

Usage:

import com.embabel.agent.api.ZeroToOne;

@Condition(name = "hasStock", cost = ZeroToOne.of(0.1))
public boolean hasStock(String productId) {
    return inventory.getStock(productId) > 0;
}
import com.embabel.agent.api.ZeroToOne

@Condition(name = "userAuthenticated", cost = ZeroToOne.of(0.05))
fun isAuthenticated(userId: String): Boolean {
    return authService.isAuthenticated(userId)
}

Budget and Limits

Budget

Execution budget configuration (time or steps).

package com.embabel.agent.api

data class Budget(
    val type: BudgetType,
    val value: Long
) {
    companion object {
        fun of(time: Long, unit: TimeUnit): Budget
        fun ofSteps(steps: Long): Budget
        fun unlimited(): Budget
    }
}

enum class BudgetType {
    TIME, STEPS, UNLIMITED
}

Properties:

  • type: BudgetType - Budget type
  • value: Long - Budget value

Factory Methods:

  • of(time: Long, unit: TimeUnit): Budget - Create time budget
  • ofSteps(steps: Long): Budget - Create step budget
  • unlimited(): Budget - Create unlimited budget

BudgetType Values:

  • TIME - Time-based budget
  • STEPS - Step-based budget
  • UNLIMITED - No budget limit

Usage:

import com.embabel.agent.api.Budget;
import java.util.concurrent.TimeUnit;

AgentInvocation<AnalysisResult> invocation = AgentInvocation.builder(platform)
    .withBudget(Budget.of(60, TimeUnit.SECONDS))
    .build(AnalysisResult.class);

Verbosity

Logging verbosity levels.

package com.embabel.agent.api

enum class Verbosity {
    SILENT, MINIMAL, NORMAL, DETAILED, DEBUG
}

Values:

  • SILENT - No logging
  • MINIMAL - Minimal logging
  • NORMAL - Normal logging (default)
  • DETAILED - Detailed logging
  • DEBUG - Debug-level logging

Usage:

import com.embabel.agent.api.Verbosity;

AgentInvocation<Report> invocation = AgentInvocation.builder(platform)
    .withVerbosity(Verbosity.DETAILED)
    .build(Report.class);
tessl i tessl/maven-com-embabel-agent--embabel-agent-starter@0.3.1

docs

api-annotations.md

api-domain-model.md

api-invocation.md

api-tools.md

concepts-actions.md

concepts-agents.md

concepts-goals.md

concepts-invocation.md

concepts-tools.md

guides-creating-agents.md

guides-creating-tools.md

guides-defining-actions.md

guides-goal-achievement.md

guides-human-in-loop.md

guides-multimodal.md

index.md

integration-mcp.md

integration-model-providers.md

integration-spring-boot.md

LlmTool.md

quickstart.md

reference-component-scanning.md

reference-configuration-properties.md

reference-installation.md

reference-logging.md

reference-resilience.md

reference-streaming.md

tile.json