AI Engineer Master Course
Trang chủ / Module 8
🤖 Module 8 / 17 · 4-5 tuần

AI Agents

Agent Design Patterns, LangGraph, Workflow Orchestration, Multi-agent Systems, Tool Ecosystems.

AgentsLangGraphOrchestration
📌 Vì sao module này quan trọng

"Agent" là từ khoá tuyển dụng nóng nhất 2025-2027: hệ thống AI không chỉ trả lời một câu hỏi mà tự lập kế hoạch, gọi công cụ, kiểm tra kết quả, và lặp lại cho đến khi hoàn thành một nhiệm vụ nhiều bước. Đây là nơi giá trị kinh doanh lớn nhất của AI ứng dụng hiện nay, và cũng là nơi khó làm đúng nhất.

🎯 Mục tiêu học tập

  • Phân biệt được các agent design pattern: ReAct, Plan-and-Execute, Reflection, Orchestrator-Worker
  • Xây dựng agent workflow bằng LangGraph (graph-based state machine)
  • Thiết kế multi-agent system với phân chia trách nhiệm rõ ràng giữa các agent
  • Hiểu rủi ro và giới hạn thực tế của agent tự động (vòng lặp vô hạn, chi phí bùng nổ, quyết định sai)

Agent Design Patterns

  • ReAct (Reason + Act): vòng lặp suy nghĩ → hành động (gọi tool) → quan sát kết quả → suy nghĩ tiếp, lặp đến khi xong. Pattern nền tảng, đơn giản, dễ debug.
  • Plan-and-Execute: agent lập kế hoạch nhiều bước trước, rồi thực thi tuần tự — tiết kiệm chi phí hơn ReAct thuần cho nhiệm vụ có cấu trúc rõ ràng vì không phải suy nghĩ lại sau mỗi bước.
  • Reflection: agent tự đánh giá/phê bình kết quả của chính mình trước khi trả về, cải thiện chất lượng đáng kể cho tác vụ sáng tạo/code, đánh đổi bằng chi phí và độ trễ gấp đôi.
  • Orchestrator-Worker: một agent điều phối chia nhỏ nhiệm vụ, giao cho các agent con chuyên biệt xử lý song song, rồi tổng hợp — mô hình phổ biến nhất cho hệ thống multi-agent production.
💡 Nguyên tắc vàng

Luôn bắt đầu từ workflow xác định (deterministic pipeline) — chỉ chuyển sang agent tự chủ hoàn toàn khi thực sự cần xử lý các trường hợp không lường trước được. Agent càng "tự do" càng khó kiểm soát chi phí và độ tin cậy.

LangGraph — xây agent như một state machine

LangGraph mô hình hoá agent workflow thành một đồ thị có trạng thái (graph of nodes), mỗi node là một bước xử lý (gọi LLM, gọi tool, rẽ nhánh điều kiện), các cạnh (edge) định nghĩa luồng đi tiếp theo — kể cả vòng lặp có kiểm soát. Ưu điểm so với "vòng lặp while tự viết": có sẵn cơ chế checkpointing (lưu trạng thái giữa các bước, phục hồi khi lỗi), human-in-the-loop (tạm dừng chờ người duyệt trước bước nhạy cảm), và visualize được toàn bộ luồng agent.

from langgraph.graph import StateGraph, END

def plan(state): ...
def execute_tool(state): ...
def should_continue(state) -> str:
    return "execute_tool" if state["needs_tool"] else END

graph = StateGraph(AgentState)
graph.add_node("plan", plan)
graph.add_node("execute_tool", execute_tool)
graph.add_conditional_edges("plan", should_continue)
graph.add_edge("execute_tool", "plan")
graph.set_entry_point("plan")
app = graph.compile()

Multi-agent Systems

Khi một nhiệm vụ cần nhiều "vai trò" khác nhau (ví dụ: agent nghiên cứu + agent viết + agent kiểm tra chất lượng), chia thành nhiều agent chuyên biệt thường tốt hơn một agent "biết tuốt": mỗi agent có system prompt, tool, và context nhỏ gọn hơn nên ít bị nhiễu (context pollution), dễ test độc lập, và có thể dùng model khác nhau cho từng vai trò (agent điều phối dùng model mạnh, agent thực thi đơn giản dùng model rẻ).

