วิธีการทำงานของ Agent Loop
ทำความเข้าใจวงจรชีวิตของข้อความ การดำเนินการ tool context window และสถาปัตยกรรมที่ขับเคลื่อน SDK agents
Agent SDK ช่วยให้คุณฝัง agent loop อัตโนมัติของ Claude Code ลงในแอปพลิเคชันของคุณ SDK เป็น package แบบ standalone ที่ให้คุณควบคุม tools, permissions, ขีดจำกัดต้นทุน และ output ได้ด้วยโปรแกรม คุณไม่จำเป็นต้องติดตั้ง Claude Code CLI เพื่อใช้งาน
เมื่อคุณเริ่ม agent SDK จะรัน execution loop เดียวกับที่ขับเคลื่อน Claude Code: Claude ประเมิน prompt ของคุณ เรียกใช้ tools เพื่อดำเนินการ รับผลลัพธ์ และวนซ้ำจนกว่างานจะเสร็จ หน้านี้จะอธิบายสิ่งที่เกิดขึ้นภายใน loop นั้น เพื่อให้คุณสร้าง debug และปรับแต่ง agents ได้อย่างมีประสิทธิภาพ
ภาพรวมของ Loop
ทุก agent session ทำตามวงจรเดียวกัน:
- รับ prompt Claude รับ prompt ของคุณ พร้อมกับ system prompt, tool definitions และประวัติการสนทนา SDK จะส่ง
SystemMessageที่มี subtype"init"ซึ่งประกอบด้วย session metadata - ประเมินและตอบสนอง Claude ประเมินสถานะปัจจุบันและตัดสินใจว่าจะดำเนินการอย่างไร อาจตอบด้วยข้อความ ร้องขอการเรียกใช้ tool หนึ่งรายการขึ้นไป หรือทั้งสองอย่าง SDK จะส่ง
AssistantMessageที่ประกอบด้วยข้อความและคำขอเรียกใช้ tool ต่างๆ - ดำเนินการ tools SDK รัน tool ที่ร้องขอแต่ละรายการและรวบรวมผลลัพธ์ ผลลัพธ์ของแต่ละชุด tool จะส่งกลับไปยัง Claude เพื่อการตัดสินใจครั้งถัดไป คุณสามารถใช้ hooks เพื่อดักจับ แก้ไข หรือบล็อก tool calls ก่อนที่จะรัน
- วนซ้ำ ขั้นตอนที่ 2 และ 3 วนซ้ำเป็นวัฏจักร แต่ละรอบเต็มคือหนึ่ง turn Claude ยังคงเรียก tools และประมวลผลผลลัพธ์จนกว่าจะสร้างการตอบสนองที่ไม่มี tool calls
- ส่งคืนผลลัพธ์ SDK ส่ง
AssistantMessageสุดท้ายพร้อมการตอบสนองข้อความ (ไม่มี tool calls) ตามด้วยResultMessageพร้อมข้อความสุดท้าย การใช้ token ต้นทุน และ session ID
Turns และ Messages
Turn คือการเดินทางไปกลับหนึ่งครั้งภายใน loop: Claude สร้าง output ที่มี tool calls, SDK ดำเนินการ tools เหล่านั้น และผลลัพธ์จะส่งกลับไปยัง Claude โดยอัตโนมัติ สิ่งนี้เกิดขึ้นโดยไม่ต้องคืนการควบคุมกลับไปยังโค้ดของคุณ Turns ดำเนินต่อไปจนกว่า Claude จะสร้าง output ที่ไม่มี tool calls
ลองพิจารณาว่า session เต็มรูปแบบอาจมีลักษณะอย่างไรสำหรับ prompt "Fix the failing tests in auth.ts":
- Turn 1: Claude เรียก
Bashเพื่อรันnpm testSDK ส่งAssistantMessageพร้อม tool call ดำเนินการคำสั่ง จากนั้นส่งUserMessageพร้อม output (ความล้มเหลวสามรายการ) - Turn 2: Claude เรียก
Readบนauth.tsและauth.test.tsSDK ส่งคืนเนื้อหาไฟล์และส่งAssistantMessage - Turn 3: Claude เรียก
Editเพื่อแก้auth.tsจากนั้นเรียกBashเพื่อรันnpm testอีกครั้ง - Turn สุดท้าย: Claude สร้างการตอบสนองแบบข้อความเท่านั้นโดยไม่มี tool calls
คุณสามารถจำกัด loop ด้วย max_turns / maxTurns ซึ่งนับเฉพาะ turns ที่ใช้ tool หรือใช้ max_budget_usd / maxBudgetUsd เพื่อจำกัด turns ตามค่าใช้จ่าย
ประเภทข้อความ
ขณะที่ loop รัน SDK จะส่งสตรีมของข้อความ ห้าประเภทหลักได้แก่:
SystemMessage: เหตุการณ์ lifecycle ของ session. fieldsubtypeบ่งบอกความแตกต่าง:"init"คือข้อความแรก (session metadata) และ"compact_boundary"จะเกิดหลัง compactionAssistantMessage: ส่งหลังจากการตอบสนองของ Claude แต่ละครั้งUserMessage: ส่งหลังจากการดำเนินการ tool แต่ละครั้งพร้อมผลลัพธ์ tool ที่ส่งกลับไปยัง ClaudeStreamEvent: ส่งเฉพาะเมื่อเปิดใช้งาน partial messages ประกอบด้วย raw API streaming eventsResultMessage: ทำเครื่องหมายจุดสิ้นสุดของ agent loop ประกอบด้วยผลลัพธ์ข้อความสุดท้าย การใช้ token ต้นทุน และ session ID
จัดการข้อความ
ข้อความที่คุณจัดการขึ้นอยู่กับสิ่งที่คุณกำลังสร้าง:
- ผลลัพธ์สุดท้ายเท่านั้น: จัดการ
ResultMessageเพื่อรับ output, ต้นทุน และว่างานสำเร็จหรือถึงขีดจำกัด - การอัปเดตความคืบหน้า: จัดการ
AssistantMessageเพื่อดูสิ่งที่ Claude ทำในแต่ละ turn - Streaming แบบ live: เปิดใช้งาน partial messages เพื่อรับ
StreamEventmessages แบบ real-time
from claude_agent_sdk import query, AssistantMessage, ResultMessage
async for message in query(prompt="Summarize this project"):
if isinstance(message, AssistantMessage):
print(f"Turn completed: {len(message.content)} content blocks")
if isinstance(message, ResultMessage):
if message.subtype == "success":
print(message.result)
else:
print(f"Stopped: {message.subtype}")
import { query } from "@anthropic-ai/claude-agent-sdk";
for await (const message of query({ prompt: "Summarize this project" })) {
if (message.type === "assistant") {
console.log(`Turn completed: ${message.message.content.length} content blocks`);
}
if (message.type === "result") {
if (message.subtype === "success") {
console.log(message.result);
} else {
console.log(`Stopped: ${message.subtype}`);
}
}
}
การดำเนินการ Tool
Tools ให้ agent ของคุณสามารถดำเนินการได้ หากไม่มี tools, Claude จะตอบด้วยข้อความเท่านั้น
Tools ในตัว
SDK มี tools เดียวกับที่ขับเคลื่อน Claude Code:
| หมวดหมู่ | Tools | ฟังก์ชัน |
|---|---|---|
| การดำเนินการไฟล์ | Read, Edit, Write | อ่าน แก้ไข และสร้างไฟล์ |
| การค้นหา | Glob, Grep | ค้นหาไฟล์ตามรูปแบบ ค้นหาเนื้อหาด้วย regex |
| การดำเนินการ | Bash | รัน shell commands, scripts, git operations |
| เว็บ | WebSearch, WebFetch | ค้นหาเว็บ ดึงและแยกวิเคราะห์หน้าเว็บ |
| การค้นพบ | ToolSearch | ค้นหาและโหลด tools ตามต้องการ |
| การประสานงาน | Agent, Skill, AskUserQuestion, TaskCreate, TaskUpdate | Spawn subagents, เรียกใช้ skills, ถามผู้ใช้ |
สิทธิ์การใช้งาน Tool
Claude กำหนดว่าจะเรียก tools ใด แต่คุณควบคุมว่า calls เหล่านั้นจะได้รับอนุญาตให้รันหรือไม่:
allowed_tools/allowedToolsอนุมัติอัตโนมัติสำหรับ tools ที่ระบุdisallowed_tools/disallowedToolsบล็อก tools ที่ระบุ ไม่ว่าการตั้งค่าอื่นจะเป็นอย่างไรpermission_mode/permissionModeควบคุมสิ่งที่เกิดขึ้นกับ tools ที่ไม่ได้ครอบคลุมโดย allow หรือ deny rules
ควบคุมวิธีการรัน Loop
Turns และงบประมาณ
| ตัวเลือก | ควบคุม | ค่าเริ่มต้น |
|---|---|---|
Max turns (max_turns / maxTurns) | จำนวน tool-use round trips สูงสุด | ไม่จำกัด |
Max budget (max_budget_usd / maxBudgetUsd) | ต้นทุนสูงสุดก่อนหยุด | ไม่จำกัด |
ระดับ Effort
ตัวเลือก effort ควบคุมว่า Claude ใช้การให้เหตุผลมากน้อยเพียงใด:
| ระดับ | พฤติกรรม | เหมาะสำหรับ |
|---|---|---|
"low" | การให้เหตุผลขั้นต่ำ การตอบสนองเร็ว | การค้นหาไฟล์ การแสดงรายการไดเรกทอรี |
"medium" | การให้เหตุผลที่สมดุล | การแก้ไขทั่วไป งานมาตรฐาน |
"high" | การวิเคราะห์อย่างละเอียด | การ refactor การ debugging |
"xhigh" | ความลึกในการให้เหตุผลที่ขยาย | งานเขียนโค้ดและ agentic |
"max" | ความลึกในการให้เหตุผลสูงสุด | ปัญหาหลายขั้นตอนที่ต้องการการวิเคราะห์เชิงลึก |
Permission Mode
| Mode | พฤติกรรม |
|---|---|
"default" | Tools ที่ไม่ได้ครอบคลุมโดย allow rules จะเรียก approval callback ของคุณ |
"acceptEdits" | อนุมัติการแก้ไขไฟล์และคำสั่ง filesystem ทั่วไปโดยอัตโนมัติ |
"plan" | Claude สำรวจและวางแผนโดยไม่แก้ไขไฟล์ source ของคุณ |
"dontAsk" | ไม่มีการแจ้งเตือน Tools ที่ได้รับการอนุมัติล่วงหน้าโดย rules รัน ส่วนที่เหลือถูกปฏิเสธ |
"auto" (TypeScript เท่านั้น) | ใช้ model classifier เพื่ออนุมัติหรือปฏิเสธแต่ละ tool call |
"bypassPermissions" | รัน tools ที่ได้รับอนุญาตทั้งหมดโดยไม่ถาม |
Context Window
Context window คือข้อมูลทั้งหมดที่ใช้ได้สำหรับ Claude ระหว่าง session มันจะไม่รีเซ็ตระหว่าง turns ภายใน session ทุกอย่างสะสม: system prompt, tool definitions, ประวัติการสนทนา, tool inputs และ tool outputs
การบีบอัดอัตโนมัติ
เมื่อ context window ใกล้ถึงขีดจำกัด SDK จะบีบอัดการสนทนาโดยอัตโนมัติ: สรุปประวัติเก่าเพื่อเพิ่มพื้นที่ และรักษาการแลกเปลี่ยนล่าสุดและการตัดสินใจสำคัญไว้
คุณสามารถปรับแต่งพฤติกรรมการบีบอัดได้หลายวิธี:
- คำแนะนำการสรุปใน CLAUDE.md: ผู้บีบอัดจะอ่าน CLAUDE.md ของคุณเหมือนกับ context อื่นๆ
PreCompacthook: รันตรรกะแบบกำหนดเองก่อนการบีบอัด เช่น การเก็บถาวร transcript เต็ม- การบีบอัดด้วยตนเอง: ส่ง
/compactเป็น prompt string เพื่อเรียกการบีบอัดตามต้องการ
Sessions และความต่อเนื่อง
แต่ละการโต้ตอบกับ SDK จะสร้างหรือดำเนินต่อ session จับ session ID จาก ResultMessage.session_id เพื่อ resume ในภายหลัง
เมื่อคุณ resume ประวัติบริบทเต็มรูปแบบจาก turns ก่อนหน้าจะถูกกู้คืน: ไฟล์ที่ถูกอ่าน การวิเคราะห์ที่ดำเนินการ และการกระทำที่เกิดขึ้น
ดู Session management สำหรับคำแนะนำเต็มรูปแบบเกี่ยวกับรูปแบบ resume, continue และ fork
จัดการผลลัพธ์
เมื่อ loop สิ้นสุด ResultMessage จะบอกคุณว่าเกิดอะไรขึ้นและให้ output:
| Result subtype | สิ่งที่เกิดขึ้น | field result พร้อมใช้งาน? |
|---|---|---|
success | Claude เสร็จสิ้นงานตามปกติ | ใช่ |
error_max_turns | ถึงขีดจำกัด maxTurns ก่อนเสร็จสิ้น | ไม่ |
error_max_budget_usd | ถึงขีดจำกัด maxBudgetUsd ก่อนเสร็จสิ้น | ไม่ |
error_during_execution | ข้อผิดพลาดทำให้ loop หยุดชะงัก | ไม่ |
error_max_structured_output_retries | ไม่มี structured output ที่ถูกต้องภายในขีดจำกัด retry | ไม่ |
ตัวอย่างแบบครบถ้วน
ตัวอย่างนี้รวมแนวคิดหลักจากหน้านี้เป็น agent เดียวที่แก้ไขการทดสอบที่ล้มเหลว:
import asyncio
from claude_agent_sdk import query, ClaudeAgentOptions, ResultMessage
async def run_agent():
session_id = None
async for message in query(
prompt="Find and fix the bug causing test failures in the auth module",
options=ClaudeAgentOptions(
allowed_tools=["Read", "Edit", "Bash", "Glob", "Grep"],
setting_sources=["project"],
max_turns=30,
effort="high",
),
):
if isinstance(message, ResultMessage):
session_id = message.session_id
if message.subtype == "success":
print(f"Done: {message.result}")
elif message.subtype == "error_max_turns":
print(f"Hit turn limit. Resume session {session_id} to continue.")
elif message.subtype == "error_max_budget_usd":
print("Hit budget limit.")
else:
print(f"Stopped: {message.subtype}")
if message.total_cost_usd is not None:
print(f"Cost: ${message.total_cost_usd:.4f}")
asyncio.run(run_agent())
import { query } from "@anthropic-ai/claude-agent-sdk";
let sessionId: string | undefined;
for await (const message of query({
prompt: "Find and fix the bug causing test failures in the auth module",
options: {
allowedTools: ["Read", "Edit", "Bash", "Glob", "Grep"],
settingSources: ["project"],
maxTurns: 30,
effort: "high"
}
})) {
if (message.type === "system" && message.subtype === "init") {
sessionId = message.session_id;
}
if (message.type === "result") {
if (message.subtype === "success") {
console.log(`Done: ${message.result}`);
} else if (message.subtype === "error_max_turns") {
console.log(`Hit turn limit. Resume session ${sessionId} to continue.`);
} else if (message.subtype === "error_max_budget_usd") {
console.log("Hit budget limit.");
} else {
console.log(`Stopped: ${message.subtype}`);
}
console.log(`Cost: $${message.total_cost_usd.toFixed(4)}`);
}
}
ขั้นตอนถัดไป
- ยังไม่ได้รัน agent? เริ่มต้นด้วย quickstart เพื่อติดตั้ง SDK และดูตัวอย่างแบบครบถ้วน
- พร้อม hook เข้ากับโปรเจกต์? โหลด CLAUDE.md, skills และ filesystem hooks เพื่อให้ agent ปฏิบัติตามแบบแผนโปรเจกต์ของคุณ
- สร้าง interactive UI? เปิดใช้งาน streaming เพื่อแสดงข้อความแบบ live และ tool calls ขณะที่ loop รัน
- ต้องการการควบคุมที่เข้มงวดขึ้น? ล็อค tool access ด้วย permissions และใช้ hooks เพื่อตรวจสอบ บล็อก หรือแปลง tool calls