Microsoft Ship AI Agent Framework: Giải Thích Chi Tiết Kèm Ví Dụ
1. Tổng quan
Microsoft vừa chính thức ship (GA – General Availability) một framework thống nhất để xây dựng, điều phối và vận hành AI Agent, bằng cách hợp nhất hai sản phẩm trước đó là Semantic Kernel và AutoGen. Đây không chỉ là tin tức sản phẩm — nó định hình lại cách bạn nên thiết kế một hệ thống có LLM “tự quyết định hành động” thay vì chỉ trả lời một câu hỏi.
Bài này giải thích AI Agent khác chatbot thông thường ở điểm nào, Microsoft đã ship cụ thể cái gì, rồi bạn sẽ tự tay dựng một agent tối giản bằng Java 21 + Spring Boot 3 + Spring AI (tích hợp Azure OpenAI) để hiểu rõ cơ chế bên dưới, dù framework gốc của Microsoft chạy trên .NET và Python.
2. AI Agent là gì?
Một chatbot thông thường nhận câu hỏi, gọi LLM một lần, trả về câu trả lời. Agent khác ở chỗ nó lặp lại vòng suy nghĩ – hành động nhiều lần, tự quyết định có cần gọi tool (API, database, file…) hay không, trước khi đưa ra câu trả lời cuối cùng.
| Đặc điểm | Chatbot | AI Agent |
|---|---|---|
| Số lần gọi LLM | 1 lần/câu hỏi | Nhiều lần, tự lặp |
| Dùng tool ngoài | Thường không | Có, tool do model tự chọn |
| Trạng thái | Stateless hoặc lưu lịch sử chat | Có memory, có thể checkpoint |
| Độ trễ | Thấp | Cao hơn (nhiều round-trip) |
| Độ tin cậy | Dễ kiểm soát | Cần guardrail, human-in-the-loop |
2.1. Vòng lặp Reason–Act (ReAct)
Cơ chế lõi mà hầu hết agent framework hiện nay dùng là ReAct: model “nghĩ” (Thought), chọn hành động (Action) là gọi một tool, nhận kết quả (Observation), rồi lặp lại cho đến khi đủ thông tin trả lời (Final Answer).
Thought: Người dùng hỏi trạng thái đơn ORD-001, tôi cần tra cứu.
Action: lookupOrder("ORD-001")
Observation: Đơn ORD-001: trạng thái SHIPPED, tổng tiền 450000 VND
Thought: Đã đủ thông tin.
Final Answer: Đơn ORD-001 của bạn đang được giao, tổng tiền 450.000đ.
Đây là phần mà Microsoft Agent Framework (và Spring AI mà bạn sẽ dùng bên dưới) tự động hóa — bạn không cần viết tay vòng lặp này, chỉ cần khai báo tool và system prompt.
3. Microsoft đã “ship” những gì cho AI Agent
Trước khi hợp nhất, Microsoft có hai hướng phát triển song song:
- Semantic Kernel: SDK hướng production, nhấn mạnh plugin type-safe, tích hợp enterprise (Azure, .NET), phù hợp triển khai ổn định.
- AutoGen: hướng nghiên cứu, mạnh về multi-agent conversation — nhiều agent “chat” với nhau để giải quyết task phức tạp.
Framework mới gộp cả hai điểm mạnh, gồm các năng lực chính:
- Orchestration pattern có sẵn: sequential (agent A xong rồi đến B), concurrent (nhiều agent chạy song song rồi tổng hợp), hand-off (agent chuyển task cho agent chuyên trách khác), group chat (nhiều agent thảo luận trước khi trả lời).
- Durable/stateful execution: agent có thể checkpoint giữa chừng, resume lại nếu process crash — quan trọng cho task dài (vài phút đến vài giờ).
- Observability built-in: trace theo chuẩn OpenTelemetry, bạn xem được từng bước Thought/Action/Observation trong production.
- Human-in-the-loop: tạm dừng agent để chờ người duyệt trước khi thực hiện hành động nhạy cảm (hoàn tiền, xoá dữ liệu…).
- Azure AI Foundry Agent Service: runtime hosted để deploy agent, có catalog tool sẵn (Bing search, code interpreter, file retrieval) và hỗ trợ Model Context Protocol (MCP) để kết nối tool bên ngoài theo chuẩn mở, không khoá vendor.
Framework gốc chạy trên .NET/Python, nhưng pattern thì phổ quát. Phần tiếp theo mình dựng lại đúng pattern đó trong Java để bạn thấy nó hoạt động thế nào ở tầng code.
4. Kiến trúc lõi của một AI Agent
Một agent tối giản cần 4 thành phần: Planner (chính là LLM), Tool (hàm agent có thể gọi), Memory (lịch sử hội thoại/kết quả tool), Executor (vòng lặp điều phối). Spring AI đóng gói sẵn Executor và Planner thông qua ChatClient, bạn chỉ cần khai báo Tool.
4.1. Dependency Maven
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-azure-openai-spring-boot-starter</artifactId>
<version>1.0.0</version>
</dependency>
Cấu hình kết nối Azure OpenAI (dịch vụ GPT của Microsoft, deploy qua Azure):
spring.ai.azure.openai.api-key=${AZURE_OPENAI_KEY}
spring.ai.azure.openai.endpoint=${AZURE_OPENAI_ENDPOINT}
spring.ai.azure.openai.chat.options.deployment-name=gpt-4o-mini
4.2. Định nghĩa Tool cho agent
Tool là một method Java bình thường, được đánh dấu @Tool để model biết nó có thể gọi và biết gọi với tham số gì.
public record Order(String id, String status, BigDecimal total) {}
public interface OrderService {
Order findById(String orderId);
}
@Service
public class OrderTools {
private final OrderService orderService;
public OrderTools(OrderService orderService) {
this.orderService = orderService;
}
@Tool(description = "Tra cứu trạng thái và tổng tiền của một đơn hàng theo mã đơn")
public String lookupOrder(String orderId) {
Order order = orderService.findById(orderId);
return "Đơn %s: trạng thái %s, tổng tiền %s VND"
.formatted(order.id(), order.status(), order.total());
}
}
description trong @Tool chính là thứ model đọc để quyết định có nên gọi lookupOrder hay không — viết mô tả rõ ràng, cụ thể, agent sẽ chọn tool chính xác hơn.
4.3. Agent gọi tool tự động qua ChatClient
@Service
public class SupportAgentService {
private final ChatClient chatClient;
public SupportAgentService(ChatClient.Builder builder, OrderTools orderTools) {
this.chatClient = builder
.defaultSystem("""
Bạn là trợ lý hỗ trợ khách hàng của một shop online.
Nếu câu hỏi liên quan đến đơn hàng, hãy dùng tool lookupOrder.
Trả lời ngắn gọn, thân thiện, bằng tiếng Việt.
""")
.defaultTools(orderTools)
.build();
}
public String handle(String userMessage) {
return chatClient.prompt()
.user(userMessage)
.call()
.content();
}
}
Dòng .defaultTools(orderTools) đăng ký toolset, ChatClient tự chạy vòng ReAct bên trong: gửi prompt kèm danh sách tool cho model, nếu model trả về yêu cầu gọi lookupOrder, Spring AI tự thực thi method Java tương ứng, đưa kết quả (Observation) trở lại model, rồi mới nhận câu trả lời cuối. Bạn không viết tay vòng lặp — đây chính là phần mà Microsoft Agent Framework và Spring AI làm giống nhau về bản chất.
> handle("Đơn ORD-001 của tôi đang ở đâu rồi?")
Đơn ORD-001 của bạn đang được giao (SHIPPED), tổng tiền 450.000đ nhé!
Lưu ý: Model chỉ gọi tool khi nó “quyết định” cần — không phải mọi câu hỏi đều kích hoạt tool. Nếu người dùng hỏi “shop có ship quốc tế không?”, model sẽ trả lời trực tiếp mà không gọi
lookupOrder.
5. Multi-agent: khi một agent không đủ
Một trong những năng lực nổi bật mà Microsoft ship là hand-off — chuyển cuộc hội thoại giữa các agent chuyên trách. Với bài toán nhỏ, bạn có thể mô phỏng bằng một router đơn giản, chưa cần framework multi-agent phức tạp:
@Service
public class AgentRouter {
private final SupportAgentService orderAgent;
private final RefundAgentService refundAgent;
public AgentRouter(SupportAgentService orderAgent, RefundAgentService refundAgent) {
this.orderAgent = orderAgent;
this.refundAgent = refundAgent;
}
public String route(String userMessage) {
String lower = userMessage.toLowerCase();
if (lower.contains("hoàn tiền") || lower.contains("refund")) {
return refundAgent.handle(userMessage);
}
return orderAgent.handle(userMessage);
}
}
Router này đóng vai trò “orchestrator” tối giản. Ở quy mô lớn hơn, bản thân việc chọn agent nào xử lý cũng nên để chính LLM quyết định (intent classification bằng model), thay vì hard-code contains() — cách viết tay chỉ phù hợp demo hoặc tập intent rất nhỏ và ổn định.
6. Viết test cho tool và agent
Phần dễ test nhất trong một hệ agent là tool — vì nó là method Java thuần, không phụ thuộc LLM. Bạn nên test kỹ phần này, vì agent chỉ “thông minh” bằng đúng chất lượng tool nó gọi.
class OrderToolsTest {
@Test
void shouldReturnOrderSummaryWithStatusAndTotal() {
OrderService fakeOrderService = orderId ->
new Order(orderId, "SHIPPED", new BigDecimal("450000"));
OrderTools tools = new OrderTools(fakeOrderService);
String result = tools.lookupOrder("ORD-001");
assertThat(result)
.contains("ORD-001")
.contains("SHIPPED")
.contains("450000");
}
}
Vì OrderService chỉ có một method findById, mình dùng lambda để làm fake implementation thay vì cần thêm dependency mocking framework — gọn và đủ cho test đơn vị này.
class AgentRouterTest {
@Test
void shouldRouteRefundKeywordToRefundAgent() {
SupportAgentService orderAgent = mock(SupportAgentService.class);
RefundAgentService refundAgent = mock(RefundAgentService.class);
when(refundAgent.handle(anyString())).thenReturn("Đã ghi nhận yêu cầu hoàn tiền");
AgentRouter router = new AgentRouter(orderAgent, refundAgent);
String result = router.route("Tôi muốn hoàn tiền đơn ORD-002");
assertThat(result).isEqualTo("Đã ghi nhận yêu cầu hoàn tiền");
verify(refundAgent).handle(anyString());
verify(orderAgent, never()).handle(anyString());
}
}
Lưu ý: Không nên viết test “end-to-end gọi thật LLM” trong unit test — kết quả không deterministic (model có thể trả lời khác nhau mỗi lần), tốn tiền gọi API, và làm CI chậm/flaky. Hãy mock
ChatClienthoặc test riêng phần tool/router như trên; để riêng một tập integration test (chạy tay hoặc nightly) cho việc kiểm tra agent có chọn đúng tool trong tình huống thật.
7. Lỗi hay gặp và khi nào không nên dùng agent
- Dùng agent cho việc có thể giải quyết bằng if-else: nếu logic chọn hành động đã biết trước và cố định (ví dụ: luôn tra đơn khi có mã đơn dạng
ORD-\d+), viết code thường rẻ hơn, nhanh hơn, dễ test hơn nhiều so với để LLM “suy nghĩ” mỗi lần. - Bỏ qua guardrail cho hành động nhạy cảm: agent có quyền gọi tool xoá dữ liệu, hoàn tiền, gửi email cho khách — nếu không có bước xác nhận (human-in-the-loop) hoặc giới hạn quyền tool, một prompt injection hoặc lỗi suy luận của model có thể gây hậu quả thật.
- Không giới hạn số vòng lặp: nếu model liên tục chọn sai tool hoặc không đủ dữ liệu để kết luận, vòng ReAct có thể lặp vô hạn, tốn token và tiền. Luôn đặt số bước tối đa và timeout.
- Thiếu observability: khi agent trả lời sai, bạn cần xem lại được toàn bộ chuỗi Thought/Action/Observation để debug — không có log/trace chi tiết thì gần như không thể tìm ra model đã “nghĩ” gì dẫn đến kết quả sai.
- Latency và chi phí: mỗi bước trong vòng lặp là một lần gọi LLM. Một câu hỏi đơn giản có thể tốn 2-3 lần gọi model (và từng lần đều mất vài trăm ms đến vài giây). Với API cần phản hồi tức thì (ví dụ dưới 200ms), agent kiểu này không phù hợp.
8. Kết luận
Việc Microsoft hợp nhất Semantic Kernel và AutoGen thành một framework duy nhất cho thấy xu hướng rõ ràng: AI Agent đang chuyển từ “demo thú vị” sang hạ tầng production cần orchestration, state, observability và kiểm soát quyền hạn nghiêm ngặt như mọi hệ thống enterprise khác. Dù bạn dùng .NET, Python hay Java/Spring AI như ví dụ trong bài, bản chất kiến trúc vẫn xoay quanh bốn khối: Planner, Tool, Memory, Executor — nắm vững bốn khối này, bạn có thể đọc hiểu và áp dụng bất kỳ agent framework nào xuất hiện sau này.