A distributed microservices architecture implementing the Saga Pattern with AI-powered orchestration using LangChain4j. Three intelligent agents β powered by Gemini, Ollama, and pgvector β automatically diagnose failures, compose dynamic saga plans, and answer operational questions in natural language.
The system consists of 6 microservices communicating via Kafka and an AI agent service that connects to all of them via MCP (Model Context Protocol).
βββββββββββββββββββββββ
β ai-saga-agent β
β port: 8099 β
β Gemini Β· MCP Β· RAG β
ββββββββββ¬βββββββββββββ
β MCP (HTTP/SSE)
βββββββββββββββ¬ββββββββΌβββββββββ¬βββββββββββββββ
βΌ βΌ βΌ βΌ βΌ
ββββββββββββββββ ββββββββββββ βββββββββββββββ βββββββββββββββββββ
β order-serviceβ βorchestr. β βpayment-svc β βinventory-svc β
β port: 3000 β βport: 8050β βport: 8091 β βport: 8092 β
β MongoDB β βRedis β βPostgreSQL β βPostgreSQL β
ββββββββββββββββ ββββββββββββ βββββββββββββββ βββββββββββββββββββ
βββββββββββββββββββ
βproduct-valid-svc β
βport: 8090 β
βPostgreSQL β
βββββββββββββββββββ
Order Service β Orchestrator β Product Validation β
β Payment β
β Inventory β
β Finish Success
If any step fails, compensating transactions roll back the previous steps automatically.
| Agent | Trigger | What it does | Storage |
|---|---|---|---|
| OperationsAgent | Kafka notify-ending (FAIL) |
Auto-diagnoses saga failures using RAG over historical incidents | pgvector + PostgreSQL |
| SagaComposerAgent | Scheduled (every 60s dev / 30min prod) | Decides optimal step order per customer profile | Redis saga-plan:{profile} |
| DataAnalystAgent | HTTP GET /api/agent/chat?question=... |
Answers operational questions in natural language via MCP tools | Human-readable response |
Before running the project, make sure you have the following installed:
| Tool | Version | Purpose |
|---|---|---|
| Java JDK | 21+ | All microservices |
| Docker & Docker Compose | Latest | Databases, Kafka, Redis |
| Ollama | Latest | Local embedding model (nomic-embed-text) |
| Gemini API Key | β | Primary LLM for agents (free tier available) |
| Tool | Version | Purpose |
|---|---|---|
| Claude API Key | β | Alternative LLM provider |
| Gradle | 8.11+ | Included via wrapper (./gradlew) |
The AI agent service requires at least one LLM API key. The default configuration uses Gemini.
- Go to Google AI Studio
- Create a new API key
- Export it as an environment variable:
export GEMINI_API_KEY=your-gemini-api-key-hereIf you want to use Claude as the LLM provider:
- Get an API key from Anthropic Console
- Export it:
export CLAUDE_API_KEY=your-claude-api-key-hereThen change the primary model in ai-saga-agent/src/main/resources/application.yml:
ai:
primary-model: claude # change from 'gemini' to 'claude'Ollama runs locally and is used for generating embeddings (RAG). It's free and no API key is needed.
# Install Ollama
brew install ollama # macOS
# or: curl -fsSL https://ollama.ai/install.sh | sh # Linux
# Pull the embedding model
ollama pull nomic-embed-text
# Start the Ollama server
ollama serve
# API runs at http://localhost:11434There are two ways to run the project. In both cases, the ai-saga-agent runs outside Docker (it needs access to Ollama and your API keys).
Runs the 5 core microservices + all infrastructure in Docker. Only the AI agent runs locally.
β οΈ You must build the JARs before runningdocker-compose, because eachDockerfilecopies the pre-compiled JAR (COPY build/libs/*.jar app.jar). Without the build, the containers will fail.
# 1. Build all JARs (publishes saga-commons + compiles all services)
chmod +x build-all.sh
./build-all.sh
# 2. Start everything (infra + 5 microservices)
docker-compose up --build -d
# 3. Wait for all containers to be healthy, then start the AI agent separately
cd ai-saga-agent && GEMINI_API_KEY=your-key-here ./gradlew bootRunThis starts:
| Container | Port | Type |
|---|---|---|
order-db (MongoDB) |
27017 | Infrastructure |
product-db (PostgreSQL) |
5432 | Infrastructure |
payment-db (PostgreSQL) |
5433 | Infrastructure |
inventory-db (PostgreSQL) |
5434 | Infrastructure |
vectors-db (pgvector) |
5435 | Infrastructure |
redis |
6379 | Infrastructure |
kafka |
9092 | Infrastructure |
redpanda (Kafka UI) |
8081 | Infrastructure |
prometheus |
9090 | Monitoring |
grafana |
3001 | Monitoring |
order-service |
3000 | Microservice |
orchestrator-service |
8050 | Microservice |
product-validation-service |
8090 | Microservice |
payment-service |
8091 | Microservice |
inventory-service |
8092 | Microservice |
| ai-saga-agent (local) | 8099 | AI Agent (manual) |
Runs only infrastructure in Docker; all microservices run via Gradle. Useful for development and debugging.
# 1. Start only infrastructure (databases, Kafka, Redis)
docker-compose up -d order-db product-db payment-db inventory-db vectors-db redis kafka redpanda-console
# 2. Build everything
chmod +x build-all.sh
./build-all.sh
# 3. Start each service in a separate terminal
cd orchestrator-service && ./gradlew bootRun
cd product-validation-service && ./gradlew bootRun
cd payment-service && ./gradlew bootRun
cd inventory-service && ./gradlew bootRun
cd order-service && ./gradlew bootRun
# 4. Start the AI agent (requires GEMINI_API_KEY + Ollama running)
cd ai-saga-agent && GEMINI_API_KEY=your-key-here ./gradlew bootRuncurl http://localhost:3000/actuator/health # order-service
curl http://localhost:8050/actuator/health # orchestrator
curl http://localhost:8090/actuator/health # product-validation
curl http://localhost:8091/actuator/health # payment-service
curl http://localhost:8092/actuator/health # inventory-service
curl http://localhost:8099/actuator/health # ai-saga-agent./build-all.sh --parallel # Build all in parallel (faster)
./build-all.sh --with-tests # Include unit tests
./build-all.sh ai-saga-agent # Build only a specific service
./build-all.sh --help # Show all optionsπ¦ Ready-to-use request collection included! The repo contains a
Saga-Bruno.zipwith all API requests pre-configured. Import it into Bruno, Insomnia, or any OpenAPI-compatible client.
curl -X POST http://localhost:3000/api/orders \
-H "Content-Type: application/json" \
-d '{
"products": [
{
"product": { "code": "COMIC_BOOKS", "unitValue": 15.50 },
"quantity": 3
},
{
"product": { "code": "BOOKS", "unitValue": 9.90 },
"quantity": 1
}
],
"customerId": "customer-001",
"clientType": "new"
}'Valid product codes: COMIC_BOOKS, BOOKS, MOVIES, MUSIC
Open the Redpanda Console at http://localhost:8081 to see events flowing through topics.
# Natural language query via the DataAnalystAgent
curl "http://localhost:8099/api/agent/chat?question=List%20the%205%20most%20recent%20failed%20sagas%20and%20assess%20their%20fraud%20risk"# See all auto-generated failure diagnostics
curl http://localhost:8099/api/agent/diagnostics# See the AI-generated execution plans per customer profile
curl http://localhost:8099/api/agent/composer/planscurl -X GET http://localhost:3000/api/events/filters \
-H "Content-Type: application/json" \
-d '{ "orderId": "YOUR_ORDER_ID", "transactionId": "" }'You can test the MCP protocol manually against any service. First open an SSE session, then send JSON-RPC messages:
# 1. Open SSE session (returns a sessionId)
curl http://localhost:3000/sse
# 2. Initialize the MCP connection
curl -X POST "http://localhost:3000/mcp/message?sessionId=YOUR_SESSION_ID" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 1, "method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"clientInfo": { "name": "test-client", "version": "1.0.0" },
"capabilities": {}
}
}'
# 3. List available tools
curl -X POST "http://localhost:3000/mcp/message?sessionId=YOUR_SESSION_ID" \
-H "Content-Type: application/json" \
-d '{ "jsonrpc": "2.0", "id": 2, "method": "tools/list", "params": {} }'
# 4. Execute a tool
curl -X POST "http://localhost:3000/mcp/message?sessionId=YOUR_SESSION_ID" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0", "id": 3, "method": "tools/call",
"params": {
"name": "getStockByProduct",
"arguments": { "productCode": "COMIC_BOOKS" }
}
}'| Method | Endpoint | Description |
|---|---|---|
POST |
/api/orders |
Create a new order (triggers the saga) |
GET |
/api/events |
List all saga events |
GET |
/api/events/filters |
Filter events by orderId or transactionId |
Swagger UI available at: http://localhost:3000/swagger-ui/index.html
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/agent/chat?question=... |
Ask the DataAnalystAgent a natural language question |
GET |
/api/agent/diagnostics |
List all auto-generated failure diagnostics |
GET |
/api/agent/composer/plans |
View current AI-generated saga plans per profile |
| Service | SSE Endpoint | Message Endpoint |
|---|---|---|
| order-service | GET http://localhost:3000/sse |
POST http://localhost:3000/mcp/message?sessionId=... |
| product-validation | GET http://localhost:8090/sse |
POST http://localhost:8090/mcp/message?sessionId=... |
| payment-service | GET http://localhost:8091/sse |
POST http://localhost:8091/mcp/message?sessionId=... |
| inventory-service | GET http://localhost:8092/sse |
POST http://localhost:8092/mcp/message?sessionId=... |
saga-orchestration/
βββ saga-commons/ # Shared DTOs, enums, utilities (published to mavenLocal)
βββ order-service/ # REST API + MongoDB + Kafka producer
βββ orchestrator-service/ # Saga state machine + Redis plan lookup
βββ product-validation-service/ # Product catalog validation + MCP server
βββ payment-service/ # Payment + fraud scoring + MCP server
βββ inventory-service/ # Stock management + MCP server
βββ ai-saga-agent/ # 3 AI agents (Gemini + Ollama + pgvector + MCP client)
βββ docker-compose.yml # Full infrastructure stack
βββ build-all.sh # One-command build script
βββ bruno-collection.zip # Pre-configured API request collection
βββ readme.md
| Variable | Default | Required | Description |
|---|---|---|---|
GEMINI_API_KEY |
β | Yes (if using Gemini) | Google AI Gemini API key |
CLAUDE_API_KEY |
β | No | Anthropic Claude API key |
GEMINI_MODEL |
gemini-2.5-flash |
No | Gemini model name |
CLAUDE_MODEL |
claude-sonnet-4-20250514 |
No | Claude model name |
OLLAMA_BASE_URL |
http://localhost:11434 |
No | Ollama server URL |
OLLAMA_MODEL |
qwen3:8b |
No | Ollama chat model (for local inference) |
KAFKA_BROKER |
localhost:9092 |
No | Kafka bootstrap servers |
REDIS_HOST |
localhost |
No | Redis host |
VECTORS_DB_HOST |
localhost |
No | pgvector PostgreSQL host |
VECTORS_DB_PORT |
5435 |
No | pgvector PostgreSQL port |
MONGO_DB_URI |
mongodb://admin:123456@localhost:27017 |
No | MongoDB connection URI |
Edit ai-saga-agent/src/main/resources/application.yml:
ai:
primary-model: gemini # options: gemini, claude, ollama, ollama-no-thinkEach microservice exposes an MCP server over HTTP/SSE, making its business logic available as tools that any AI agent can discover and invoke.
| Service | MCP Endpoint | Available Tools |
|---|---|---|
| order-service | localhost:3000/sse |
getOrderById, listRecentEvents, getLastEventByOrder |
| payment-service | localhost:8091/sse |
getPaymentStatus, getRefundRate, getFraudRiskScore |
| inventory-service | localhost:8092/sse |
getStockByProduct, getLowStockAlert, checkReservationExists |
| product-validation | localhost:8090/sse |
checkProductExists, checkValidationExists, listCatalog |
The OperationsAgent vectorizes every saga event into pgvector using Ollama's nomic-embed-text model. When a saga fails, the agent searches for similar past incidents to enrich its diagnosis.
The SagaComposerAgent periodically analyzes system metrics and historical patterns, then writes optimized saga step sequences to Redis. The orchestrator reads these plans to decide the execution order per customer profile (e.g., running fraud validation before payment for new high-value customers).
| Layer | Technology |
|---|---|
| Language | Java 21 |
| Framework | Spring Boot 3.4 / 4.0 |
| AI SDK | LangChain4j 1.11 |
| LLM (cloud) | Google Gemini 2.5 Flash |
| LLM (local) | Ollama (qwen3:8b / nomic-embed-text) |
| Vector DB | PostgreSQL + pgvector |
| Messaging | Apache Kafka |
| Cache | Redis 7 |
| Databases | MongoDB, PostgreSQL |
| Build | Gradle |
| Containers | Docker Compose |
| Monitoring | Prometheus + Grafana |
Make sure all microservices are running before starting the ai-saga-agent. The agent tries to connect to MCP servers on startup.
- Verify
GEMINI_API_KEYis set and valid - Check that Ollama is running (
ollama serve) and thenomic-embed-textmodel is pulled - Increase
maxOutputTokensinChatModelConfig.javaif responses are truncated (default is 1024; use 4096 for complex queries)
All services depend on saga-commons. Run the build script or publish it manually:
cd saga-commons && ./gradlew publishToMavenLocalEnsure Kafka is fully started before launching services. Check Redpanda Console at http://localhost:8081.
- MCP > @Tool for microservices β reuse business logic across any agent without coupling
- SystemMessage alignment is critical β tools described in the prompt that don't exist cause silent failures
- JSON responses win over key=value β
ObjectMapper.writeValueAsString()is one line, zero bugs - Workflow instructions > tool descriptions β tell the agent HOW to use tools, not just WHAT they do
- maxOutputTokens matters β 1024 isn't enough for 5 sagas + fraud scores; use 4096
- Virtual threads are essential β
spring.threads.virtual.enabled=trueenables parallel MCP calls at no cost
Here are some enhancements and learning challenges to evolve the project:
- Implement Hexagonal Architecture (Ports & Adapters)
- Extract Kafka message contracts into a shared module
- Create integration tests using Embedded Kafka
- Add support for the Outbox pattern
- Implement Liquibase
- Add Micrometer + Prometheus metrics
- Implement structured logging with correlation IDs
- Publish Grafana dashboards
- Implement ELK for logs
- Add compensation logic in payment-service
- Support multi-step saga with dynamic ordering (e.g., payment β shipment β invoice)
- Add saga status endpoint
- Add JWT-based authentication
- Implement Oauth Server
- Restrict Kafka topic access with ACL or SASL
- Create Docker Compose environment (Kafka + PostgreSQL + Services)
- Set up CI/CD with GitHub Actions
- Add Kubernetes readiness and liveness probes
- Implement test with Jmeter
- Generate OpenAPI (Swagger) docs
- Include event orchestration sequence diagram
- Add guide for local mock testing
- Achieve 80%+ test coverage
- Implement to report to test coverage
- Add end-to-end tests with Testcontainers
- Introduce Domain Events and Event Sourcing
- Implement Saga Timeout Handling
- Support parallel saga steps
- Load saga flow from JSON/YAML config
- Use state machine library to manage saga steps
- Add retry and backoff policies for Kafka consumers
- Use circuit breakers
- Persist saga history in a dedicated table
- Configure Kafka Dead Letter Topics (DLT)
- Provide Postman or Insomnia collection
- Create mock implementations for dependencies
- Add Makefile or CLI utility scripts
- Build a saga dashboard UI (React/Vue)
- Make Kafka topics configurable per environment
- Add event sharding by saga ID
- Configure microservices for horizontal scaling
- Add multi-tenant support via headers or topics
- Support localization of logs and messages
- Add tenant-aware metrics and logs
Avro/Protobuf Integration
- Migrate from JSON to Avro or Protobuf
- Maintain a central schema repository
Schema Registry Setup
- Integrate Confluent Schema Registry (via Docker)
- Set appropriate subject naming strategy
- Secure access with basic auth or API keys
Validation & Compatibility
- Enforce schema compatibility rules (backward/forward)
- Add CI step for schema validation
- Test schema evolution scenarios
Development & Testing
- Use MockSchemaRegistry in tests
- Generate Avro classes from .avsc files
Monitoring
- Monitor schema usage with Confluent Control Center
- Log schema version and validation errors
β Saga Manager Dashboard
- Build a real-time dashboard for saga tracking
- Allow manual retry/restart of sagas
π§Ύ Audit & History
- Store full saga execution history
- Create endpoint to fetch history by saga ID
π€ Webhooks & Notifications
- Allow webhook subscriptions for saga completion
- Integrate with Slack or email for alerts
π§ Dynamic Orchestration
- Support saga definitions via JSON/YAML
- Design a DSL for saga steps and compensations
β»οΈ Manual Retry & Reprocessing
- Add endpoint to reprocess events by saga ID
- Support execution of compensation steps only
π Multi-Region & Partition Tolerance
- Support distributed saga execution across regions
- Use Kafka MirrorMaker 2.0 for topic replication
- LangChain4j docs: langchain4j.dev
Pedro Santos β LinkedIn