Thách thức chính: giao tiếp giữa các agent (qua state chung, message passing, hay blackboard pattern), và tránh vòng lặp vô hạn khi hai agent liên tục "đẩy việc" qua lại nhau — luôn đặt giới hạn số bước tối đa cứng (hard max iterations).

Tool Ecosystems

Một agent hữu ích cần bộ công cụ (tools) được thiết kế tốt: mỗi tool nên có một trách nhiệm rõ ràng, tên và mô tả tham số phải đủ rõ để model tự chọn đúng công cụ mà không cần đoán, và nên trả về lỗi có cấu trúc (không phải raw exception) để agent có thể tự sửa và thử lại. Xem Module 9 (MCP) để biết cách chuẩn hoá tool ecosystem dùng chung giữa nhiều agent/ứng dụng.

🔬 Đào sâu — Viết vòng lặp ReAct từ đầu (không dùng framework)

Trước khi dùng LangGraph/CrewAI, nên tự viết một vòng lặp ReAct thô để hiểu rõ "bên dưới framework đang làm gì" — điều này giúp debug framework dễ hơn rất nhiều về sau:

def run_agent(user_msg: str, tools: dict, max_steps: int = 8) -> str:
    messages = [{"role": "user", "content": user_msg}]
    for step in range(max_steps):
        resp = client.messages.create(
            model="claude-sonnet-5", max_tokens=1024,
            tools=[t["schema"] for t in tools.values()],
            messages=messages,
        )
        messages.append({"role": "assistant", "content": resp.content})

        tool_calls = [b for b in resp.content if b.type == "tool_use"]
        if not tool_calls:
            return "".join(b.text for b in resp.content if b.type == "text")

        tool_results = []
        for call in tool_calls:
            try:
                result = tools[call.name]["fn"](**call.input)
            except Exception as e:
                result = {"error": str(e)}  # trả lỗi có cấu trúc để model tự sửa
            tool_results.append({
                "type": "tool_result", "tool_use_id": call.id, "content": str(result),
            })
        messages.append({"role": "user", "content": tool_results})

    return "Đã vượt quá số bước tối đa — dừng agent để tránh chi phí bùng nổ."

Ba điều quan trọng thể hiện rõ trong đoạn code trên mà framework thường "giấu đi": (1) giới hạn max_steps cứng, (2) lỗi tool được bắt và trả về dưới dạng nội dung cho model đọc thay vì làm sập chương trình, (3) toàn bộ lịch sử hội thoại + tool call/result được tích luỹ trong messages — đây chính là "state" mà LangGraph quản lý hộ bạn ở quy mô lớn hơn.

🔬 Đào sâu — LangGraph: Checkpointing & Human-in-the-loop

Hai tính năng khiến LangGraph vượt trội so với vòng lặp tự viết khi lên production: checkpointing (lưu state sau mỗi bước, phục hồi được khi service restart giữa chừng) và interrupt (tạm dừng chờ con người duyệt trước bước nhạy cảm).

from langgraph.graph import StateGraph, END
from langgraph.checkpoint.postgres import PostgresSaver

checkpointer = PostgresSaver.from_conn_string(DATABASE_URL)

graph = StateGraph(AgentState)
graph.add_node("plan", plan_node)
graph.add_node("execute_tool", execute_tool_node)
graph.add_node("send_payment", send_payment_node)  # hành động có tác dụng phụ, cần duyệt
graph.add_conditional_edges("plan", route_next)
graph.set_entry_point("plan")

app = graph.compile(
    checkpointer=checkpointer,
    interrupt_before=["send_payment"],  # tạm dừng, chờ con người duyệt trước khi thực thi
)

# Chạy đến điểm interrupt
config = {"configurable": {"thread_id": "order-8842"}}
app.invoke({"messages": [...]}, config=config)

# ... sau khi người duyệt xác nhận trên UI riêng ...
app.invoke(None, config=config)  # tiếp tục từ đúng checkpoint đã lưu

