Bài này bạn viết một agent bằng code, bắt đầu từ tool use thuần (hiểu bản chất), rồi biết khi nào nên nâng lên LangGraph. Cùng bài toán CSKH ở Bài 5 để dễ đối chiếu.
Bước 1 — Định nghĩa tool
tools = [
{"name": "search_faq", "description": "Tra FAQ theo câu hỏi",
"input_schema": {"type": "object",
"properties": {"query": {"type": "string"}}, "required": ["query"]}},
{"name": "get_order", "description": "Tra đơn hàng theo mã",
"input_schema": {"type": "object",
"properties": {"order_id": {"type": "string"}}, "required": ["order_id"]}},
]
Bước 2 — Vòng lặp agent (tool use thuần)
def run_tool(name, args):
if name == "search_faq": return faq_lookup(args["query"])
if name == "get_order": return order_lookup(args["order_id"])
messages = [{"role": "user", "content": user_question}]
while True:
resp = client.messages.create(
model="claude-...", max_tokens=1024,
system="Chỉ trả lời dựa trên tool. Không chắc thì nói không biết.",
tools=tools, messages=messages)
if resp.stop_reason != "tool_use":
print(resp.content[0].text); break # câu trả lời cuối
messages.append({"role": "assistant", "content": resp.content})
results = []
for block in resp.content:
if block.type == "tool_use":
out = run_tool(block.name, block.input)
results.append({"type": "tool_result",
"tool_use_id": block.id, "content": str(out)})
messages.append({"role": "user", "content": results})
Đây là trái tim của mọi agent. Framework nào cũng bọc quanh vòng lặp này.
Bước 3 — Khi nào nâng lên LangGraph
Dừng lại và nâng cấp khi bạn gặp một trong các dấu hiệu:
- Cần rẽ nhánh có điều kiện rõ ràng (nếu là khiếu nại → nhánh khác).
- Cần lưu state qua nhiều lượt / nhiều phiên (persistence, checkpoint).
- Cần human-in-the-loop (dừng chờ người duyệt rồi chạy tiếp).
- Vòng lặp tự viết bắt đầu rối, khó test.
# LangGraph (ý tưởng): mô hình hóa thành đồ thị state
# builder.add_node("agent", call_model)
# builder.add_node("tools", tool_node)
# builder.add_conditional_edges("agent", should_continue, {"tools": "tools", "end": END})
# builder.add_edge("tools", "agent")
# graph = builder.compile(checkpointer=memory) # có persistence
Các bước triển khai
- Viết tool use thuần trước để hiểu và kiểm soát.
- Thêm giới hạn số vòng lặp (tránh loop vô hạn đốt token).
- Test các nhánh: FAQ, tra đơn, ngoài phạm vi.
- Chỉ khi chạm giới hạn (state/branch/human-in-loop) mới chuyển LangGraph.
- Giữ tool tách biệt, tái dùng được ở cả hai kiến trúc.
Một điểm khác biệt then chốt giữa tool use thuần và LangGraph là quản lý state. Trong vòng lặp thuần, state của bạn chính là biến messages — mất khi tiến trình kết thúc. LangGraph cho phép gắn checkpointer để lưu state ra bộ nhớ/CSDL, nên agent có thể tạm dừng chờ người duyệt rồi chạy tiếp đúng chỗ đã dừng, hoặc phục hồi sau khi server restart. Nếu bài toán của bạn là một câu hỏi–một câu trả lời trong một request, tool use thuần là đủ. Nếu là quy trình dài nhiều chặng, có phê duyệt, có gián đoạn, thì state bền vững của LangGraph mới đáng giá.
Khung tư duy pro-code
> Bắt đầu từ vòng lặp tool use tối giản. Nâng lên framework khi — và chỉ khi — bạn cần state, branch, hoặc human-in-the-loop. Framework là để giải quyết độ phức tạp, không phải để trông "pro".
Sai lầm thường gặp
- Không giới hạn số vòng lặp: agent kẹt loop, đốt token và có thể gọi tool lặp vô hạn.
- Nhảy thẳng vào LangGraph mà chưa hiểu tool use, dẫn tới không debug được khi lỗi.
- Trộn logic tool vào vòng lặp: khó test, khó tái dùng. Tách hàm tool riêng.
- Bỏ qua xử lý lỗi tool: khi API đơn hàng sập, agent nhận rác và trả lời sai thay vì báo lỗi.