Agent Architecture
Kiến trúc Agent — Bộ não của AI tự chủ
Bạn muốn xây AI có thể: tìm vé máy bay, so sánh giá, đặt vé, và tự điều chỉnh khi chuyến bị đầy. Agent này cần tối thiểu bao nhiêu thành phần?
Hình minh họa
Bên trong một Agent đặt vé máy bay
Nhấn vào từng thành phần để xem vai trò. Dùng thanh pha ở dưới để chạy vòng lặp Perceive → Plan → Act → Reflect.
Perceive — Agent nhận yêu cầu từ người dùng, môi trường hoặc kết quả tool trả về. Đây là giai đoạn 'nghe' và 'đọc'.
Ví dụ (đặt vé): Người dùng gõ: 'Đặt vé SGN → Tokyo ngày 2/5, dưới 15 triệu, thích Vietnam Airlines'. LLM parse ý định, lưu vào bộ nhớ ngắn hạn.
Latency trung bình: ~80 ms
Tokens tiêu thụ: input tokens
Nguy cơ sai sót: Thấp — chỉ là đọc hiểu
Thành phần chính: LLM + Short-term memory
Đầu ra: Intent đã parse + entities
LLM
Bộ não trung tâm
Phân tích yêu cầu người dùng, suy luận từng bước, quyết định gọi công cụ nào và tổng hợp kết quả cuối cùng.
Ẩn dụ: Như vỏ não trước (prefrontal cortex) của con người — nơi diễn ra suy luận, ra quyết định và lập ngôn ngữ.
Vai trong đặt vé: Đọc câu lệnh 'Đặt vé TP.HCM → Tokyo ngày 2/5 dưới 15 triệu', hiểu ý định, chia nhỏ thành các yêu cầu con: tìm chuyến, so sánh giá, đặt chỗ, xuất vé.
Agent được giao: 'Tìm 5 bài báo về AI, tóm tắt mỗi bài, gửi email tổng hợp cho sếp'. Những thành phần nào phải phối hợp?
Giải thích
Kiến trúc Agent hiện đại gồm 4 thành phần cốt lõi hoạt động trong vòng lặp liên tục, còn gọi là agentic loop. Mỗi thành phần có chức năng riêng biệt nhưng phải phối hợp chặt chẽ thông qua một giao thức chung (thường là JSON messages).
- LLM (bộ não): Trung tâm suy luận. Nhận input từ người dùng + context từ bộ nhớ + kết quả từ công cụ → đưa ra quyết định tiếp theo. Thường là GPT-4, Claude, hay Gemini.
- Bộ nhớ: Chia hai tầng. Ngắn hạn là context window + scratchpad JSON. Dài hạn là vector DB (Pinecone, Weaviate, pgvector) truy cập qua embedding.
- Công cụ: Mở rộng khả năng hành động — search web, code execution, API calls, DB queries, trình duyệt, file system. Mô tả bằng JSON Schema để LLM biết cách gọi.
- Lập kế hoạch: Task decomposition + reflection + self-correction. Biến nhiệm vụ phức tạp thành chuỗi bước khả thi và giữ Agent đi đúng hướng.
Mối liên hệ toán học giữa các thành phần có thể biểu diễn dạng state transition:
trong đó là trạng thái Agent ở bước (bao gồm memory), là hành động (tool call) được LLM chọn, là quan sát (kết quả tool), và là hàm chuyển trạng thái của môi trường. Đây là hệ thống Markov Decision Process (MDP) quen thuộc trong Reinforcement Learning.
# Pseudocode dùng LangGraph để triển khai vòng lặp Agent 4 pha
from typing import TypedDict, Annotated
from langgraph.graph import StateGraph, END
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
class AgentState(TypedDict):
"""Trạng thái được chuyền qua các pha"""
user_request: str
plan: list[str]
current_step: int
tool_results: list[dict]
long_term_memory: dict
final_answer: str | None
llm = ChatOpenAI(model="gpt-4o", temperature=0)
@tool
def search_flights(origin: str, destination: str, date: str, max_price: int) -> list[dict]:
"""Tìm chuyến bay theo tuyến và ngân sách."""
# Giả lập gọi API
return [{"id": "VN-301", "price": 12000000, "airline": "VietnamAirlines"}]
@tool
def book_flight(flight_id: str, passenger: dict) -> dict:
"""Đặt vé và trả về mã xác nhận."""
return {"confirmation": "ABC123", "flight_id": flight_id}
TOOLS = [search_flights, book_flight]
# ── Pha 1: Perceive ────────────────────────────────────────────────────────
def perceive(state: AgentState) -> AgentState:
# Chuẩn hoá yêu cầu thô của người dùng thành intent rõ ràng.
prompt = f"Parse intent và extract entities từ: {state['user_request']}"
parsed = llm.invoke(prompt)
state["user_request"] = parsed.content
return state
# ── Pha 2: Plan ─────────────────────────────────────────────────────────────
def plan(state: AgentState) -> AgentState:
# Tham chiếu long-term memory để cá nhân hoá
prefs = state["long_term_memory"].get("flight_prefs", {})
plan_prompt = (
f"Tạo kế hoạch 3-5 bước để hoàn thành: {state['user_request']}. "
f"Sở thích người dùng: {prefs}. "
f"Công cụ khả dụng: {[t.name for t in TOOLS]}"
)
response = llm.invoke(plan_prompt)
state["plan"] = response.content.split("\n")
state["current_step"] = 0
return state
# ── Pha 3: Act ──────────────────────────────────────────────────────────────
def act(state: AgentState) -> AgentState:
step = state["plan"][state["current_step"]]
# LLM chọn tool + tham số, sau đó ta execute
llm_with_tools = llm.bind_tools(TOOLS)
tool_call = llm_with_tools.invoke(f"Thực hiện bước: {step}")
for call in tool_call.tool_calls:
matched = next(t for t in TOOLS if t.name == call["name"])
result = matched.invoke(call["args"])
state["tool_results"].append({"step": step, "result": result})
state["current_step"] += 1
return state
# ── Pha 4: Reflect ──────────────────────────────────────────────────────────
def reflect(state: AgentState) -> AgentState:
recent = state["tool_results"][-1]
critique_prompt = (
f"Kết quả bước vừa rồi: {recent}. "
f"Đã hoàn thành yêu cầu '{state['user_request']}' chưa? "
"Nếu chưa, có cần thay đổi kế hoạch không?"
)
verdict = llm.invoke(critique_prompt)
if "hoàn thành" in verdict.content.lower():
state["final_answer"] = verdict.content
return state
def route_next(state: AgentState) -> str:
if state["final_answer"] is not None:
return END
if state["current_step"] >= len(state["plan"]):
return "plan" # Replan nếu hết bước mà chưa xong
return "act"
# ── Lắp ráp đồ thị ──────────────────────────────────────────────────────────
graph = StateGraph(AgentState)
graph.add_node("perceive", perceive)
graph.add_node("plan", plan)
graph.add_node("act", act)
graph.add_node("reflect", reflect)
graph.set_entry_point("perceive")
graph.add_edge("perceive", "plan")
graph.add_edge("plan", "act")
graph.add_edge("act", "reflect")
graph.add_conditional_edges("reflect", route_next, {
"act": "act",
"plan": "plan",
END: END,
})
agent = graph.compile()
result = agent.invoke({
"user_request": "Đặt vé TP.HCM → Tokyo ngày 2/5, dưới 15 triệu",
"plan": [],
"current_step": 0,
"tool_results": [],
"long_term_memory": {"flight_prefs": {"airline": "VietnamAirlines"}},
"final_answer": None,
})while True dễ dẫn đến race conditions, khó resume khi gặp lỗi, và khó kiểm thử. Graph-based agent là chuẩn công nghiệp hiện nay.max_steps giới hạn vòng lặp; (2) Guardrails giới hạn hành động nguy hiểm; (3) Monitoring log từng bước để debug khi Agent đi chệch.# CrewAI cho bạn định nghĩa Agent ở mức cao hơn, không cần tự viết graph.
from crewai import Agent, Task, Crew, Process
from crewai.memory import ShortTermMemory, LongTermMemory
from crewai_tools import SerperDevTool
search_tool = SerperDevTool()
# ── Định nghĩa Agent ─────────────────────────────────────────────────────
flight_planner = Agent(
role="Flight Planner",
goal="Đặt vé máy bay đúng ngân sách và sở thích người dùng",
backstory=(
"Bạn là chuyên gia đặt vé với 10 năm kinh nghiệm. "
"Ưu tiên chất lượng, giá, và sở thích người dùng trong thứ tự đó."
),
tools=[search_tool],
memory=True,
short_term_memory=ShortTermMemory(),
long_term_memory=LongTermMemory(),
allow_delegation=False,
verbose=True,
max_iter=8, # max_steps — chặn loop vô hạn
max_rpm=20, # rate limit API
)
# ── Định nghĩa Task ──────────────────────────────────────────────────────
book_task = Task(
description=(
"Tìm vé TP.HCM → Tokyo ngày 2/5, dưới 15 triệu, ưu tiên Vietnam Airlines. "
"Nếu không tìm thấy, đề xuất 2 giải pháp thay thế."
),
expected_output="Mã xác nhận đặt vé hoặc 2 giải pháp thay thế có giải thích.",
agent=flight_planner,
human_input=False, # Bật True nếu muốn hỏi xác nhận
)
# ── Crew: khung Agent + Task ────────────────────────────────────────────
crew = Crew(
agents=[flight_planner],
tasks=[book_task],
process=Process.sequential,
memory=True,
verbose=True,
)
result = crew.kickoff()
print(result)search_flights tốt hơn tool1). Viết docstring ngắn gọn nhưng đủ chi tiết để LLM hiểu KHI NÀO dùng. Giới hạn tham số (không nên quá 5). Trả về JSON có cấu trúc ổn định, tránh text tự do. Lý tưởng là mỗi tool chỉ làm một việc duy nhất, thay vì gộp nhiều hành vi vào một hàm khổng lồ — Agent dễ nhầm khi tool có quá nhiều nhánh.LLM
Phân tích yêu cầu người dùng, suy luận từng bước, quyết định gọi công cụ nào và tổng hợp kết quả cuối cùng.
Bộ nhớ ngắn hạn
Lưu trữ thông tin trong phiên hiện tại: lịch sử hội thoại, kết quả tool call, ghi chú trung gian. Bị giới hạn bởi context window của LLM.
Bộ nhớ dài hạn
Lưu trữ vĩnh viễn: sở thích người dùng, các chuyến đi trước, kiến thức miền. Truy vấn qua embedding + semantic search.
Công cụ
Các hành động Agent có thể thực hiện: gọi API, truy vấn DB, chạy code, duyệt web, gửi email. Mỗi tool có schema rõ ràng (tên, tham số, mô tả).
Lập kế hoạch
Chia bài toán lớn thành chuỗi bước nhỏ, giám sát tiến độ, phát hiện lệch hướng và điều chỉnh (replan) khi cần.
Agent đặt vé đã tìm được 3 chuyến phù hợp trong pha Act. Pha nào tiếp theo chịu trách nhiệm quyết định 'đề xuất cho user hay tìm thêm'?
- 4 thành phần cốt lõi: LLM (bộ não suy luận), Memory (ngắn hạn context + dài hạn vector DB), Tools (API/code/DB — mô tả bằng JSON Schema), Planning (chia bước + reflection).
- Agent hoạt động theo vòng lặp 4 pha: Perceive (nhận thức) → Plan (lập kế hoạch) → Act (hành động) → Reflect (phản ánh) → lặp lại.
- Khác chatbot: Agent TỰ CHỦ thực hiện nhiều bước với môi trường thực, thay vì chỉ phản hồi 1 lượt hội thoại.
- Long-term memory qua vector DB cho phép Agent nhớ sở thích người dùng xuyên phiên; short-term dùng context window cho phiên hiện tại.
- Bẫy phổ biến: loop vô hạn, gọi sai tool, mất ngữ cảnh. Luôn có max_steps, guardrails, và logging từng bước.
- Framework chuẩn: LangGraph (graph-based, rõ state), CrewAI (declarative role/task), AutoGen (multi-agent chat) — chọn theo nhu cầu cụ thể.
Kiểm tra hiểu biết
Thành phần nào KHÔNG thể thiếu trong mọi AI Agent?
Bạn đã nắm kiến trúc tổng thể — bước tiếp theo:
- Học cách Agent chọn tool qua function calling.
- Đi sâu vào Planning — chiến lược chia bài toán lớn.
- Khám phá Memory Systems với 3 tầng: working, episodic, semantic.
- Xem các mẫu workflow ở Agentic Workflows.
- Khi có nhiều Agent, bạn sẽ cần Multi-Agent + Orchestration.
Danh sách kiểm tra trước khi triển khai Agent lên production:
- Giới hạn bước:
max_iterhoặcrecursion_limitđược set cụ thể, không để mặc định vô tận. - Sandbox: mọi tool thực thi code phải chạy trong container cô lập (Docker, Firecracker, gVisor), không bao giờ chạy trực tiếp trên máy chủ chính.
- Allowlist: tool gọi API phải chỉ được phép truy cập domain đã whitelist, không mở rộng ra toàn bộ internet.
- Audit log: mỗi tool call + tham số + kết quả ghi vào log có thể truy vết — tối thiểu 30 ngày.
- Human-in-the-loop: các hành động không đảo ngược (send email, charge payment, delete file) phải chờ confirmation trước khi thực thi.
- Budget guard:theo dõi tổng token + tổng chi phí theo phiên. Tự ngắt khi vượt ngưỡng để tránh "cost explosion".
- Test harness: viết test giả lập môi trường (mock tools) để Agent có thể được kiểm thử regression mỗi khi prompt hay model thay đổi.
- Observability: dùng LangSmith, Langfuse hoặc Arize — trực quan hoá graph run, xem token flow, đánh giá chất lượng qua LLM judge.
Case study nhỏ để luyện tập:
- Personal research assistant: Agent nhận câu hỏi nghiên cứu, tự tìm 5 nguồn, tóm tắt, và xuất bản tóm tắt markdown. Cần: search tool, read tool, memory để tránh đọc trùng, reflection để đánh giá chất lượng tóm tắt.
- Helpdesk Agent: đọc ticket, phân loại, tham chiếu KB (vector DB), đề xuất giải pháp, chuyển ticket khó cho người thật. Cần: memory dài hạn (KB), memory ngắn hạn (ticket context), tool gọi CRM.
- Data analysis Agent: nhận câu hỏi dữ liệu, tự viết SQL, chạy, kiểm tra kết quả bất thường, vẽ biểu đồ. Cần: code execution tool (sandbox), vector DB schema, reflection để phát hiện bug SQL.