Các bài trong khoáBài 1/30

30 bài

Domain 1: Agentic Architecture & Orchestration·Task 1.1

Vòng lặp agent và stop_reason

Agent gọi Claude, chạy tool, gửi kết quả rồi gọi tiếp. Bài này giúp bạn biết khi nào vòng lặp phải chạy tiếp, khi nào dừng, và những cách dừng sai hay gặp.

  • 8 phút đọc
  • Đối chiếu docs 02/11/2026
  • 5 nguồn

Đọc xong bạn nắm được

  • Biết khi nào vòng lặp phải gọi Claude tiếp, khi nào dừng
  • Gửi kết quả tool về đúng cách để Claude dùng được ở lượt sau
  • Phân biệt agent tự chọn bước tiếp theo với quy trình viết sẵn trong code
  • Nhận ra ba cách dừng vòng lặp nghe hợp lý nhưng sai

Khi bạn cho Claude dùng tool, Claude không tự chạy tool đó. Nó chỉ trả lời kiểu "tôi muốn gọi tool này, với tham số này". Việc chạy tool, gửi kết quả lại cho Claude và gọi Claude thêm lần nữa là việc của code bạn viết. Đoạn code lặp đi lặp lại như vậy gọi là vòng lặp agent, tiếng Anh là agentic loop.

Câu hỏi quan trọng nhất của bài: làm sao code biết lúc nào lặp tiếp, lúc nào dừng? Câu trả lời nằm ở một field trong phản hồi của Claude, tên là stop_reason.

Ví dụ xuyên suốt: agent đặt phòng họp

Giả sử công ty bạn có một agent đặt phòng họp, được cho dùng hai tool:

  • find_rooms: tìm phòng còn trống theo ngày, giờ, số người và thiết bị cần có.
  • book_room: giữ một phòng và trả về mã đặt phòng.

Một nhân viên nhắn: "Đặt giúp mình phòng cho 6 người, chiều thứ Năm 14h–15h, cần máy chiếu."

Agent sẽ chạy qua ba lượt:

LượtClaude trả vềstop_reasonCode của bạn làm gì
1Yêu cầu gọi find_roomstool_useChạy find_rooms, gửi kết quả cho Claude: phòng P302 và P305 còn trống
2Yêu cầu gọi book_room cho phòng P302tool_useChạy book_room, gửi kết quả cho Claude: mã đặt BK-0412
3Câu trả lời: "Mình đã đặt phòng P302…"end_turnDừng, gửi câu trả lời cho nhân viên

Để ý là trong code không có dòng nào viết "tìm phòng xong thì đặt phòng". Claude tự quyết định lượt 2 làm gì sau khi thấy kết quả của lượt 1.

Vòng lặp chạy thế nào

Mỗi vòng có bốn bước:

  1. Gửi cho Claude toàn bộ cuộc hội thoại từ đầu tới giờ, kèm danh sách tool.
  2. Xem stop_reason trong phản hồi.
  3. Nếu là tool_use, nghĩa là Claude muốn gọi tool: chạy tool đó, rồi thêm kết quả vào cuộc hội thoại.
  4. Quay lại bước 1. Nếu là end_turn, nghĩa là Claude đã trả lời xong: dừng.

Viết bằng TypeScript, vòng lặp trông như sau. Bạn chỉ cần để ý những chữ in đậm:

const messages: MessageParam[] = [
  { role: "user", content: "Đặt phòng cho 6 người, chiều thứ Năm 14h–15h, cần máy chiếu" },
];

while (true) {
  const response = await client.messages.create({ model, max_tokens: 1024, tools, messages });
  messages.push({ role: "assistant", content: response.content });

  if (response.stop_reason !== "tool_use") return response;

  const results: ToolResultBlockParam[] = [];
  for (const block of response.content) {
    if (block.type !== "tool_use") continue;
    results.push({
      type: "tool_result",
      tool_use_id: block.id,
      content: await runTool(block.name, block.input),
    });
  }
  messages.push({ role: "user", content: results });
}

Cho gọn, dòng return ở trên coi mọi giá trị khác tool_use là dừng. Khi viết thật, bạn nên xử lý riêng từng giá trị, xem mục cuối bài.

Gửi kết quả tool về cho đúng

Claude không có trí nhớ giữa các lần gọi. Nó chỉ biết những gì nằm trong danh sách messages bạn gửi lên. Nếu bạn quên thêm kết quả của find_rooms vào đó, ở lượt sau Claude sẽ không biết P302 còn trống, và sẽ gọi lại find_rooms hoặc đoán bừa.

Khi gửi kết quả tool về, bạn cần làm đúng mấy điều sau, nếu không API sẽ báo lỗi hoặc Claude sẽ hiểu sai:

  • Trước tiên, lưu nguyên phản hồi của Claude vào messages (vai assistant), rồi mới thêm kết quả.
  • Message chứa kết quả phải nằm ngay sau message có yêu cầu gọi tool. Không chen message nào khác vào giữa.
  • Mỗi yêu cầu gọi tool có một id riêng. Kết quả gửi về phải ghi đúng id đó trong field tool_use_id, để Claude biết kết quả nào thuộc yêu cầu nào. Thiếu kết quả cho một id thì API báo lỗi.
  • Trong message kết quả, các khối tool_result phải đứng đầu tiên. Đặt chữ lên trước thì API trả lỗi 400.
  • Tool chạy bị lỗi thì vẫn gửi tool_result, thêm is_error: true và mô tả lỗi, để Claude biết mà tìm cách khác.

