Bỏ qua

Bài 1: What Is an AI Agent?

Tổng quan

Bài này xây dựng nền tảng khái niệm cho toàn bộ Module II: agent là gì, khác gì với một lời gọi LLM đơn thuần hay một RAG pipeline cố định, các thành phần cấu thành nên một agent, cách cấu trúc system prompt cho agent phức tạp, và bức tranh landscape framework/protocol năm 2026.


1. Định nghĩa & Sự tiến hoá

Agent là gì?

Một AI agent là một hệ thống dùng LLM làm bộ não trung tâm để tự quyết định chuỗi hành động cần thực hiện nhằm đạt mục tiêu, thay vì đi theo một luồng xử lý cố định do lập trình viên viết sẵn.

Điểm khác biệt cốt lõi so với pipeline truyền thống: ai quyết định bước tiếp theo.

Pipeline cố định (vd: RAG ở Module I) Agent
Luồng xử lý Lập trình viên định nghĩa trước: retrieve → generate LLM tự quyết định: cần tool nào, gọi mấy lần, khi nào dừng
Số bước Cố định Động, phụ thuộc vào kết quả trung gian
Khả năng phục hồi lỗi Không - nếu retrieve rỗng, generate vẫn chạy Có thể quan sát lỗi và thử cách khác

RAG có phải là agent không?

RAG cơ bản (retrieve → generate) không phải agent - đó là pipeline cố định. Agentic RAG (Module I, Bài 6) đã bắt đầu mang tính agent vì model tự quyết định có cần retrieve lại hay tìm web không. Ranh giới nằm ở quyền tự quyết định hành động tiếp theo.

Sự tiến hoá

graph LR
    A[2020-2022<br/>Prompt engineering<br/>1 lời gọi, output cố định] --> B[2023<br/>ReAct, Chain-of-Thought<br/>Reasoning + Action]
    B --> C[2024<br/>Function calling chuẩn hoá<br/>LangChain, AutoGPT]
    C --> D[2025<br/>Graph-based orchestration<br/>LangGraph, CrewAI, OpenAI Agents SDK]
    D --> E[2026<br/>Protocol chuẩn hoá<br/>MCP, A2A, Multi-agent phổ biến]

A2A là gì?

Agent2Agent (A2A) là chuẩn giao tiếp giữa các agent với nhau (agent-to-agent), khác với MCP vốn chuẩn hoá giao tiếp giữa agent và tool/data source. A2A liên quan trực tiếp đến Multi-Agent Systems (Bài 6) nhưng nằm ngoài phạm vi module này - chỉ nhắc đến ở đây để định vị trong bức tranh landscape.


2. Core Components

Mọi agent, dù dùng framework nào, đều gồm 4 thành phần:

graph TD
    subgraph Agent
        BRAIN[LLM Brain<br/>Reasoning + Decision making]
        TOOLS[Tools<br/>Function calling, APIs, RAG]
        MEMORY[Memory<br/>Short-term + Long-term]
        PLAN[Planning Loop<br/>Observe → Think → Act]
    end
    BRAIN <--> TOOLS
    BRAIN <--> MEMORY
    BRAIN --> PLAN
    PLAN --> BRAIN
Thành phần Vai trò Ví dụ
LLM Brain Reasoning, ra quyết định, chọn hành động tiếp theo GPT-4o, Claude, Gemini
Tools Cầu nối với thế giới bên ngoài Web search, database query, RAG retrieval, code execution
Memory Giữ ngữ cảnh qua nhiều bước / nhiều lượt hội thoại Conversation history, vector store, scratchpad
Planning Loop Vòng lặp quan sát - suy nghĩ - hành động, quyết định khi nào dừng ReAct loop, task decomposition

Thiếu 1 thành phần vẫn có thể gọi là agent, nhưng giới hạn

Một chatbot chỉ có LLM Brain + Memory (không có Tools) chỉ có thể trò chuyện, không thể hành động. Một script gọi tool cố định (không có Planning Loop) là automation, không phải agent thực sự.


