Vòng lặp agent về bản chất rất ngắn: gọi model kèm khai báo tool → nếu model xin gọi tool thì chạy tool, nhét kết quả vào hội thoại, gọi lại → lặp cho tới khi model trả lời thẳng.
TOOLS = [{
"type": "function",
"function": {
"name": "calculator",
"description": "Tính một biểu thức toán. Dùng cho mọi phép tính.",
"parameters": {"type": "object", "required": ["expression"],
"properties": {"expression": {"type": "string",
"description": "Biểu thức Python, vd 'sqrt(2) * 15'"}}},
}},
# ... web_search khai báo tương tự
]
def run_agent(user_query: str, max_iterations: int = 10) -> str:
messages = [{"role": "system", "content": SYSTEM_PROMPT},
{"role": "user", "content": user_query}]
for _ in range(max_iterations):
msg = client.chat.completions.create(
model="gpt-4o-mini", messages=messages,
tools=TOOLS, tool_choice="auto", temperature=0,
).choices[0].message
messages.append(msg.model_dump(exclude_none=True))
if not msg.tool_calls: # không gọi tool nữa = đã có câu trả lời
return msg.content
for tc in msg.tool_calls: # chạy từng tool, trả kết quả vào hội thoại
args = json.loads(tc.function.arguments)
result = TOOL_IMPLS[tc.function.name](args)
messages.append({"role": "tool", "tool_call_id": tc.id,
"content": str(result)})
return "Agent vượt quá số vòng cho phép."Ví dụ hỏi "GDP Việt Nam 2023 chia đều cho 100 triệu dân là bao nhiêu": model gọi web_search lấy số GDP, rồi gọi calculator chia, rồi mới trả lời.
Ba chỗ quyết định agent chạy được hay không:
max_iterationslà bắt buộc. Thiếu nó, một tool trả kết quả model không hiểu sẽ khiến nó gọi đi gọi lại tới hết ngân sách. Đây là lỗi số một khi tự viết agent.- Mô tả tool quan trọng hơn code tool. Model chọn tool hoàn toàn dựa vào phần
description, nên mô tả phải nói rõ khi nào dùng, không chỉ nó làm gì. Và giữ số tool ít (dưới khoảng hai chục) — càng nhiều tool càng dễ chọn nhầm. - Đừng
evalbiểu thức người dùng đưa vào. Ví dụ trên viết cho gọn; bản thật phải dùng trình đánh giá biểu thức có giới hạn (simpleeval,asteval) hoặc chạy trong sandbox. Với agent, đây không chỉ là lỗ hổng thường mà là lỗ hổng model có thể bị lừa để kích hoạt qua nội dung nó đọc được.
Khi lên production thêm: bắt lỗi và retry quanh mỗi lần gọi tool; log từng bước để lần lại được khi agent đi sai; và tận dụng việc model gọi nhiều tool trong cùng một bước để chạy song song, tiết kiệm độ trễ.
Nếu không muốn tự viết: LangGraph khi cần luồng phức tạp có trạng thái, Vercel AI SDK nếu làm Next.js, hoặc Assistants API nếu muốn phần quản lý trạng thái do nhà cung cấp lo. Còn muốn tool dùng lại được giữa nhiều agent thì expose tool qua MCP thay vì viết cứng trong từng ứng dụng.