Claude có thể yêu cầu gọi nhiều tool cùng lúc, ví dụ tìm phòng ở hai tầng một lượt. Khi đó bạn chạy hết, rồi gửi tất cả kết quả trong một message duy nhất.

Để Claude chọn bước tiếp theo, hay viết sẵn trong code

Có hai cách để một hệ thống biết bước tiếp theo làm gì. Đề thi gọi cách thứ nhất là model-driven decision-making, cách thứ hai là pre-configured decision trees hay tool sequences:

Để Claude tự chọnViết sẵn thứ tự trong code
Ai quyết định bước tiếp theoClaude, dựa vào kết quả vừa nhậnCode, theo thứ tự đã định
Khi find_rooms không tìm thấy phòng nàoClaude có thể tìm khung giờ khác, hoặc hỏi lại người dùngCode vẫn gọi book_room và lỗi, hoặc dừng luôn
Hợp vớiYêu cầu đa dạng, khó đoán trướcQuy trình cố định, lần nào cũng giống nhau

Vòng lặp agent đi theo cách thứ nhất. Còn khi một bước bắt buộc phải làm trước bước khác, ví dụ phải xác minh danh tính rồi mới được hoàn tiền, thì nên chặn bằng code thay vì chỉ dặn trong prompt. Phần đó nằm ở bài 1.4.

Ba cách dừng vòng lặp nghe hợp lý nhưng sai

Có ba cách quyết định "đã xong chưa" mà nhiều người hay dùng, tiếng Anh gọi chung là anti-pattern (cách làm sai nhưng phổ biến). Trong đề thi, chúng thường nằm ở các đáp án sai, nên bạn cần nhận ra ngay. Mỗi cách có kèm cách đề thi tiếng Anh mô tả nó:

  1. Đọc nội dung câu trả lời để đoán đã xong (parsing natural language signals to determine loop termination). Ví dụ code dò thấy trong câu trả lời có chữ "đã đặt phòng xong" thì dừng. Câu đó chỉ là lời Claude nói với người dùng, không phải tín hiệu gì của API. Claude có thể viết câu đó mà vẫn còn muốn gọi thêm tool, hoặc lần sau diễn đạt khác đi.
  2. Đặt số vòng tối đa làm cách dừng chính (setting arbitrary iteration caps as the primary stopping mechanism). Ví dụ "chạy tối đa 5 vòng". Việc cần 6 vòng sẽ bị cắt giữa chừng, còn agent đang lặp vô ích vẫn chạy đủ 5 vòng mới chịu dừng.
  3. Thấy phản hồi có chữ là coi như xong (checking for assistant text content as a completion indicator). Một phản hồi có thể vừa có chữ ("Để mình tìm phòng trước nhé") vừa có yêu cầu gọi tool. Có chữ không có nghĩa là hết việc.

Đặt số vòng tối đa vẫn có ích, nhưng chỉ để phòng hờ agent chạy không dứt. Agent SDK của Anthropic có tuỳ chọn max_turns cho việc này. Mặc định nó không giới hạn, và khi chạm ngưỡng thì kết quả trả về báo lỗi error_max_turns. Agent dừng bình thường là nhờ stop_reason; giới hạn số vòng chỉ để chặn trường hợp bất thường.

Các giá trị khác của stop_reason

Đề thi chủ yếu hỏi tool_use và end_turn. Khi viết agent thật, bạn sẽ gặp thêm vài giá trị nữa. Biết qua để không coi nhầm chúng là "đã xong":

Giá trịNghĩa làNên làm gì
max_tokensCâu trả lời bị cắt vì chạm giới hạn max_tokens bạn đặtTăng max_tokens hoặc cho Claude viết tiếp
stop_sequenceClaude gặp một chuỗi dừng mà bạn tự đặtXem field stop_sequence để biết chuỗi nào
pause_turnTool chạy phía Anthropic (như web search) đã lặp tới giới hạn, mặc định 10 lượtGửi lại nguyên phản hồi để Claude làm tiếp
refusalClaude từ chối trả lờiXem stop_details để biết lý do, có thể thử lại bằng model khác
model_context_window_exceededCâu trả lời lấp đầy giới hạn ngữ cảnh của modelCoi như câu trả lời bị cắt
  1. stop_reason là tool_use?Chạy tool, gửi kết quả, gọi Claude tiếp
  2. pause_turn?Gửi lại nguyên phản hồi để Claude làm tiếp
  3. max_tokens hoặc model_context_window_exceeded?Câu trả lời bị cắt: tăng max_tokens hoặc cho viết tiếp
  4. refusal?Xem stop_details, thử model khác hoặc báo người dùng
  5. Còn lạiend_turn hoặc stop_sequence: dừng, dùng câu trả lời

Nguồn

  1. Exam Guide CCAR-F v1.0, Task Statement 1.1(mở tab mới)
  2. Handling stop reasons (Claude API)(mở tab mới)
  3. Handle tool calls (Claude API)(mở tab mới)
  4. Parallel tool use (Claude API)(mở tab mới)
  5. How the agent loop works (Agent SDK)(mở tab mới)

Nắm rồi thì thử sức với đề

Xem khoá luyện thi
Vòng lặp agent và stop_reason · Anthropic Exam Pro