AI Agent là gì? Giải thích chi tiết kèm ví dụ Java
1. Tổng quan
“AI Agent” là từ khóa xuất hiện khắp nơi nhưng định nghĩa thường mơ hồ: có người gọi mọi chatbot là agent, có người chỉ coi hệ thống đa bước phức tạp mới là agent thật. Bài này giải thích rõ AI Agent là gì, các thành phần bắt buộc phải có, và cơ chế vòng lặp đứng sau nó. Đọc xong, bạn sẽ tự dựng được một agent tối giản bằng Java thuần để hiểu “ruột gan” nó hoạt động ra sao, rồi nâng cấp lên bản dùng LLM thật với Spring AI.
2. AI Agent là gì?
Định nghĩa ngắn gọn: AI Agent là một hệ thống dùng LLM làm bộ não để tự quyết định hành động nhằm đạt một mục tiêu, thay vì chỉ trả lời một câu hỏi rồi dừng lại.
Phân biệt với chatbot thông thường:
| Đặc điểm | Chatbot thường | AI Agent |
|---|---|---|
| Số lượt xử lý | 1 lượt: hỏi → trả lời | Nhiều bước: quan sát → suy luận → hành động → lặp lại |
| Có gọi tool/API không | Thường không | Có, tự quyết định gọi tool nào |
| Có mục tiêu dài hạn | Không | Có, agent tự chia nhỏ việc để đạt mục tiêu |
| Ví dụ | “Thời tiết Hà Nội thế nào?” → trả văn bản mô tả | “Đặt vé rẻ nhất Hà Nội - TP.HCM ngày mai” → tự tìm vé, so giá, đặt, xác nhận |
Nói cách khác, LLM chỉ là “bộ não ngôn ngữ” biết sinh văn bản. Agent biến bộ não đó thành một thực thể có thể hành động trong thế giới thật (gọi API, đọc file, truy vấn database) và tự lặp lại quá trình suy luận cho tới khi xong việc.
3. Thành phần cốt lõi của một AI Agent
Một agent tối thiểu cần 4 thành phần. Thiếu một trong số này, hệ thống chỉ là chatbot “mặc áo” agent.
3.1. LLM – bộ não suy luận
LLM nhận prompt (gồm mục tiêu, lịch sử, danh sách tool khả dụng) và sinh ra quyết định tiếp theo: trả lời trực tiếp hay gọi tool nào, với tham số gì.
3.2. Tool (function calling) – tay chân của agent
Tool là một hàm cụ thể mà agent có thể gọi: tra cứu đơn hàng, gọi API thời tiết, truy vấn database. Đây là phần biến agent từ “biết nói” thành “biết làm”.
public interface Tool {
String name();
boolean canHandle(String input);
String execute(String input);
}
canHandle kiểm tra xem tool này có xử lý được input hiện tại không; execute thực hiện hành động và trả kết quả (observation).
3.3. Memory – bộ nhớ
Agent cần nhớ lại những gì đã làm ở bước trước (lịch sử hội thoại, kết quả tool đã gọi) để tránh lặp lại hành động vô ích. Memory có thể đơn giản là một List<String> lưu log các bước, hoặc phức tạp hơn là vector store để tìm lại thông tin liên quan.
3.4. Control loop – vòng lặp điều khiển
Đây là phần “mô-tơ” chạy toàn bộ quá trình: lặp qua các bước Thought → Action → Observation cho tới khi đạt mục tiêu hoặc hết số bước cho phép. Phần tiếp theo sẽ đi sâu vào cơ chế này.
4. Vòng lặp ReAct: cách agent “suy nghĩ rồi hành động”
ReAct (Reasoning + Acting) là mô hình vòng lặp phổ biến nhất cho agent:
- Thought: LLM suy luận “mình cần làm gì tiếp theo?”
- Action: chọn một tool và gọi nó với tham số phù hợp.
- Observation: nhận kết quả từ tool, đưa lại vào context.
- Lặp lại từ bước 1 cho tới khi LLM quyết định đã đủ thông tin để trả lời cuối cùng, hoặc hết
maxSteps.
Để hiểu rõ cơ chế này mà không cần gọi LLM thật (tốn API key), ta tự dựng một agent mini bằng Java thuần, dùng if-else thay cho LLM thật.
public class SimpleAgent {
private final List<Tool> tools;
private final int maxSteps;
public SimpleAgent(List<Tool> tools, int maxSteps) {
this.tools = tools;
this.maxSteps = maxSteps;
}
public String run(String goal) {
String observation = goal;
for (int step = 1; step <= maxSteps; step++) {
Tool chosen = tools.stream()
.filter(t -> t.canHandle(observation))
.findFirst()
.orElse(null);
if (chosen == null) {
return "Không có tool nào xử lý được: " + observation;
}
System.out.printf("Bước %d - Thought: cần dùng tool '%s'%n", step, chosen.name());
String result = chosen.execute(observation);
System.out.printf("Bước %d - Observation: %s%n", step, result);
return result; // ví dụ đơn giản: xong sau 1 bước
}
return "Hết số bước cho phép (" + maxSteps + ") mà chưa xong việc.";
}
}
maxSteps chính là “ngân sách” bước lặp — bắt buộc phải có để agent không chạy vô tận nếu không bao giờ đạt mục tiêu. Vòng for mô phỏng Thought (chọn tool), Action (execute), Observation (kết quả in ra console).
Ba tool minh họa:
public class WeatherTool implements Tool {
@Override
public String name() {
return "WeatherTool";
}
@Override
public boolean canHandle(String input) {
return input.toLowerCase().contains("thời tiết");
}
@Override
public String execute(String input) {
return "Hà Nội hôm nay 28°C, trời nhiều mây.";
}
}
public class OrderStatusTool implements Tool {
@Override
public String name() {
return "OrderStatusTool";
}
@Override
public boolean canHandle(String input) {
return input.toLowerCase().contains("đơn hàng");
}
@Override
public String execute(String input) {
return "Đơn hàng #1023 đang được vận chuyển, dự kiến giao trong 2 ngày.";
}
}
public class CalculatorTool implements Tool {
@Override
public String name() {
return "CalculatorTool";
}
@Override
public boolean canHandle(String input) {
return input.matches(".*\\d+\\s*\\+\\s*\\d+.*");
}
@Override
public String execute(String input) {
String digits = input.replaceAll("[^0-9+]", "");
String[] parts = digits.split("\\+");
int sum = Integer.parseInt(parts[0]) + Integer.parseInt(parts[1]);
return "Kết quả: " + sum;
}
}
Gọi thử:
SimpleAgent agent = new SimpleAgent(
List.of(new CalculatorTool(), new WeatherTool(), new OrderStatusTool()),
3
);
String result = agent.run("Cho tôi biết thời tiết Hà Nội hôm nay");
System.out.println(result);
Kết quả:
Bước 1 - Thought: cần dùng tool 'WeatherTool'
Bước 1 - Observation: Hà Nội hôm nay 28°C, trời nhiều mây.
Hà Nội hôm nay 28°C, trời nhiều mây.
Viết test để chốt hành vi chọn tool đúng và xử lý trường hợp không tool nào phù hợp:
import org.junit.jupiter.api.Test;
import java.util.List;
import static org.assertj.core.api.Assertions.assertThat;
class SimpleAgentTest {
@Test
void shouldPickWeatherToolWhenGoalMentionsWeather() {
SimpleAgent agent = new SimpleAgent(
List.of(new CalculatorTool(), new WeatherTool(), new OrderStatusTool()),
3
);
String result = agent.run("Cho tôi biết thời tiết Hà Nội hôm nay");
assertThat(result).contains("Hà Nội");
}
@Test
void shouldReturnErrorWhenNoToolMatches() {
SimpleAgent agent = new SimpleAgent(List.of(new CalculatorTool()), 3);
String result = agent.run("Hát cho tôi một bài");
assertThat(result).startsWith("Không có tool nào xử lý được");
}
}
Ví dụ này dùng if-else thay cho LLM, nên “suy luận” rất cứng nhắc. Agent thật khác ở điểm: thay canHandle cứng nhắc bằng việc LLM tự đọc mô tả tool rồi quyết định gọi tool nào, với tham số được LLM tự trích xuất từ câu hỏi tự nhiên.
5. Dựng agent thật với Spring AI và tool calling
Để thấy LLM thật ra quyết định, ta dùng Spring AI — framework tích hợp model AI vào Spring Boot, hỗ trợ sẵn tool calling.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
<version>1.0.0</version>
</dependency>
Cấu hình API key và model:
spring:
ai:
openai:
api-key: ${OPENAI_API_KEY}
chat:
options:
model: gpt-4o-mini
Khai báo tool bằng annotation @Tool, đúng với vai trò của OrderStatusTool ở ví dụ trước nhưng lần này LLM thật sẽ gọi nó:
import org.springframework.ai.tool.annotation.Tool;
import org.springframework.stereotype.Component;
@Component
public class OrderTools {
@Tool(description = "Tra cứu trạng thái đơn hàng theo mã đơn hàng")
public String getOrderStatus(String orderId) {
// thực tế sẽ gọi OrderService / database ở đây
return "Đơn hàng " + orderId + " đang được vận chuyển, dự kiến giao trong 2 ngày.";
}
}
description cực kỳ quan trọng: LLM dựa vào mô tả này để quyết định có nên gọi tool này không và truyền tham số gì.
Service dùng ChatClient để gắn tool vào agent:
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;
@Service
public class OrderAssistantService {
private final ChatClient chatClient;
public OrderAssistantService(ChatClient.Builder builder, OrderTools orderTools) {
this.chatClient = builder
.defaultTools(orderTools)
.build();
}
public String ask(String question) {
return chatClient.prompt(question).call().content();
}
}
Gọi ask("Đơn hàng ORD-1023 của tôi đang ở đâu?"), bên dưới Spring AI sẽ:
- Gửi câu hỏi kèm mô tả tool
getOrderStatuscho model. - Model trả về quyết định “gọi
getOrderStatusvớiorderId="ORD-1023"” thay vì trả lời ngay. - Spring AI tự động invoke method Java tương ứng, lấy kết quả.
- Gửi kết quả đó lại cho model để model viết câu trả lời tự nhiên cuối cùng.
Đơn hàng ORD-1023 của bạn hiện đang được vận chuyển và dự kiến giao trong 2 ngày nữa.
Toàn bộ 4 bước trên chính là một vòng ReAct hoàn chỉnh, chỉ khác là Spring AI đã ẩn vòng for đi, bạn không cần tự viết control loop như ví dụ Java thuần ở mục 4.
Lưu ý: version
spring-ai-starter-model-openaivà tên artifact có thể thay đổi theo thời gian; luôn kiểm tra lại BOM tương ứng với version Spring Boot bạn dùng trước khi thêm dependency.
6. Các kiểu Agent phổ biến
- Single-agent ReAct: một agent duy nhất, lặp Thought-Action-Observation. Phù hợp cho task vừa phải, như hai ví dụ trên.
- Plan-and-Execute: agent lập kế hoạch chi tiết (danh sách bước) trước, rồi thực thi từng bước, không suy luận lại liên tục như ReAct. Phù hợp task nhiều bước có cấu trúc rõ (ví dụ: “tạo báo cáo gồm 5 phần”).
- Multi-agent: nhiều agent chuyên biệt hợp tác, thường có một agent “Supervisor” điều phối các agent “Worker” (ví dụ: agent tìm kiếm, agent viết văn bản, agent kiểm tra số liệu), kết quả được tổng hợp lại.
Chọn kiểu nào phụ thuộc độ phức tạp của task: task đơn giản dùng single-agent, task có nhiều domain khác nhau (tìm kiếm + viết + kiểm tra) nên tách thành multi-agent để dễ kiểm soát và debug từng phần.
7. Lỗi hay gặp & khi nào KHÔNG nên dùng Agent
- Vòng lặp vô hạn, đốt token: nếu không đặt
maxStepshoặc budget token, agent có thể lặp mãi vì LLM “tưởng” chưa xong việc. Luôn đặt giới hạn số bước rõ ràng nhưSimpleAgentở mục 4. - Mô tả tool mơ hồ: nếu
descriptioncủa tool không rõ ràng, LLM dễ gọi sai tool hoặc truyền tham số sai kiểu. Viết description cụ thể, nêu rõ định dạng tham số mong đợi. - Thiếu guardrail cho hành động nguy hiểm: agent có quyền gọi tool xóa dữ liệu, chuyển tiền… mà không có bước xác nhận là rủi ro lớn. Luôn thêm lớp kiểm duyệt (human-in-the-loop hoặc rule-based check) trước khi thực thi hành động không thể hoàn tác.
- Overkill cho task đơn giản: nếu câu hỏi chỉ cần 1 lần gọi LLM để lấy câu trả lời (ví dụ dịch một câu), đừng dựng cả agent loop với tool calling. Vừa tốn thêm latency, vừa tốn chi phí gọi model nhiều lần không cần thiết.
Lưu ý: nếu hệ thống của bạn không cần gọi hành động bên ngoài (API, database) và chỉ cần sinh văn bản một lần, đó là bài toán cho LLM thường — không phải agent. Đừng thêm phức tạp không cần thiết.
8. Kết luận
AI Agent khác chatbot thường ở khả năng tự quyết định hành động và lặp lại quá trình suy luận cho tới khi đạt mục tiêu, dựa trên bốn thành phần: LLM, tool, memory và control loop. Vòng lặp ReAct (Thought-Action-Observation) là cơ chế phổ biến đứng sau phần lớn agent hiện nay, và bạn có thể tự mô phỏng nó bằng Java thuần để hiểu bản chất trước khi chuyển sang dùng framework như Spring AI cho production. Quan trọng nhất: luôn đặt giới hạn số bước, viết mô tả tool rõ ràng, và thêm guardrail cho các hành động không thể hoàn tác — agent mạnh nhưng cũng dễ “làm quá” nếu thiếu kiểm soát.