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.
Auto-configuration mechanics, component scanning, and META-INF registration for Embabel Agent Framework Spring Boot integration.
Main auto-configuration class that bootstraps the Embabel Agent Platform.
package com.embabel.agent.autoconfigure.platform;
@AutoConfiguration
@Import({
ScanConfiguration.class,
AgentPlatformConfiguration.class,
ToolGroupsConfiguration.class,
QuiteMcpClientAutoConfiguration.class
})
public class AgentPlatformAutoConfiguration {
// Bootstraps Agent Platform, Tools, RAG Services
}Responsibilities:
Registration: META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
Configures component scanning for agent packages.
@Configuration
@ComponentScan(basePackages = {
"com.embabel.agent.api",
"com.embabel.agent.core",
"com.embabel.agent.experimental",
"com.embabel.agent.prompt",
"com.embabel.agent.spi",
"com.embabel.agent.test",
"com.embabel.agent.tools",
"com.embabel.agent.web"
})
@EnableConfigurationProperties
public class ScanConfiguration {
// Enables component scanning and configuration properties
}Scanned Packages:
com.embabel.agent.api - Core agent API componentscom.embabel.agent.core - Core implementation classescom.embabel.agent.experimental - Experimental featurescom.embabel.agent.prompt - Prompt-related componentscom.embabel.agent.spi - Service Provider Interface implementationscom.embabel.agent.test - Testing support componentscom.embabel.agent.tools - Tool implementationscom.embabel.agent.web - Web-related componentsUsage: Place your @Agent, @Component, @Service classes in these packages for automatic discovery.
Enhanced MCP (Model Context Protocol) client with resilience patterns.
@AutoConfiguration
@ConditionalOnProperty(
prefix = "spring.ai.mcp.client",
name = "enabled",
havingValue = "true",
matchIfMissing = true
)
public class QuiteMcpClientAutoConfiguration {
// Configures resilient MCP client (sync and async)
}Features:
Configuration: spring.ai.mcp.client.* properties
Filters out conflicting Spring AI auto-configurations.
@AutoConfigurationImportFilter
public class AgentPlatformAutoConfigurationFilter
implements AutoConfigurationImportFilter {
@Override
public boolean[] match(String[] autoConfigurationClasses,
AutoConfigurationMetadata autoConfigurationMetadata) {
// Excludes Spring AI's default McpClientAutoConfiguration
// Allows Embabel's enhanced implementation to take precedence
}
}Purpose: Ensures Embabel's resilient MCP client is used instead of Spring AI's default implementation.
Registers SPI implementations.
# Environment Post Processor
org.springframework.boot.env.EnvironmentPostProcessor=\
com.embabel.agent.config.annotation.spi.EnvironmentPostProcessor
# Auto-Configuration Import Filter
org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
com.embabel.agent.autoconfigure.platform.AgentPlatformAutoConfigurationFilterEarly initialization hook that runs before application context is created.
public class EnvironmentPostProcessor
implements org.springframework.boot.env.EnvironmentPostProcessor {
@Override
public void postProcessEnvironment(
ConfigurableEnvironment environment,
SpringApplication application) {
// Activates profiles based on @EnableAgents annotation
// Sets embabel.agent.logging.personality property
}
}Timing: Runs during Spring Boot startup, before bean creation.
Actions:
@EnableAgents annotationRegisters auto-configuration classes.
com.embabel.agent.autoconfigure.platform.AgentPlatformAutoConfigurationThis file is read by Spring Boot to discover auto-configuration classes.
Default configuration for the agent platform.
# Scanning
embabel.agent.platform.scanning.annotation=true
embabel.agent.platform.scanning.bean=false
# Ranking
embabel.agent.platform.ranking.max-attempts=5
embabel.agent.platform.ranking.backoff-millis=100
embabel.agent.platform.ranking.backoff-multiplier=5.0
embabel.agent.platform.ranking.backoff-max-interval=180000
# Autonomy
embabel.agent.platform.autonomy.agent-confidence-cut-off=0.6
embabel.agent.platform.autonomy.goal-confidence-cut-off=0.6
# LLM Operations
embabel.agent.platform.llm-operations.prompts.maybe-prompt-template=maybe_prompt_contribution
embabel.agent.platform.llm-operations.prompts.generate-examples-by-default=true
embabel.agent.platform.llm-operations.data-binding.max-attempts=10
embabel.agent.platform.llm-operations.data-binding.fixed-backoff-millis=30
# SSE
embabel.agent.platform.sse.max-buffer-size=100
embabel.agent.platform.sse.max-process-buffers=1000
# Model Provider Retries
embabel.agent.platform.models.anthropic.max-attempts=10
embabel.agent.platform.models.anthropic.backoff-millis=5000
embabel.agent.platform.models.anthropic.backoff-multiplier=5.0
embabel.agent.platform.models.anthropic.backoff-max-interval=180000
embabel.agent.platform.models.openai.max-attempts=10
embabel.agent.platform.models.openai.backoff-millis=5000
embabel.agent.platform.models.openai.backoff-multiplier=5.0
embabel.agent.platform.models.openai.backoff-max-interval=180000
# Testing
embabel.agent.platform.test.mock-mode=trueApplication-level defaults.
spring.application.name=agent-api
spring.threads.virtual.enabled=true
spring.output.ansi.enabled=ALWAYS
spring.ai.ollama.base-url=http://localhost:11434
spring.ai.openai.api-key=${OPENAI_API_KEY}
management.tracing.enabled=false
embabel.models.default-llm=gpt-4.1-mini
embabel.models.default-embedding-model=text-embedding-3-small
logging.pattern.console=%clr(%d{HH:mm:ss.SSS}){faint} %clr([%t]){magenta} %clr(%-5level) %clr(%logger{0}){cyan} %clr(-){faint} %msg%nProvides IDE autocomplete and validation.
{
"properties": [
{
"name": "embabel.agent.logging.personality",
"type": "java.lang.String",
"description": "Logging personality theme for agent operations",
"sourceType": "com.embabel.agent.config.annotation.LoggingThemes"
}
],
"hints": [
{
"name": "embabel.agent.logging.personality",
"values": [
{"value": "starwars", "description": "Star Wars themed logging"},
{"value": "severance", "description": "Severance themed logging"},
{"value": "colossus", "description": "Colossus themed logging"},
{"value": "hitchhiker", "description": "Hitchhiker's Guide themed logging"},
{"value": "montypython", "description": "Monty Python themed logging"}
]
}
]
}Benefits:
Place agent classes in scanned packages for automatic discovery:
package com.embabel.agent.api.myapp; // ✅ Scanned
@Agent(description = "My agent")
@Component
public class MyAgent {
// Automatically discovered
}package com.embabel.agent.api.agents
import com.embabel.agent.api.annotation.Agent
import com.embabel.agent.api.annotation.Action
import org.springframework.stereotype.Component
@Agent(description = "Data processing agent")
@Component
class DataProcessingAgent {
@Action
fun processData(input: Input): Result {
// Implementation
}
}Add custom packages to scanning:
package com.mycompany.myapp;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = {
"com.mycompany.myapp.agents",
"com.mycompany.myapp.services"
})
public class MyAppScanConfiguration {
// Your custom packages will now be scanned
}package com.mycompany.myapp
import org.springframework.context.annotation.ComponentScan
import org.springframework.context.annotation.Configuration
@Configuration
@ComponentScan(basePackages = [
"com.mycompany.myapp.agents",
"com.mycompany.myapp.services"
])
class MyAppScanConfigurationControl annotation-based agent scanning via properties:
embabel:
agent:
platform:
scanning:
annotation: true # Enable @Agent/@Agentic annotation scanning (default: true)
bean: false # Enable bean-based agent scanning (default: false)import com.embabel.agent.api.platform.AgentPlatform;
import com.embabel.agent.api.services.PlatformServices;
import org.springframework.stereotype.Component;
@Component
public class MyService {
private final AgentPlatform platform;
private final PlatformServices services;
// Constructor injection (recommended)
public MyService(AgentPlatform platform, PlatformServices services) {
this.platform = platform;
this.services = services;
}
public void runAgent() {
platform.execute(/* ... */);
}
}import com.embabel.agent.autoconfigure.platform.AgentPlatformProperties;
import org.springframework.stereotype.Component;
@Component
public class MyService {
private final AgentPlatformProperties properties;
public MyService(AgentPlatformProperties properties) {
this.properties = properties;
}
public void configure() {
double cutoff = properties.getAutonomy().getAgentConfidenceCutOff();
// Use configuration
}
}# application-dev.yml
embabel:
agent:
platform:
test:
mock-mode: true # Enable mocks in development
# application-prod.yml
embabel:
agent:
platform:
test:
mock-mode: false # Real LLM calls in productionActivate with:
export SPRING_PROFILES_ACTIVE=dev
# or
java -jar app.jar --spring.profiles.active=prodimport org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class CustomConfiguration {
@Bean
@ConditionalOnProperty(
prefix = "embabel.agent",
name = "custom-feature-enabled",
havingValue = "true"
)
public CustomFeature customFeature() {
return new CustomFeature();
}
}Enable conditional bean creation based on configured MCP connections.
package com.embabel.agent.spi.config.spring
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
@MustBeDocumented
@Conditional(OnMcpConnectionCondition::class)
annotation class ConditionalOnMcpConnection(
vararg val value: String
)Usage Example (Java):
import com.embabel.agent.spi.config.spring.ConditionalOnMcpConnection;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MyToolsConfiguration {
@Bean
@ConditionalOnMcpConnection("github-mcp")
public ToolGroup githubTools() {
// Only created when github-mcp connection is configured
return ToolGroup.create("github", githubToolList);
}
@Bean
@ConditionalOnMcpConnection("brave-search-mcp", "fetch-mcp")
public ToolGroup webTools() {
// Created when ANY of the specified connections exists
return ToolGroup.create("web", webToolList);
}
}Usage Example (Kotlin):
import com.embabel.agent.spi.config.spring.ConditionalOnMcpConnection
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
@Configuration
class MyToolsConfiguration {
@Bean
@ConditionalOnMcpConnection("github-mcp", "docker-mcp")
fun githubToolsGroup(): ToolGroup {
// Created if either github-mcp or docker-mcp is configured
return McpToolGroup(
name = "github-tools",
description = "GitHub API tools",
clients = mcpSyncClients
)
}
}Configuration Example:
spring:
ai:
mcp:
client:
stdio:
connections:
github-mcp:
command: npx
args:
- -y
- @modelcontextprotocol/server-github
docker-mcp:
command: docker
args:
- run
- -i
- --rm
- ghcr.io/modelcontextprotocol/servers/githubHow It Works:
spring.ai.mcp.client.stdio.connections.{name}.commandspring.ai.mcp.client.sse.connections.{name}.url@RestController
@RequestMapping("/api/agents")
public class AgentController {
private final AgentPlatform platform;
public AgentController(AgentPlatform platform) {
this.platform = platform;
}
@PostMapping("/execute")
public ResponseEntity<Result> execute(@RequestBody Request request) {
Result result = platform.execute(request);
return ResponseEntity.ok(result);
}
}import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledAgentRunner {
private final AgentPlatform platform;
public ScheduledAgentRunner(AgentPlatform platform) {
this.platform = platform;
}
@Scheduled(cron = "0 0 * * * *") // Every hour
public void runPeriodicAgent() {
platform.execute(/* periodic task */);
}
}import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
@Component
public class EventDrivenAgentRunner {
private final AgentPlatform platform;
public EventDrivenAgentRunner(AgentPlatform platform) {
this.platform = platform;
}
@EventListener
public void handleCustomEvent(CustomEvent event) {
platform.execute(event.getData());
}
}Solution: Ensure your classes are in scanned packages (com.embabel.agent.*).
Solution: Check property names and ensure application.yml is in src/main/resources/.
Solution: Verify Spring Milestones repository is configured and spring.ai.mcp.client.enabled=true.
Solution: Check for conflicting auto-configurations and exclude them in @SpringBootApplication:
@SpringBootApplication(exclude = {ConflictingAutoConfiguration.class})
public class MyApplication {
// ...
}Solutions:
com.embabel.agent.*)@Component annotation on agent class@Agent annotation is presentscanning.annotation=true in configurationSolution: Use constructor injection and @Lazy where needed:
@Component
public class ServiceA {
private final ServiceB serviceB;
public ServiceA(@Lazy ServiceB serviceB) {
this.serviceB = serviceB;
}
}tessl i tessl/maven-com-embabel-agent--embabel-agent-starter@0.3.1docs