3. System Prompt: Cấu trúc & Cách lắp ráp

System prompt là nơi cấu hình "LLM Brain" - agent càng phức tạp, system prompt càng cần được lắp ráp có cấu trúc thay vì viết tay một đoạn văn dài.

6 tầng của một system prompt

Tầng Trả lời câu hỏi Ví dụ
Identity Agent là ai? "Bạn là trợ lý kỹ thuật cấp cao chuyên về..."
Constraints Luôn/không bao giờ làm gì? "Không bao giờ thực thi lệnh phá huỷ dữ liệu mà chưa xác nhận"
Capabilities Có tool gì? Mô tả + schema của các tool khả dụng
Context Môi trường hiện tại? Thư mục làm việc, trạng thái git, thời gian
Behavior Cư xử thế nào? Tone, độ dài phản hồi, phong cách ra quyết định
Knowledge Kiến thức chuyên biệt? Skill instructions, memory liên quan (Bài 3)

Lắp ráp theo từng phần, không viết 1 khối văn bản

def assemble_system_prompt(agent_config: dict, task: str, environment: dict) -> str:
    sections = []
    sections.append(agent_config["identity"])       # Luôn có
    sections.append(agent_config["constraints"])     # Luôn có
    sections.append(format_tools(select_tools(task, agent_config["tools"])))  # Lọc theo task
    sections.append(format_environment(environment)) # Động, theo runtime
    if agent_config.get("soul"):
        sections.append(agent_config["soul"])         # Behavior, xem SOUL.md bên dưới
    return "\n\n".join(sections)

Anti-pattern: nhồi tất cả vào 1 chuỗi

Viết system prompt như 1 đoạn văn dài chứa mọi thứ (identity + toàn bộ 50 tool + toàn bộ lịch sử user + 200 skill) không maintain được, không customize được theo task, và lãng phí token nghiêm trọng. Luôn lắp ráp từ các phần nhỏ, lọc theo nhu cầu hiện tại - giống cách JIT tool loading lọc tool theo task (Bài 4).

AGENTS.md vs SOUL.md: tách "làm gì" khỏi "là ai"

Với agent cá nhân hoá (vd: trợ lý dùng lâu dài, nhớ user qua nhiều session - Bài 3), tách system prompt thành 2 file riêng biệt giúp thay đổi tính cách mà không đụng vào logic vận hành, và ngược lại:

File Trả lời Ví dụ nội dung
AGENTS.md Agent làm gì, quy tắc vận hành "Dùng web_search cho câu hỏi thực tế. Luôn xác nhận trước khi xoá dữ liệu."
SOUL.md Agent cư xử ra sao, tính cách "Trả lời trực tiếp rồi mới giải thích. Thừa nhận khi không chắc thay vì bịa."
# AGENTS.md (vận hành - developer sở hữu)
## Quy tắc công cụ
- Dùng `search_vietnamese_news` cho câu hỏi thời sự
- Luôn xác nhận trước khi gọi tool có side effect

# SOUL.md (tính cách - user tuỳ chỉnh)
## Phong cách giao tiếp
- Trả lời ngắn gọn, đi thẳng vào trọng tâm
- Dùng ví dụ cụ thể thay vì giải thích trừu tượng

Lợi ích: User đổi tông giọng agent (SOUL.md) mà không sợ phá vỡ logic vận hành (AGENTS.md); developer thêm tool/quy tắc mới mà không ảnh hưởng tính cách đã được user tuỳ chỉnh.

Chỉ cần tách khi agent thực sự cá nhân hoá lâu dài

Với agent dùng 1 lần hoặc task-specific (đa số ví dụ trong module này), 1 system prompt đơn giản là đủ. Tách AGENTS.md/SOUL.md đáng giá khi agent phục vụ nhiều user với gu cá nhân khác nhau, hoặc khi đội ngũ vận hành và đội ngũ thiết kế trải nghiệm là 2 nhóm khác nhau.


