A practical example demonstrating how to use Rod Johnson's embabel framework to add AI-powered customer support agents to existing Java Spring Boot applications.
Embabel is an innovative framework that allows you to create agentic AI systems using Java annotations. Instead of writing complex orchestration code, you define agent behavior declaratively using annotations like @Agent, @Action, and @Condition.
This repository shows how to integrate embabel into a traditional Spring Boot e-commerce application to handle customer refunds and replacements automatically.
- Java 21 or higher
- LLM API Key - Either OpenAI or Anthropic API key required for LLM operations
The embabel framework requires either an OpenAI or Anthropic API key to function. Choose one:
For OpenAI:
export OPENAI_API_KEY=your-openai-api-key-hereFor Anthropic:
export ANTHROPIC_API_KEY=your-anthropic-api-key-hereOr on Windows:
set OPENAI_API_KEY=your-openai-api-key-here
# OR
set ANTHROPIC_API_KEY=your-anthropic-api-key-heregit clone <this-repo>
cd ecommerce-demo
./mvnw spring-boot:runThe application will start on port 8080.
You can interact with the agent in two ways:
Option A: Using the Interactive Shell
To use the shell version, you need to modify the Application.java file:
- Comment out
@EnableAgentMcpServeron line 10 - Uncomment
@EnableAgentShellon line 11
Then run:
./scripts/shell.shThis starts an interactive shell where you can chat directly with the customer support agent. Once the shell is open, prefix your messages with x followed by your request:
x "Hello! I'd like to return order ORD-123."
Option B: MCP Server (for Claude Desktop integration)
The agent is also available at http://localhost:8080/sse and can handle customer requests like:
- "I need a refund for order ORD-123"
- "Can I get a replacement for order ORD-456?"
- "I'm angry about my order ORD-789, I want my money back!"
@Agent(
name = "Customer Support Agent",
description = "Assists customers with refunds and replacements"
)
public class CustomerSupportAgent {
// Agent implementation
}@Action
ParsedRequest parseRequest(UserInput userInput, OperationContext context) {
// Uses LLM to extract order ID, operation type, and sentiment
}
@Action(pre = "shouldReplace")
OrderAdjustmentResponse processReplacement(OrderSearchResult searchResult) {
// Only executes if shouldReplace condition is true
}@Condition(name = "shouldReplace")
public boolean shouldReplace(ParsedRequest request, OrderSearchResult result) {
boolean wantsReplacement = OperationType.REPLACE.equals(request.operationType());
boolean hasInventory = inventoryService.getQuantity(result.order().sku()) > 0;
return hasInventory && wantsReplacement;
}@AchievesGoal(
export = @Export(
name = "refundOrReplaceOrder",
remote = true,
startingInputTypes = {UserInput.class}
)
)To interact with the agent through Claude Desktop, add this to your claude_desktop_config.json:
{
"mcpServers": {
"customer-support": {
"command": "npx",
"args": ["-y", "mcp-remote", "http://localhost:8080/sse"]
}
}
}Then restart Claude Desktop and you can chat with the customer support agent directly.
src/main/java/com/kylehoehns/ecommerce/
├── agent/
│ ├── CustomerSupportAgent.java # Main embabel agent
│ ├── OperationType.java # REFUND/REPLACE enum
│ └── Sentiment.java # POSITIVE/NEUTRAL/NEGATIVE enum
├── order/ # Order management services
├── inventory/ # Inventory management
└── Application.java # Spring Boot app with @EnableAgentMcpServer
-
Input Processing: Customer requests are parsed using LLM to extract:
- Order ID
- Desired operation (refund/replacement)
- Customer sentiment
-
Business Logic: The agent checks:
- If the order exists
- Current inventory levels
- Customer preferences
-
Decision-Making: Based on conditions:
- Replacements are offered if inventory is available
- Refunds are processed if no inventory or customer prefers refund
-
Response Generation: LLM generates personalized responses considering customer sentiment
- GitHub Repository: embabel-agent
- Rod Johnson's Blog: Medium @springrod - Contains in-depth examples and tutorials
- Framework Documentation: Available in the embabel-agent repository
While the agent handles most operations, you can also interact with the underlying services:
# Check inventory
curl http://localhost:8080/api/inventory
# Create an order
curl -X POST http://localhost:8080/api/orders \
-H "Content-Type: application/json" \
-d '{"sku": "shirt-m"}'
# List orders
curl http://localhost:8080/api/ordersThe key embabel dependency is added to pom.xml:
<dependency>
<groupId>com.embabel.agent</groupId>
<artifactId>embabel-agent-starter</artifactId>
<version>0.1.1-SNAPSHOT</version>
</dependency>- Explore the
CustomerSupportAgent.javato understand embabel patterns - Try modifying conditions to change agent behavior
- Add new actions for additional customer support scenarios
- Read Rod Johnson's blog posts for advanced embabel techniques
- Check out the embabel-agent repository for more examples