MultiAIAgent
- Anand Nerurkar
- Apr 14
- 4 min read
Scenario: AI-Powered Multi-Agent Banking Assistant
Use Case
A customer wants to:
Understand their loan eligibility
Get KYC updated
Learn about investment products
Raise a dispute for a transaction
Each task is handled by a specialized AI agent, collaborating to complete the user's end goal.
Agents Involved
Agent | Responsibility |
KYC Agent | Verifies documents, updates KYC |
Loan Agent | Checks eligibility, recommends loans |
Investment Agent | Suggests financial products |
Dispute Agent | Initiates dispute and tracks status |
Coordinator Agent | Orchestrates flow between other agents |
🔄 Interaction Flow
sql
User Input → Spring Boot API → Coordinator Agent
↘ Calls:
- Loan Agent
- KYC Agent
- Investment Agent
- Dispute Agent
↘ Aggregated Response → User
Each agent:
Uses tools like BankAPIWrapper, VectorSearchTool, or FormFillerTool
May delegate subtasks to another agent (e.g., Dispute Agent → KYC Agent for verification)
Talks through a message bus or task chain, either via LangChain agents or custom logic
Architecture Diagram Update (Conceptual)
+-------------------+
| Frontend (UI) |
+-------------------+
|
v
+-------------------+
| Spring Boot API |
+-------------------+
|
v
+------------------------+
| Coordinator Agent |
+------------------------+
| | | |
v v v v
+------+ +------+ +--------+ +-----------+
| KYC | | Loan | | Invest | | Dispute |
|Agent | |Agent | |Agent | |Agent |
+------+ +------+ +--------+ +-----------+
\ | /
\ | /
\ v /
+------------------+
| RAG + Core APIs |
+------------------+
Technologies to Enable This
Spring Boot – API Gateway & orchestration
LangChain or CrewAI – Multi-agent support (roles, tools, communication)
OpenAI / Azure OpenAI – GenAI backend
Redis or Message Bus – Agent messaging/state sharing
Pinecone / FAISS – RAG-based context grounding
Example Task
Prompt: “I want to update my KYC and check if I’m eligible for a home loan.”
Coordinator Agent triggers:
KYC Agent → Verifies via OCR + fetches user docs
Loan Agent → Calls Core Banking APIs to evaluate eligibility
Returns combined response like:"Your KYC is now verified. Based on your profile, you're eligible for a ₹45L home loan. Want to proceed?"
📁 Project Structure (Agent Services)
src/main/java/com/bankgenai/agents
│
├── controller/
│ └── AssistantController.java
│
├── service/
│ ├── CoordinatorAgentService.java
│ ├── KycAgentService.java
│ ├── LoanAgentService.java
│ ├── InvestmentAgentService.java
│ └── DisputeAgentService.java
│
└── model/
├── AgentRequest.java
model/AgentRequest.java
java
public class AgentRequest {
private String userId;
private String query;
// Additional metadata if needed
}
📦 model/AgentResponse.java
java
public class AgentResponse {
private String agentName;
private String response;
}
java
@Service
public class KycAgentService {
public AgentResponse handleKyc(String userId) {
// Simulate OCR/KYC update logic
String result = "KYC verified successfully for user " + userId;
return new AgentResponse("KYC_AGENT", result);
}
}
java
@Service
public class LoanAgentService {
public AgentResponse evaluateLoan(String userId) {
// Simulate loan eligibility logic
String loanInfo = "Eligible for a ₹45L home loan based on income.";
return new AgentResponse("LOAN_AGENT", loanInfo);
}
}
java
@Service
public class InvestmentAgentService {
public AgentResponse suggestInvestments(String userId) {
String suggestion = "Recommended: SIP in large cap mutual funds.";
return new AgentResponse("INVESTMENT_AGENT", suggestion);
}
}
java
@Service
public class DisputeAgentService {
public AgentResponse handleDispute(String userId, String transactionId) {
String response = "Dispute raised for transaction ID " + transactionId;
return new AgentResponse("DISPUTE_AGENT", response);
}
}
java
@Service
@RequiredArgsConstructor
public class CoordinatorAgentService {
private final KycAgentService kycAgent;
private final LoanAgentService loanAgent;
private final InvestmentAgentService investmentAgent;
private final DisputeAgentService disputeAgent;
public List<AgentResponse> processUserQuery(String userId, String query) {
List<AgentResponse> responses = new ArrayList<>();
if (query.toLowerCase().contains("kyc")) {
responses.add(kycAgent.handleKyc(userId));
}
if (query.toLowerCase().contains("loan")) {
responses.add(loanAgent.evaluateLoan(userId));
}
if (query.toLowerCase().contains("invest")) {
responses.add(investmentAgent.suggestInvestments(userId));
}
if (query.toLowerCase().contains("dispute")) {
// extract transaction ID in real implementation
responses.add(disputeAgent.handleDispute(userId, "TXN12345"));
}
return responses;
}
}
java
@RestController
@RequestMapping("/api/assistant")
@RequiredArgsConstructor
public class AssistantController {
private final CoordinatorAgentService coordinatorAgent;
@PostMapping("/ask")
public ResponseEntity<List<AgentResponse>> handleQuery(@RequestBody AgentRequest request) {
List<AgentResponse> results = coordinatorAgent.processUserQuery(request.getUserId(), request.getQuery());
return ResponseEntity.ok(results);
}
}
External API connectors or LangChain agent logic
To integrate external API connectors or LangChain agent logic into your multi-agent Spring Boot banking system, we can follow these steps:
1. Adding External API Connectors
For example, let's connect to a third-party KYC API for verification or an external loan evaluation API.
We'll use RestTemplate or WebClient (for non-blocking calls) to make API requests.
This service will integrate with external KYC and Loan APIs.
java
package com.bankgenai.service;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.reactive.function.client.WebClient;
@Service
public class ExternalApiService {
@Value("${external.api.kyc.url}")
private String kycApiUrl;
@Value("${external.api.loan.url}")
private String loanApiUrl;
private final RestTemplate restTemplate;
private final WebClient webClient;
public ExternalApiService(RestTemplate restTemplate, WebClient.Builder webClientBuilder) {
this.restTemplate = restTemplate;
this.webClient = webClientBuilder.baseUrl("http://external-api.com").build();
}
// KYC verification through external API
public String verifyKyc(String userId) {
String response = restTemplate.getForObject(kycApiUrl + "/verify/" + userId, String.class);
return response;
}
// Loan eligibility check via external API
public String checkLoanEligibility(String userId) {
return webClient.get()
.uri(loanApiUrl + "/loan-check/" + userId)
.retrieve()
.bodyToMono(String.class)
.block();
}
}
📦 Application Properties (application.yml)
yaml
external:
api:
kyc:
url: "https://external-kyc-api.com"
loan:
url: "https://external-loan-api.com"
2. Adding LangChain Logic
LangChain is a framework designed for building LLM-powered applications. We can integrate it to create intelligent agents that can interact with various APIs and process tasks like loan evaluation, dispute resolution, etc.
To add LangChain-like behavior in Java, we need to integrate a LangChain-like service that processes requests via LLMs, like OpenAI or Anthropic, while incorporating API calls. Here’s a general pattern:
Here we define a LangChain Agent to process customer queries with external APIs:
java
3. Integrating LangChain with Spring Boot Controller
Now, integrate the LangChainService with the existing controller logic.
java
package com.bankgenai.controller;
import com.bankgenai.service.LangChainService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/assistant")
@RequiredArgsConstructor
public class AssistantController {
private final LangChainService langChainService;
@PostMapping("/ask")
public String handleQuery(@RequestBody String query) {
return langChainService.processCustomerQuery("user123", query);
}
}
4. Handling Long-running API Calls with Async Logic (Optional)
For better performance, especially with long-running calls, you can use asynchronous APIs. For example, make API calls with @Async annotations and CompletableFuture in Spring Boot.
Example of an asynchronous call in the ExternalApiService.java:
java
import org.springframework.scheduling.annotation.Async;
import java.util.concurrent.CompletableFuture;
@Service
public class ExternalApiService {
@Async
public CompletableFuture<String> verifyKycAsync(String userId) {
String response = restTemplate.getForObject(kycApiUrl + "/verify/" + userId, String.class);
return CompletableFuture.completedFuture(response);
}
}
5. Dockerize the Application (Optional)
To run this service in a containerized environment, you'll need a Dockerfile.
dockerfile
# Use OpenJDK 17 image for the Java application
FROM openjdk:17-jdk-alpine
# Set the working directory
WORKDIR /app
# Copy the compiled jar file
COPY target/banking-genai-application.jar /app/banking-genai-application.jar
# Expose the port
EXPOSE 8080
# Run the application
CMD ["java", "-jar", "banking-genai-application.jar"]
Comments