4. Agent Paradigms

Reflex Agent

Phản ứng trực tiếp với input hiện tại, không có bộ nhớ về quá khứ, không lập kế hoạch nhiều bước.

def reflex_agent(user_input: str) -> str:
    # Map input → action, không suy luận nhiều bước
    if "thời tiết" in user_input:
        return get_weather()
    if "giá vàng" in user_input:
        return get_gold_price()
    return llm_respond(user_input)

Phù hợp khi: Task đơn giản, 1 bước, không cần ngữ cảnh trước đó.


Planning Agent

Trước khi hành động, agent lập kế hoạch toàn bộ các bước cần làm, rồi thực thi theo kế hoạch (có thể điều chỉnh khi gặp lỗi).

PLAN_PROMPT = """Nhiệm vụ: {task}

Hãy lập kế hoạch các bước cần thực hiện để hoàn thành nhiệm vụ.
Trả về danh sách bước theo thứ tự, mỗi bước là 1 hành động cụ thể.
"""

# LLM trả về:
# 1. Tìm kiếm thông tin về công ty X
# 2. Tổng hợp báo cáo tài chính quý gần nhất
# 3. So sánh với đối thủ cạnh tranh
# 4. Viết báo cáo tổng hợp

Phù hợp khi: Task phức tạp, nhiều bước phụ thuộc lẫn nhau, cần nhìn toàn cảnh trước khi hành động (vd: research agent trong capstone).


ReAct (Reasoning + Acting)

Xen kẽ giữa suy nghĩ (Thought), hành động (Action), và quan sát (Observation) - mỗi bước phụ thuộc vào kết quả của bước trước, thay vì lập kế hoạch toàn bộ ngay từ đầu.

Thought: Cần biết giá cổ phiếu VNM hôm nay để trả lời câu hỏi.
Action: get_stock_price("VNM")
Observation: VNM: 68,500 VNĐ (+1.2%)
Thought: Đã có giá. Giờ cần biết vốn hoá thị trường để so sánh.
Action: get_market_cap("VNM")
Observation: Vốn hoá: 142,000 tỷ VNĐ
Thought: Đã đủ thông tin để trả lời.
Final Answer: Cổ phiếu VNM hôm nay giao dịch ở mức 68,500 VNĐ (+1.2%)...
from openai import OpenAI

client = OpenAI()

REACT_SYSTEM_PROMPT = """Bạn giải quyết task bằng vòng lặp Thought/Action/Observation.
Sau mỗi Observation, quyết định: cần Action tiếp theo, hay đã đủ để đưa Final Answer.
Không lập kế hoạch trước - suy nghĩ từng bước dựa trên thông tin quan sát được."""

def react_loop(task: str, tools: dict, max_steps: int = 6):
    messages = [
        {"role": "system", "content": REACT_SYSTEM_PROMPT},
        {"role": "user", "content": task},
    ]
    for step in range(max_steps):
        response = client.chat.completions.create(
            model="gpt-4o-mini", messages=messages, tools=tools["schema"]
        )
        msg = response.choices[0].message
        if msg.tool_calls:
            messages.append(msg)
            for call in msg.tool_calls:
                result = tools["execute"](call)
                messages.append({
                    "role": "tool", "tool_call_id": call.id, "content": str(result)
                })
        else:
            return msg.content  # Final Answer
    return "Vượt quá số bước cho phép."

Phù hợp khi: Không biết trước cần bao nhiêu bước hoặc tool nào; mỗi bước phụ thuộc kết quả quan sát trước đó (vd: debug lỗi, multi-hop question answering).

So sánh 3 paradigms

Paradigm Có bộ nhớ nhiều bước? Lập kế hoạch trước? Độ phức tạp task phù hợp
Reflex Không Không Thấp - 1 bước
Planning Có, toàn bộ trước khi chạy Cao - nhiều bước độc lập, biết trước cấu trúc
ReAct Không, từng bước một Cao - nhiều bước phụ thuộc kết quả trung gian

