Vòng lặp agent vốn dĩ hay lặp lại: model gọi lại tool khi kết quả không như mong đợi, request bị timeout rồi retry, agent bị restart và replay lại lịch sử. Nên tool ghi phải idempotent, đó là yêu cầu thiết kế chứ không phải tùy chọn.
Idempotency key do phía gọi sinh ra, gắn với ý định chứ không gắn với lần thử:
def create_order(user_id, items, idempotency_key):
existing = db.find_by_key(idempotency_key)
if existing:
return existing # replay returns the same order, no new row
return db.insert(user_id, items, idempotency_key)Khóa nên được sinh từ (session_id, tên tool, tham số đã chuẩn hóa) hoặc do lớp orchestrator cấp, không để model tự bịa — model sinh khóa ngẫu nhiên mỗi lần thì cơ chế mất tác dụng.
Các lớp bảo vệ đi kèm:
- Tách đọc và ghi: tool đọc cho chạy tự do; tool ghi đi qua danh sách hẹp, có kiểm tra quyền ở phía server (đừng tin user_id model truyền vào).
- Human-in-the-loop theo ngưỡng: hành động vượt hạn mức (hoàn tiền > X, gửi mail hàng loạt) thì dừng lại xin xác nhận.
- Hạn mức và trần: giới hạn số lần gọi tool ghi trong một phiên, rate limit theo user.
- Audit log: ghi lại đủ session, tool, tham số, kết quả để dựng lại sự việc khi có khiếu nại.
Câu chốt khi trả lời phỏng vấn: an toàn không nằm ở prompt. Prompt "hãy cẩn thận, đừng gọi hai lần" không phải là một cơ chế — ràng buộc phải nằm ở tầng thực thi tool.