Mẫu thiết kế này (checkpoint + interrupt) là cách chuẩn để đưa agent tự động vào các quy trình có rủi ro tài chính/pháp lý mà vẫn giữ được tốc độ tự động hoá cho phần còn lại của luồng xử lý.

🔬 Đào sâu — So sánh framework Agent 2026

FrameworkĐiểm mạnhKhi nào dùng
LangGraphKiểm soát luồng chi tiết (graph), checkpointing mạnh, hệ sinh thái LangChain rộngWorkflow phức tạp cần rẽ nhánh/vòng lặp tường minh, cần human-in-the-loop
OpenAI Agents SDKĐơn giản, tích hợp chặt với model OpenAI, có sẵn tracingTeam đã gắn với hệ sinh thái OpenAI, muốn triển khai nhanh
Claude Agent SDKTối ưu cho coding agent & tác vụ dài hơi, quản lý context tự động tốtAgent cần chạy tác vụ dài, nhiều bước, liên quan đến code/file system
CrewAITrừu tượng hoá cao ở mức "vai trò" (role-based), dễ tiếp cận Prototype nhanh multi-agent theo mô hình "đội nhóm" (researcher, writer, reviewer...)
Microsoft Agent Framework / Semantic KernelTích hợp sâu hệ sinh thái Azure/.NET, hỗ trợ đa ngôn ngữ lập trìnhDoanh nghiệp đã dùng hệ sinh thái Microsoft/Azure

Lời khuyên: học kỹ một framework có kiểm soát luồng tường minh (LangGraph là lựa chọn phổ biến nhất để học vì tư duy graph áp dụng được sang framework khác) — đừng cố học hết 5 framework, khái niệm nền tảng (state, node, edge, checkpoint) giống nhau ở mọi nơi.

🔬 Đào sâu — Lỗi thường gặp & cách xử lý

Triệu chứngNguyên nhân thường gặpCách xử lý
Agent lặp vô hạn giữa 2 bướcĐiều kiện dừng (routing logic) sai, hoặc tool trả kết quả khiến model luôn nghĩ "chưa xong"Giới hạn max_steps cứng + log lại lý do dừng để phát hiện pattern lặp
Chi phí bùng nổ bất thườngAgent gọi lại tool tốn kém (ví dụ retrieval) nhiều lần không cần thiết, hoặc context tích luỹ quá dài qua nhiều bướcCache kết quả tool trong 1 phiên, tóm tắt/cắt bớt lịch sử hội thoại cũ khi context vượt ngưỡng
Model "bịa" tên tool không tồn tạiMô tả tool không đủ rõ, hoặc có quá nhiều tool (>20) khiến model nhầm lẫnViết lại mô tả tool cụ thể hơn; nhóm tool theo domain, chỉ expose tool liên quan đến bước hiện tại thay vì toàn bộ cùng lúc
Agent "quên" chỉ thị ban đầu sau nhiều bướcContext pollution — lịch sử tool call/result quá dài làm loãng system promptTóm tắt định kỳ, hoặc dùng multi-agent để mỗi agent con có context ngắn gọn hơn thay vì 1 agent ôm hết

🏋️ Bài tập thực hành

Agent nghiên cứu & tổng hợp báo cáo

Xây một multi-agent system với LangGraph: Agent điều phối nhận yêu cầu nghiên cứu một chủ đề → giao cho Agent tìm kiếm (dùng tool search có sẵn hoặc RAG từ Module 6) thu thập thông tin → Agent viết tổng hợp thành báo cáo → Agent kiểm tra chất lượng/tính nhất quán trước khi trả kết quả cuối. Thêm giới hạn cứng tối đa 10 bước lặp và log lại toàn bộ quyết định của agent để debug.

📚 Tài nguyên học tập

✅ Tự đánh giá hoàn thành

  • Giải thích được sự khác nhau giữa ReAct, Plan-and-Execute, và Orchestrator-Worker
  • Xây được ít nhất 1 agent workflow bằng LangGraph có rẽ nhánh điều kiện
  • Triển khai multi-agent system với 2+ agent chuyên biệt phối hợp nhau
  • Có cơ chế giới hạn số bước lặp cứng để tránh chi phí bùng nổ