Bài 3 bạn chạy 1 tool 1 vòng. Thực tế agent phải chạy nhiều tool, nhiều vòng cho tới khi hoàn thành nhiệm vụ. Đây là trái tim của agent engineering.
Vòng lặp agent (agent loop)
Thay vì gọi model 1-2 lần cứng, ta bọc trong vòng while:
def run_agent(user_msg, tools, tool_map, max_steps=6):
msgs = [{"role": "user", "content": user_msg}]
for _ in range(max_steps):
r = client.chat.completions.create(
model="gpt-4o-mini", messages=msgs, tools=tools)
m = r.choices[0].message
msgs.append(m)
if not m.tool_calls:
return m.content # xong: model tra ve text cuoi
for call in m.tool_calls: # co the goi nhieu tool 1 luot
args = json.loads(call.function.arguments)
out = tool_map[call.function.name](**args)
msgs.append({"role": "tool",
"tool_call_id": call.id,
"content": str(out)})
return "Da dat gioi han buoc." # chot an toan
Hai chi tiết SỐNG CÒN:
max_steps: chốt chặn chống vòng lặp vô hạn (agent gọi tool mãi không dừng -> cháy túi tiền). Luôn có giới hạn.- Vòng lặp dừng khi model trả về text thay vì tool_call — đó là tín hiệu "tôi đã đủ thông tin để trả lời".
Ví dụ: agent nghiên cứu giá
Nhiệm vụ: "So sánh giá iPhone ở 2 cửa hàng và tính chênh lệch". Agent sẽ:
- Gọi
get_price("shopA")-> 25000000 - Gọi
get_price("shopB")-> 24200000 - Gọi
calculate("25000000 - 24200000")-> 800000 - Trả text: "Shop A đắt hơn Shop B 800.000đ."
Memory: ngắn hạn vs dài hạn
- Ngắn hạn (short-term): chính là mảng
msgs— ngữ cảnh hội thoại hiện tại. Vấn đề: dài quá sẽ vượt context window và tốn token. Giải pháp: tóm tắt (summarize) các lượt cũ. - Dài hạn (long-term): lưu ra ngoài (vector DB, database) rồi truy hồi khi cần. Ví dụ: nhớ tên khách, đơn hàng cũ giữa các phiên.
Context window that -> tom tat 10 luot dau thanh 1 doan -> giu nguyen 3 luot gan nhat
Khung tư duy thiết kế tool tốt
Một tool tốt phải:
- Đơn nhiệm: mỗi tool làm 1 việc rõ ràng (
get_order, không phảido_everything). - Mô tả (description) rõ: model chọn tool dựa vào description — mô tả mơ hồ = model chọn sai.
- Tham số chặt chẽ: dùng enum/required để giảm ảo giác tham số.
- Trả lỗi có ý nghĩa: khi lỗi, trả chuỗi mô tả để model tự sửa ("khong tim thay don, kiem tra lai ma") thay vì crash.
Các bước xây một multi-tool agent
- Liệt kê các tool cần thiết cho nhiệm vụ.
- Viết từng hàm tool + JSON schema, test riêng từng hàm.
- Bọc vòng lặp agent có
max_steps. - Thêm log in ra tool nào được gọi với tham số gì (để debug).
- Chạy thử 5-10 tình huống, quan sát agent chọn tool đúng/sai.
- Sửa description tool cho các trường hợp chọn sai.
ReAct: vì sao cho model "nghĩ ra tiếng" lại hiệu quả
ReAct (Reasoning + Acting) là mẫu thiết kế nền tảng: trước khi chọn tool, model diễn giải suy nghĩ ("tôi cần biết giá shop A trước") rồi mới hành động. Việc buộc model lập luận từng bước giúp nó chọn tool đúng hơn và bạn debug dễ hơn vì thấy được "lý do" đằng sau mỗi hành động.
Thought: Toi can gia shop A.
Action: get_price(shopA)
Observation: 25000000
Thought: Gio can gia shop B.
Action: get_price(shopB)
Observation: 24200000
Thought: Da du du lieu, tinh chenh lech.
Phần lớn framework agent hiện đại đều là biến thể của vòng lặp này.
Khi nào một tác vụ KHÔNG cần agent nhiều bước
Nếu trình tự các bước là cố định và biết trước (luôn A -> B -> C), hãy viết một workflow cứng gọi tuần tự — rẻ hơn, ổn định hơn, dễ test hơn. Chỉ dùng vòng lặp agent tự-quyết khi trình tự phụ thuộc vào kết quả trung gian mà bạn không đoán trước được. Nhầm lẫn hai thứ này là lỗi thiết kế phổ biến khiến hệ thống vừa đắt vừa khó đoán.
Checklist agent nhiều bước
- [ ] Có
max_stepschống loop vô hạn. - [ ] Log mỗi lần gọi tool để debug.
- [ ] Tool trả lỗi dạng text để model tự phục hồi.
- [ ] Có chiến lược cắt/tóm tắt ngữ cảnh khi hội thoại dài.
- [ ] Đã cân nhắc: việc này có thực sự cần agent, hay chỉ cần workflow cứng?
Sai lầm thường gặp
- Không giới hạn số bước -> agent lặp vô tận, hoá đơn API tăng vọt.
- Tool description qua loa -> model gọi nhầm tool hoặc bịa tham số.
- Nhồi toàn bộ lịch sử vào mỗi lần gọi -> vượt context, đắt và chậm; phải tóm tắt.
- Để tool crash khi lỗi thay vì trả thông báo -> agent không có cơ hội thử lại.