LangGraph hỗ trợ cả 3 paradigm

Bài 2 sẽ dùng LangGraph để implement ReAct loop bằng state graph - đây là paradigm phổ biến nhất cho agent thực tế vì cân bằng giữa tính linh hoạt và khả năng kiểm soát.


5. Landscape 2026

Framework so sánh

Framework Điểm mạnh Điểm yếu Dùng khi
LangGraph Kiểm soát chi tiết state/flow, debug tốt, tích hợp LangSmith Đường cong học tập cao hơn Cần custom logic phức tạp, production-grade
CrewAI API cấp cao, dễ setup multi-agent theo "role" Ít linh hoạt khi cần custom control flow Prototype nhanh, team-based agents
AutoGen Mạnh về multi-agent conversation, research-oriented Ít structured hơn cho production Nghiên cứu, agent hội thoại phức tạp
OpenAI Agents SDK Tích hợp chặt với OpenAI models, đơn giản Gắn với hệ sinh thái OpenAI Dự án dùng OpenAI làm nhà cung cấp chính

Vì sao Module này chọn LangGraph làm mặc định

LangGraph biểu diễn agent như một state graph tường minh - mỗi node, edge, điều kiện rẽ nhánh đều là code bạn kiểm soát hoàn toàn. Điều này giúp debug, test, và mở rộng sang multi-agent dễ dàng hơn so với các framework "hộp đen" cấp cao. Các framework khác sẽ được nhắc đến trong bảng so sánh khi liên quan (Bài 6).

MCP (Model Context Protocol)

MCP là chuẩn mở (do Anthropic khởi xướng, nay được nhiều provider hỗ trợ) để kết nối agent với tools/data sources một cách thống nhất - thay vì mỗi tool cần một tích hợp riêng.

graph LR
    subgraph "Trước MCP"
        A1[Agent A] --> T1[Tool 1 - custom integration]
        A1 --> T2[Tool 2 - custom integration]
        A2[Agent B] --> T1
        A2 --> T2
    end
graph LR
    subgraph "Với MCP"
        AG1[Agent A] --> MCP((MCP Protocol))
        AG2[Agent B] --> MCP
        MCP --> S1[MCP Server: Filesystem]
        MCP --> S2[MCP Server: Database]
        MCP --> S3[MCP Server: Vietnamese News]
    end

MCP sẽ được đào sâu ở Bài 4 (chuẩn giao tiếp, cách viết Server/Client) - phần này chỉ giới thiệu vị trí của nó trong landscape: MCP giải quyết bài toán N agent × M tool = N×M integration bằng cách chuẩn hoá thành N + M.


Tóm tắt

graph TD
    Q{Cần xây dựng gì?} --> A[Task 1 bước, input → output cố định]
    Q --> B[Task nhiều bước, biết trước cấu trúc]
    Q --> C[Task nhiều bước, phụ thuộc kết quả trung gian]
    A --> REFLEX[Reflex Agent]
    B --> PLANNING[Planning Agent]
    C --> REACT[ReAct Agent]
    REACT --> FW{Framework?}
    PLANNING --> FW
    FW --> LG[LangGraph - kiểm soát chi tiết]
    FW --> CREW[CrewAI - prototype nhanh]
Khái niệm Ghi nhớ
Agent vs Pipeline Ai quyết định bước tiếp theo: code cố định hay LLM?
Core components Brain + Tools + Memory + Planning Loop
System prompt Lắp ráp từ 6 tầng, lọc theo task - không viết 1 khối văn bản
AGENTS.md / SOUL.md Tách "làm gì" (vận hành) khỏi "là ai" (tính cách)
Reflex 1 bước, không nhớ, không lập kế hoạch
Planning Lập kế hoạch toàn bộ trước khi thực thi
ReAct Suy nghĩ - Hành động - Quan sát, lặp lại
MCP Chuẩn hoá kết nối agent ↔ tool, tránh N×M integration