Agent Framework Examples for Java and Kotlin Developers
Java
183
232 commits
updated Sep 16, 2026
ย ย ย ย
English ยท ็ฎไฝไธญๆ
Learn agentic AI development with Spring Framework and Java or Kotlin. These examples demonstrate building intelligent agents that can plan, execute workflows, use tools, and interact with humans.
This repository uses the latest Embabel snapshots to illustrate current best practice, whereas the Java and Kotlin template repositories s use the latest milestone release for greater stability. There may be some minor API incompatilibites and not everything you see here may work in your own project created from one of those templates, unless you upgrade the
embabel-agent.versionproperty in the POM file, as in this repository.
git clone https://github.com/embabel/embabel-agent-examples.git
cd embabel-agent-examples
./mvnw clean install # Unix/Linux/macOS
mvnw.cmd clean install # Windows
# Required (choose one or both)
export OPENAI_API_KEY="your_openai_key"
export ANTHROPIC_API_KEY="your_anthropic_key"
cd scripts/kotlin
./shell.sh # Unix/Linux/macOS - With Docker tools (default)
shell.cmd # Windows - With Docker tools (default)
./shell.sh --no-docker-tools # Unix/Linux/macOS - Basic features only
shell.cmd --no-docker-tools # Windows - Basic features only
cd scripts/java
./shell.sh # Unix/Linux/macOS - With Docker tools (default)
shell.cmd # Windows - With Docker tools (default)
./shell.sh --no-docker-tools # Unix/Linux/macOS - Basic features only
shell.cmd --no-docker-tools # Windows - Basic features only
You can create your own agent repo from our Java or Kotlin GitHub template by clicking the "Use this template" button.
You can also create your own Embabel agent project locally with our quick start tool, which allows some customization:
uvx --from git+https://github.com/embabel/project-creator.git project-creator
Choose Java or Kotlin and specify your project name and package name and you'll have an agent running in under a minute,
if you already have an OPENAI_API_KEY and have Maven installed.
embabel-agent-starterembabel-agent-starter-shellembabel-agent-starter-mcpserver@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.embabel.example"])
class KotlinAgentShellApplication
fun main(args: Array<String>) {
runApplication<KotlinAgentShellApplication>(*args) {
setDefaultProperties(
mapOf("embabel.agent.logging.personality" to LoggingThemes.STAR_WARS)
)
}
}
// Java version
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = {"com.embabel.example"})
public class JavaAgentShellApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(JavaAgentShellApplication.class);
app.setDefaultProperties(Map.of(
"embabel.agent.logging.personality", LoggingThemes.STAR_WARS
));
app.run(args);
}
}
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.embabel.example"])
class KotlinAgentShellApplication
fun main(args: Array<String>) {
runApplication<KotlinAgentShellApplication>(*args) {
setAdditionalProfiles(McpServers.DOCKER) // Activates application-docker-ce.yml
setDefaultProperties(
mapOf("embabel.agent.logging.personality" to LoggingThemes.SEVERANCE)
)
}
}
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.embabel.example"])
class KotlinAgentMcpServerApplication
fun main(args: Array<String>) {
runApplication<KotlinAgentMcpServerApplication>(*args) {
setAdditionalProfiles(McpServers.DOCKER, McpServers.DOCKER_DESKTOP)
}
}
Set via the embabel.agent.logging.personality property:
"starwars" - May the Force be with your logs!"severance" - Welcome to Lumon Industries (default)Configure via Spring profiles that define Spring AI MCP client connections in application-{profile}.yml:
# application-docker-ce.yml
spring:
ai:
mcp:
client:
type: SYNC
stdio:
connections:
docker-mcp:
command: docker
args: [mcp, gateway, run]
Several of the examples use the Model Context Protocol (MCP) to access tools and services.
The default source is the Docker Desktop MCP server, which is installed with Docker Desktop.
To ensure tools are available and startup doesn't time out, first pull models with:
docker login
docker mcp gateway run
When the gateway has come up you can kill it and start the Embabel server.
Available in: Java | Concept: Just a Little AI
Demonstrates how you can inject any Spring component with an Embabel OperationContext
and use it to call LLMs with the rich Embabel API.
@Component
public record InjectedComponent(Ai ai) {
public record Joke(String leadup, String punchline) {
}
public String tellJokeAbout(String topic) {
return ai
.withDefaultLlm()
.generateText("Tell me a joke about " + topic);
}
public Joke createJokeObjectAbout(String topic1, String topic2, String voice) {
return ai
.withLlm(LlmOptions.withDefaultLlm().withTemperature(.8))
.createObject("""
Tell me a joke about %s and %s.
The voice of the joke should be %s.
The joke should have a leadup and a punchline.
""".formatted(topic1, topic2, voice),
Joke.class);
}
}
Available in: Java & Kotlin | Concept: Basic Agent Workflow
A fun introduction to agent development that finds personalized news based on someone's star sign.
What It Teaches:
@Action annotations@AchievesGoalHow It Works:
Try It:
Start the agent shell, then type:
x "Find horoscope news for Alice who is a Gemini"
x is short for execute, which triggers the agent to run its workflow.
Code Comparison:
examples-kotlin/src/main/kotlin/com/embabel/example/horoscope/StarNewsFinder.ktexamples-java/src/main/java/com/embabel/example/horoscope/StarNewsFinder.javaKey Patterns:
@Agent(description = "Find news based on a person's star sign")
class StarNewsFinder {
@Action
fun extractPerson(userInput: UserInput, context: OperationContext): Person?
@Action(toolGroups = [CoreToolGroups.WEB])
fun findNewsStories(person: StarPerson, horoscope: Horoscope, context: OperationContext): RelevantNewsStories
@AchievesGoal(description = "Create an amusing writeup")
@Action
fun starNewsWriteup(/* params */): Writeup
}
Available in: Java, Kotlin | Concept: Self-Improving AI Workflows
A sophisticated research agent using multiple AI models with self-critique capabilities.
What It Teaches:
Architecture:
@ConfigurationProperties(prefix = "embabel.examples.researcher")
data class ResearcherProperties(
val maxWordCount: Int = 300,
val claudeModelName: String = AnthropicModels.CLAUDE_35_HAIKU,
val openAiModelName: String = OpenAiModels.GPT_41_MINI
)
Self-Improvement Pattern:
@Action(outputBinding = "gpt4Report")
fun researchWithGpt4(/* params */): SingleLlmReport
@Action(outputBinding = "claudeReport")
fun researchWithClaude(/* params */): SingleLlmReport
@Action(outputBinding = "mergedReport")
fun mergeReports(gpt4: SingleLlmReport, claude: SingleLlmReport): ResearchReport
@Action
fun critiqueReport(report: ResearchReport): Critique
@AchievesGoal(description = "Completes research with quality assurance")
fun acceptReport(report: ResearchReport, critique: Critique): ResearchReport
Try It:
"Research the latest developments in renewable energy adoption"
Location: examples-kotlin/src/main/kotlin/com/embabel/example/researcher/
Available in: Kotlin | Concept: Functional Agent Construction
A fact-verification agent built using Embabel's functional DSL approach instead of annotations.
What It Teaches:
DSL Construction:
fun factCheckerAgent(llms: List<LlmOptions>, properties: FactCheckerProperties) =
agent(name = "FactChecker", description = "Check content for factual accuracy") {
flow {
aggregate<UserInput, FactualAssertions, RationalizedFactualAssertions>(
transforms = llms.map { llm ->
{ context -> /* extract assertions with this LLM */ }
},
merge = { list, context -> /* rationalize overlapping claims */ }
)
}
transformation<RationalizedFactualAssertions, FactCheck> {
/* parallel fact-checking */
}
}
Domain Model:
data class FactualAssertion(
val claim: String,
val reasoning: String
)
data class AssertionCheck(
val assertion: FactualAssertion,
val isFactual: Boolean,
val confidence: Double,
val sources: List<String>
)
Try It:
"Check these facts: The Earth is flat. Paris is the capital of France."
Location: examples-kotlin/src/main/kotlin/com/embabel/example/factchecker/
Available in: Java & Kotlin | Concept: MCP Tool Access Control
Demonstrates JWT-secured MCP tool exposure using @SecureAgentTool. Each agent class
declares the Spring Security SpEL expression required to invoke any of its actions.
What It Teaches:
@SecureAgentTool@SecureAgentTool enforces per-agent authority checksAgents:
| Agent | Required authority | What it does |
|---|---|---|
NewsDigestAgent | news:read | Researches a topic via web search and returns a curated digest |
MarketIntelligenceAgent | market:admin | Produces a SWOT + competitive intelligence report |
Key Pattern:
@Agent(description = "Research a topic and return a news digest")
@SecureAgentTool("hasAuthority('news:read')") // protects every @Action in this agent
class NewsDigestAgent {
@Action // also requires news:read
fun extractTopic(userInput: UserInput, context: OperationContext): NewsTopic
@AchievesGoal(description = "Produce a curated news digest",
export = Export(remote = true, name = "newsDigest",
startingInputTypes = [UserInput::class]))
@Action // also requires news:read
fun produceDigest(topic: NewsTopic, context: OperationContext): NewsDigest
}
Run it:
cd scripts/kotlin && ./mcp_secured_server.sh
See Secured MCP Server Mode for token generation and MCP Inspector setup.
Code:
examples-kotlin/src/main/kotlin/com/embabel/example/secured/examples-java/src/main/java/com/embabel/example/secured/enable-shell, enable-shell-mcp-client, enable-agent-mcp-server@ConfigurationProperties@ConditionalOnBeantypealias OneThroughTen = Int)@Action chains@ConditionSome of our examples are projects in their own right, and are therefore in separate repositories.
See:
cd scripts/kotlin && ./shell.sh # With Docker tools (default)
cd scripts/kotlin && shell.cmd # With Docker tools (Windows)
# or
cd scripts/java && ./shell.sh # With Docker tools (default)
cd scripts/java && shell.cmd # With Docker tools (Windows)
Uses Maven profile: enable-shell-mcp-client
cd scripts/kotlin && ./shell.sh --no-docker-tools # Basic features only
cd scripts/kotlin && shell.cmd --no-docker-tools # Basic features (Windows)
# or
cd scripts/java && ./shell.sh --no-docker-tools # Basic features only
cd scripts/java && shell.cmd --no-docker-tools # Basic features (Windows)
Uses Maven profile: enable-shell
Enable distributed tracing with Zipkin by adding the --observability flag:
cd scripts/kotlin && ./shell.sh --observability # Enable observability
cd scripts/kotlin && shell.cmd --observability # Enable observability (Windows)
# or
cd scripts/java && ./shell.sh --observability # Enable observability
cd scripts/java && shell.cmd --observability # Enable observability (Windows)
Make sure to run docker compose up in the project root to start Zipkin trace collector:
docker compose up
You should be able to access Zipkin Console: http://127.0.0.1:9411/zipkin/
cd scripts/kotlin && ./mcp_server.sh
cd scripts/kotlin && mcp_server.cmd # Windows
# or
cd scripts/java && ./mcp_server.sh
cd scripts/java && mcp_server.cmd # Windows
Uses Maven profile: enable-agent-mcp-server
cd scripts/kotlin && ./mcp_secured_server.sh
cd scripts/kotlin && mcp_secured_server.cmd # Windows
Uses Maven profile: enable-secured-agent-mcp-server
See Secured MCP Server Mode for token setup and connection instructions.
You can use the Embabel agent platform as an MCP server from a UI like Claude Desktop. The Embabel MCP server is available over SSE.
Configure Claude Desktop as follows in your claude_desktop_config.yml:
{
"mcpServers": {
"embabel-examples": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://localhost:8080/sse"
]
}
}
}
See MCP Quickstart for Claude Desktop Users for how to configure Claude Desktop.
Create a project in Claude Desktop to work with Embabel examples. This will enable you to add a custom system prompt.
The Embabel server will expose each goal as an MCP tool, enabling Claude Desktop to invoke them like this:
The MCP Inspector is a helpful tool for interacting with your Embabel SSE server, manually invoking tools and checking the exposed prompts and resources.
Start the MCP Inspector with:
npx @modelcontextprotocol/inspector
# Kotlin shell mode with MCP client (default)
cd examples-kotlin
mvn -P enable-shell-mcp-client spring-boot:run
# Kotlin shell mode without MCP client
cd examples-kotlin
mvn -P enable-shell spring-boot:run
# Kotlin MCP server mode
cd examples-kotlin
mvn -P enable-agent-mcp-server spring-boot:run
# Java equivalents use the same pattern
cd examples-java
mvn -P enable-shell-mcp-client spring-boot:run
# Run all tests
./mvnw test # Unix/Linux/macOS
mvnw.cmd test # Windows
# Module-specific tests
cd examples-kotlin && ../mvnw test
cd examples-java && ../mvnw test
MCP (Model Context Protocol) is an open protocol that enables AI assistants and applications to securely connect to data sources and tools. Embabel supports MCP in two ways:
Run your agents as an MCP server that exposes tools over Server-Sent Events (SSE):
# Start Kotlin agents as MCP server
cd scripts/kotlin && ./mcp_server.sh
# Start Java agents as MCP server
cd scripts/java && ./mcp_server.sh
Your agents become available as tools:
find_horoscope_newsresearch_topiccheck_factsRun a JWT-secured MCP server that enforces per-agent access control using @SecureAgentTool.
This mode requires a valid Bearer token on every MCP request.
# Start secured Kotlin agents as MCP server
cd scripts/kotlin && ./mcp_secured_server.sh
mcp_secured_server.cmd # Windows
Uses Maven profile: enable-secured-agent-mcp-server
The secured server exposes two agents, each requiring specific JWT authorities:
| Agent | Tool name | Required authority |
|---|---|---|
NewsDigestAgent | newsDigest | news:read |
MarketIntelligenceAgent | marketIntelligenceReport | market:admin |
All @Action methods in each agent are protected โ not just the goal-achieving action.
Intermediate steps like topic extraction and web research also require the authority,
so unauthorised callers cannot burn LLM tokens on partial execution.
A keypair and token generator script are included for local development:
# Generate RSA keypair (one-time setup, from the keys/ directory)
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
The keys directory is at:
examples-common/src/main/resources/keys/
Generate a token:
pip install pyjwt cryptography
cd examples-common/src/main/resources/keys
python generate_token.py
The generated token includes news:read and market:admin authorities.
Paste it into your MCP client as a Bearer <token> Authorization header.
Start MCP Inspector and connect with transport type SSE, URL http://localhost:8443/sse,
and Authorization header:
Bearer <your_token>
Security is enforced in two layers:
/sse/** and /mcp/** require a valid JWT (401 if missing or invalid)@SecureAgentTool โ each agent class declares the required authority; denied calls return a clean MCP error response without retryingThe secured Spring profile activates both layers. Without that profile, the server runs without authentication (standard MCP server mode).
Docker tools are enabled by default. To disable:
# Disable Docker MCP integration
cd scripts/kotlin && ./shell.sh --no-docker-tools
cd scripts/java && ./shell.sh --no-docker-tools
With Docker tools enabled, your agents can:
@SpringBootApplication
class MyAgentApplication
fun main(args: Array<String>) {
runApplication<MyAgentApplication>(*args)
}
Add the shell starter to your pom.xml:
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter-shell</artifactId>
</dependency>
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.example"])
class MyThemedAgentApplication
fun main(args: Array<String>) {
runApplication<MyThemedAgentApplication>(*args) {
setAdditionalProfiles("docker-ce") // Enable MCP client via profile
setDefaultProperties(
mapOf("embabel.agent.logging.personality" to LoggingThemes.STAR_WARS)
)
}
}
@SpringBootApplication
class MyMcpServerApplication
fun main(args: Array<String>) {
runApplication<MyMcpServerApplication>(*args)
}
Add the MCP server starter to your pom.xml:
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter-mcpserver</artifactId>
</dependency>
| Problem | Solution |
|---|---|
| "No API keys found" | Set OPENAI_API_KEY or ANTHROPIC_API_KEY |
| Wrong examples load | Use correct script: kotlin/shell.sh vs java/shell.sh |
| Build failures | Run ./mvnw clean install (Unix/macOS) or mvnw.cmd clean install (Windows) from project root |
| Application class not found | Check Maven profile matches application class |
| MCP client fails to connect | Check port availability and Docker Desktop status. See instructions on pulling models above. |
Look at the log output in the event of failure as it may contain hints as to the solution.
embabel-agent-examples/
โโโ examples-kotlin/ # ๐ Kotlin implementations
โ โโโ src/main/kotlin/com/embabel/example/
โ โ โโโ KotlinAgentShellApplication.kt # Shell + MCP client (default)
โ โ โโโ KotlinAgentSimpleShellApplication.kt # Shell without MCP
โ โ โโโ KotlinAgentMcpServerApplication.kt # MCP server mode
โ โ โโโ KotlinAgentSecuredMcpServerApplication.kt# ๐ Secured MCP server mode
โ โ โโโ horoscope/ # ๐ Beginner: Star news agent
โ โ โโโ secured/ # ๐ Expert: JWT-secured agents
โ โโโ pom.xml # Maven profiles for each mode
โ โโโ README.md # ๐ Kotlin-specific documentation
โ
โโโ examples-java/ # โ Java implementations
โ โโโ src/main/java/com/embabel/example/
โ โ โโโ JavaAgentShellApplication.java # Shell with themes
โ โ โโโ JavaAgentSimpleShellApplication.java # Shell without MCP
โ โ โโโ JavaMcpServerApplication.java # MCP server mode
โ โ โโโ horoscope/ # ๐ Beginner: Star news agent
โ โโโ README.md # ๐ Java-specific documentation
โ
โโโ examples-common/ # ๐ง Shared services & utilities
โโโ scripts/ # ๐ Quick-start scripts
โ โโโ kotlin/
โ โ โโโ shell.sh # Launch shell (--no-docker-tools to disable)
โ โ โโโ mcp_server.sh # Launch MCP server
โ โ โโโ mcp_secured_server.sh # Launch JWT-secured MCP server
โ โโโ java/
โ โ โโโ shell.sh # Launch shell (--no-docker-tools to disable)
โ โ โโโ mcp_server.sh # Launch MCP server
โ โโโ support/ # Shared script utilities
โ โโโ README.md # ๐ Scripts documentation
โโโ pom.xml # Parent Maven configuration
Licensed under the Apache License 2.0. See LICENSE for details.
๐ Happy coding with Spring Framework and agentic AI!
6 followers ยท starred Jul 2025
Java
60.7%
Kotlin
30.7%
Batchfile
4.3%
Shell
3.8%
Agent Framework Examples for Java and Kotlin Developers
Java
183
232 commits
updated Sep 16, 2026
ย ย ย ย
English ยท ็ฎไฝไธญๆ
Learn agentic AI development with Spring Framework and Java or Kotlin. These examples demonstrate building intelligent agents that can plan, execute workflows, use tools, and interact with humans.
This repository uses the latest Embabel snapshots to illustrate current best practice, whereas the Java and Kotlin template repositories s use the latest milestone release for greater stability. There may be some minor API incompatilibites and not everything you see here may work in your own project created from one of those templates, unless you upgrade the
embabel-agent.versionproperty in the POM file, as in this repository.
git clone https://github.com/embabel/embabel-agent-examples.git
cd embabel-agent-examples
./mvnw clean install # Unix/Linux/macOS
mvnw.cmd clean install # Windows
# Required (choose one or both)
export OPENAI_API_KEY="your_openai_key"
export ANTHROPIC_API_KEY="your_anthropic_key"
cd scripts/kotlin
./shell.sh # Unix/Linux/macOS - With Docker tools (default)
shell.cmd # Windows - With Docker tools (default)
./shell.sh --no-docker-tools # Unix/Linux/macOS - Basic features only
shell.cmd --no-docker-tools # Windows - Basic features only
cd scripts/java
./shell.sh # Unix/Linux/macOS - With Docker tools (default)
shell.cmd # Windows - With Docker tools (default)
./shell.sh --no-docker-tools # Unix/Linux/macOS - Basic features only
shell.cmd --no-docker-tools # Windows - Basic features only
You can create your own agent repo from our Java or Kotlin GitHub template by clicking the "Use this template" button.
You can also create your own Embabel agent project locally with our quick start tool, which allows some customization:
uvx --from git+https://github.com/embabel/project-creator.git project-creator
Choose Java or Kotlin and specify your project name and package name and you'll have an agent running in under a minute,
if you already have an OPENAI_API_KEY and have Maven installed.
embabel-agent-starterembabel-agent-starter-shellembabel-agent-starter-mcpserver@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.embabel.example"])
class KotlinAgentShellApplication
fun main(args: Array<String>) {
runApplication<KotlinAgentShellApplication>(*args) {
setDefaultProperties(
mapOf("embabel.agent.logging.personality" to LoggingThemes.STAR_WARS)
)
}
}
// Java version
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = {"com.embabel.example"})
public class JavaAgentShellApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(JavaAgentShellApplication.class);
app.setDefaultProperties(Map.of(
"embabel.agent.logging.personality", LoggingThemes.STAR_WARS
));
app.run(args);
}
}
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.embabel.example"])
class KotlinAgentShellApplication
fun main(args: Array<String>) {
runApplication<KotlinAgentShellApplication>(*args) {
setAdditionalProfiles(McpServers.DOCKER) // Activates application-docker-ce.yml
setDefaultProperties(
mapOf("embabel.agent.logging.personality" to LoggingThemes.SEVERANCE)
)
}
}
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.embabel.example"])
class KotlinAgentMcpServerApplication
fun main(args: Array<String>) {
runApplication<KotlinAgentMcpServerApplication>(*args) {
setAdditionalProfiles(McpServers.DOCKER, McpServers.DOCKER_DESKTOP)
}
}
Set via the embabel.agent.logging.personality property:
"starwars" - May the Force be with your logs!"severance" - Welcome to Lumon Industries (default)Configure via Spring profiles that define Spring AI MCP client connections in application-{profile}.yml:
# application-docker-ce.yml
spring:
ai:
mcp:
client:
type: SYNC
stdio:
connections:
docker-mcp:
command: docker
args: [mcp, gateway, run]
Several of the examples use the Model Context Protocol (MCP) to access tools and services.
The default source is the Docker Desktop MCP server, which is installed with Docker Desktop.
To ensure tools are available and startup doesn't time out, first pull models with:
docker login
docker mcp gateway run
When the gateway has come up you can kill it and start the Embabel server.
Available in: Java | Concept: Just a Little AI
Demonstrates how you can inject any Spring component with an Embabel OperationContext
and use it to call LLMs with the rich Embabel API.
@Component
public record InjectedComponent(Ai ai) {
public record Joke(String leadup, String punchline) {
}
public String tellJokeAbout(String topic) {
return ai
.withDefaultLlm()
.generateText("Tell me a joke about " + topic);
}
public Joke createJokeObjectAbout(String topic1, String topic2, String voice) {
return ai
.withLlm(LlmOptions.withDefaultLlm().withTemperature(.8))
.createObject("""
Tell me a joke about %s and %s.
The voice of the joke should be %s.
The joke should have a leadup and a punchline.
""".formatted(topic1, topic2, voice),
Joke.class);
}
}
Available in: Java & Kotlin | Concept: Basic Agent Workflow
A fun introduction to agent development that finds personalized news based on someone's star sign.
What It Teaches:
@Action annotations@AchievesGoalHow It Works:
Try It:
Start the agent shell, then type:
x "Find horoscope news for Alice who is a Gemini"
x is short for execute, which triggers the agent to run its workflow.
Code Comparison:
examples-kotlin/src/main/kotlin/com/embabel/example/horoscope/StarNewsFinder.ktexamples-java/src/main/java/com/embabel/example/horoscope/StarNewsFinder.javaKey Patterns:
@Agent(description = "Find news based on a person's star sign")
class StarNewsFinder {
@Action
fun extractPerson(userInput: UserInput, context: OperationContext): Person?
@Action(toolGroups = [CoreToolGroups.WEB])
fun findNewsStories(person: StarPerson, horoscope: Horoscope, context: OperationContext): RelevantNewsStories
@AchievesGoal(description = "Create an amusing writeup")
@Action
fun starNewsWriteup(/* params */): Writeup
}
Available in: Java, Kotlin | Concept: Self-Improving AI Workflows
A sophisticated research agent using multiple AI models with self-critique capabilities.
What It Teaches:
Architecture:
@ConfigurationProperties(prefix = "embabel.examples.researcher")
data class ResearcherProperties(
val maxWordCount: Int = 300,
val claudeModelName: String = AnthropicModels.CLAUDE_35_HAIKU,
val openAiModelName: String = OpenAiModels.GPT_41_MINI
)
Self-Improvement Pattern:
@Action(outputBinding = "gpt4Report")
fun researchWithGpt4(/* params */): SingleLlmReport
@Action(outputBinding = "claudeReport")
fun researchWithClaude(/* params */): SingleLlmReport
@Action(outputBinding = "mergedReport")
fun mergeReports(gpt4: SingleLlmReport, claude: SingleLlmReport): ResearchReport
@Action
fun critiqueReport(report: ResearchReport): Critique
@AchievesGoal(description = "Completes research with quality assurance")
fun acceptReport(report: ResearchReport, critique: Critique): ResearchReport
Try It:
"Research the latest developments in renewable energy adoption"
Location: examples-kotlin/src/main/kotlin/com/embabel/example/researcher/
Available in: Kotlin | Concept: Functional Agent Construction
A fact-verification agent built using Embabel's functional DSL approach instead of annotations.
What It Teaches:
DSL Construction:
fun factCheckerAgent(llms: List<LlmOptions>, properties: FactCheckerProperties) =
agent(name = "FactChecker", description = "Check content for factual accuracy") {
flow {
aggregate<UserInput, FactualAssertions, RationalizedFactualAssertions>(
transforms = llms.map { llm ->
{ context -> /* extract assertions with this LLM */ }
},
merge = { list, context -> /* rationalize overlapping claims */ }
)
}
transformation<RationalizedFactualAssertions, FactCheck> {
/* parallel fact-checking */
}
}
Domain Model:
data class FactualAssertion(
val claim: String,
val reasoning: String
)
data class AssertionCheck(
val assertion: FactualAssertion,
val isFactual: Boolean,
val confidence: Double,
val sources: List<String>
)
Try It:
"Check these facts: The Earth is flat. Paris is the capital of France."
Location: examples-kotlin/src/main/kotlin/com/embabel/example/factchecker/
Available in: Java & Kotlin | Concept: MCP Tool Access Control
Demonstrates JWT-secured MCP tool exposure using @SecureAgentTool. Each agent class
declares the Spring Security SpEL expression required to invoke any of its actions.
What It Teaches:
@SecureAgentTool@SecureAgentTool enforces per-agent authority checksAgents:
| Agent | Required authority | What it does |
|---|---|---|
NewsDigestAgent | news:read | Researches a topic via web search and returns a curated digest |
MarketIntelligenceAgent | market:admin | Produces a SWOT + competitive intelligence report |
Key Pattern:
@Agent(description = "Research a topic and return a news digest")
@SecureAgentTool("hasAuthority('news:read')") // protects every @Action in this agent
class NewsDigestAgent {
@Action // also requires news:read
fun extractTopic(userInput: UserInput, context: OperationContext): NewsTopic
@AchievesGoal(description = "Produce a curated news digest",
export = Export(remote = true, name = "newsDigest",
startingInputTypes = [UserInput::class]))
@Action // also requires news:read
fun produceDigest(topic: NewsTopic, context: OperationContext): NewsDigest
}
Run it:
cd scripts/kotlin && ./mcp_secured_server.sh
See Secured MCP Server Mode for token generation and MCP Inspector setup.
Code:
examples-kotlin/src/main/kotlin/com/embabel/example/secured/examples-java/src/main/java/com/embabel/example/secured/enable-shell, enable-shell-mcp-client, enable-agent-mcp-server@ConfigurationProperties@ConditionalOnBeantypealias OneThroughTen = Int)@Action chains@ConditionSome of our examples are projects in their own right, and are therefore in separate repositories.
See:
cd scripts/kotlin && ./shell.sh # With Docker tools (default)
cd scripts/kotlin && shell.cmd # With Docker tools (Windows)
# or
cd scripts/java && ./shell.sh # With Docker tools (default)
cd scripts/java && shell.cmd # With Docker tools (Windows)
Uses Maven profile: enable-shell-mcp-client
cd scripts/kotlin && ./shell.sh --no-docker-tools # Basic features only
cd scripts/kotlin && shell.cmd --no-docker-tools # Basic features (Windows)
# or
cd scripts/java && ./shell.sh --no-docker-tools # Basic features only
cd scripts/java && shell.cmd --no-docker-tools # Basic features (Windows)
Uses Maven profile: enable-shell
Enable distributed tracing with Zipkin by adding the --observability flag:
cd scripts/kotlin && ./shell.sh --observability # Enable observability
cd scripts/kotlin && shell.cmd --observability # Enable observability (Windows)
# or
cd scripts/java && ./shell.sh --observability # Enable observability
cd scripts/java && shell.cmd --observability # Enable observability (Windows)
Make sure to run docker compose up in the project root to start Zipkin trace collector:
docker compose up
You should be able to access Zipkin Console: http://127.0.0.1:9411/zipkin/
cd scripts/kotlin && ./mcp_server.sh
cd scripts/kotlin && mcp_server.cmd # Windows
# or
cd scripts/java && ./mcp_server.sh
cd scripts/java && mcp_server.cmd # Windows
Uses Maven profile: enable-agent-mcp-server
cd scripts/kotlin && ./mcp_secured_server.sh
cd scripts/kotlin && mcp_secured_server.cmd # Windows
Uses Maven profile: enable-secured-agent-mcp-server
See Secured MCP Server Mode for token setup and connection instructions.
You can use the Embabel agent platform as an MCP server from a UI like Claude Desktop. The Embabel MCP server is available over SSE.
Configure Claude Desktop as follows in your claude_desktop_config.yml:
{
"mcpServers": {
"embabel-examples": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"http://localhost:8080/sse"
]
}
}
}
See MCP Quickstart for Claude Desktop Users for how to configure Claude Desktop.
Create a project in Claude Desktop to work with Embabel examples. This will enable you to add a custom system prompt.
The Embabel server will expose each goal as an MCP tool, enabling Claude Desktop to invoke them like this:
The MCP Inspector is a helpful tool for interacting with your Embabel SSE server, manually invoking tools and checking the exposed prompts and resources.
Start the MCP Inspector with:
npx @modelcontextprotocol/inspector
# Kotlin shell mode with MCP client (default)
cd examples-kotlin
mvn -P enable-shell-mcp-client spring-boot:run
# Kotlin shell mode without MCP client
cd examples-kotlin
mvn -P enable-shell spring-boot:run
# Kotlin MCP server mode
cd examples-kotlin
mvn -P enable-agent-mcp-server spring-boot:run
# Java equivalents use the same pattern
cd examples-java
mvn -P enable-shell-mcp-client spring-boot:run
# Run all tests
./mvnw test # Unix/Linux/macOS
mvnw.cmd test # Windows
# Module-specific tests
cd examples-kotlin && ../mvnw test
cd examples-java && ../mvnw test
MCP (Model Context Protocol) is an open protocol that enables AI assistants and applications to securely connect to data sources and tools. Embabel supports MCP in two ways:
Run your agents as an MCP server that exposes tools over Server-Sent Events (SSE):
# Start Kotlin agents as MCP server
cd scripts/kotlin && ./mcp_server.sh
# Start Java agents as MCP server
cd scripts/java && ./mcp_server.sh
Your agents become available as tools:
find_horoscope_newsresearch_topiccheck_factsRun a JWT-secured MCP server that enforces per-agent access control using @SecureAgentTool.
This mode requires a valid Bearer token on every MCP request.
# Start secured Kotlin agents as MCP server
cd scripts/kotlin && ./mcp_secured_server.sh
mcp_secured_server.cmd # Windows
Uses Maven profile: enable-secured-agent-mcp-server
The secured server exposes two agents, each requiring specific JWT authorities:
| Agent | Tool name | Required authority |
|---|---|---|
NewsDigestAgent | newsDigest | news:read |
MarketIntelligenceAgent | marketIntelligenceReport | market:admin |
All @Action methods in each agent are protected โ not just the goal-achieving action.
Intermediate steps like topic extraction and web research also require the authority,
so unauthorised callers cannot burn LLM tokens on partial execution.
A keypair and token generator script are included for local development:
# Generate RSA keypair (one-time setup, from the keys/ directory)
openssl genrsa -out private.pem 2048
openssl rsa -in private.pem -pubout -out public.pem
The keys directory is at:
examples-common/src/main/resources/keys/
Generate a token:
pip install pyjwt cryptography
cd examples-common/src/main/resources/keys
python generate_token.py
The generated token includes news:read and market:admin authorities.
Paste it into your MCP client as a Bearer <token> Authorization header.
Start MCP Inspector and connect with transport type SSE, URL http://localhost:8443/sse,
and Authorization header:
Bearer <your_token>
Security is enforced in two layers:
/sse/** and /mcp/** require a valid JWT (401 if missing or invalid)@SecureAgentTool โ each agent class declares the required authority; denied calls return a clean MCP error response without retryingThe secured Spring profile activates both layers. Without that profile, the server runs without authentication (standard MCP server mode).
Docker tools are enabled by default. To disable:
# Disable Docker MCP integration
cd scripts/kotlin && ./shell.sh --no-docker-tools
cd scripts/java && ./shell.sh --no-docker-tools
With Docker tools enabled, your agents can:
@SpringBootApplication
class MyAgentApplication
fun main(args: Array<String>) {
runApplication<MyAgentApplication>(*args)
}
Add the shell starter to your pom.xml:
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter-shell</artifactId>
</dependency>
@SpringBootApplication
@ConfigurationPropertiesScan(basePackages = ["com.example"])
class MyThemedAgentApplication
fun main(args: Array<String>) {
runApplication<MyThemedAgentApplication>(*args) {
setAdditionalProfiles("docker-ce") // Enable MCP client via profile
setDefaultProperties(
mapOf("embabel.agent.logging.personality" to LoggingThemes.STAR_WARS)
)
}
}
@SpringBootApplication
class MyMcpServerApplication
fun main(args: Array<String>) {
runApplication<MyMcpServerApplication>(*args)
}
Add the MCP server starter to your pom.xml:
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter-mcpserver</artifactId>
</dependency>
| Problem | Solution |
|---|---|
| "No API keys found" | Set OPENAI_API_KEY or ANTHROPIC_API_KEY |
| Wrong examples load | Use correct script: kotlin/shell.sh vs java/shell.sh |
| Build failures | Run ./mvnw clean install (Unix/macOS) or mvnw.cmd clean install (Windows) from project root |
| Application class not found | Check Maven profile matches application class |
| MCP client fails to connect | Check port availability and Docker Desktop status. See instructions on pulling models above. |
Look at the log output in the event of failure as it may contain hints as to the solution.
embabel-agent-examples/
โโโ examples-kotlin/ # ๐ Kotlin implementations
โ โโโ src/main/kotlin/com/embabel/example/
โ โ โโโ KotlinAgentShellApplication.kt # Shell + MCP client (default)
โ โ โโโ KotlinAgentSimpleShellApplication.kt # Shell without MCP
โ โ โโโ KotlinAgentMcpServerApplication.kt # MCP server mode
โ โ โโโ KotlinAgentSecuredMcpServerApplication.kt# ๐ Secured MCP server mode
โ โ โโโ horoscope/ # ๐ Beginner: Star news agent
โ โ โโโ secured/ # ๐ Expert: JWT-secured agents
โ โโโ pom.xml # Maven profiles for each mode
โ โโโ README.md # ๐ Kotlin-specific documentation
โ
โโโ examples-java/ # โ Java implementations
โ โโโ src/main/java/com/embabel/example/
โ โ โโโ JavaAgentShellApplication.java # Shell with themes
โ โ โโโ JavaAgentSimpleShellApplication.java # Shell without MCP
โ โ โโโ JavaMcpServerApplication.java # MCP server mode
โ โ โโโ horoscope/ # ๐ Beginner: Star news agent
โ โโโ README.md # ๐ Java-specific documentation
โ
โโโ examples-common/ # ๐ง Shared services & utilities
โโโ scripts/ # ๐ Quick-start scripts
โ โโโ kotlin/
โ โ โโโ shell.sh # Launch shell (--no-docker-tools to disable)
โ โ โโโ mcp_server.sh # Launch MCP server
โ โ โโโ mcp_secured_server.sh # Launch JWT-secured MCP server
โ โโโ java/
โ โ โโโ shell.sh # Launch shell (--no-docker-tools to disable)
โ โ โโโ mcp_server.sh # Launch MCP server
โ โโโ support/ # Shared script utilities
โ โโโ README.md # ๐ Scripts documentation
โโโ pom.xml # Parent Maven configuration
Licensed under the Apache License 2.0. See LICENSE for details.
๐ Happy coding with Spring Framework and agentic AI!
6 followers ยท starred Jul 2025
Java
60.7%
Kotlin
30.7%
Batchfile
4.3%
Shell
3.8%