90% ของโค้ดที่ Anthropic ถูกเขียนโดย Claude agents ไม่ใช่โดยวิศวกรที่พิมพ์ในหน้าต่างแชท แต่โดย agents อัตโนมัติที่ทำงานเป็นลูป เรียกใช้เครื่องมือ และส่งโค้ดในขณะที่ทีมงานหลับ
ติดตาม Substack ของฉันเพื่อรับ AI alpha ใหม่ๆ:
นี่คือการตั้งค่าที่แน่นอน ทีละขั้นตอน ตั้งแต่การเรียก API ครั้งแรกจนถึง agent ที่ทำงานได้จริง ซึ่งคุณสามารถชี้ไปที่งานใดก็ได้
บทความนี้จะครอบคลุม:
1 - เหตุที่ "agents" ส่วนใหญ่ที่คนสร้างขึ้นไม่ใช่ agents จริง
2 - 5 ส่วนประกอบที่ agent ทุกตัวต้องมี
3 - วิธีสร้างแต่ละส่วนด้วย Claude พร้อมโค้ด
4 - ข้อผิดพลาดที่ทำให้ agents ตายก่อนที่จะถูกใช้งานจริง
บุ๊กมาร์กไว้เลย โค้ดบล็อกทุกอันด้านล่างใช้งานได้
01. "AI agents" ส่วนใหญ่ไม่ใช่ agents
ฉันสร้างและพัง agents มาหมดแล้วนับไม่ถ้วน เคยเห็นพวกมันเผาโทเคนทั้งคืนและไม่产出อะไรเลย เคยเห็นพวกมันเขียนไฟล์เดิมซ้ำ 30 ครั้ง เคยเห็นพวกมันผ่านการทดสอบของตัวเองด้วยการลบการทดสอบทิ้ง

ทุกความล้มเหลวสอนบทเรียนเดียวกันให้ฉัน: โมเดลไม่ใช่ปัญหา สถาปัตยกรรมรอบๆ ตัวมันต่างหากที่ผิด คู่มือนี้คือทุกสิ่งที่ฉันได้เรียนรู้ บีบอัดให้สั้นที่สุดเท่าที่จะให้คุณได้
นี่คือสิ่งที่คนส่วนใหญ่สร้างเมื่อพวกเขาพูดว่า "AI agent":
1while True:2 user_input = input("> ")3 response = call_claude(user_input)4 print(response)
นั่นคือแชทบอท มันรอคุณ มันทำตามที่คุณบอก มันลืมทุกอย่างระหว่างเซสชัน เมื่อคุณปิดแท็บ มันก็หยุดทำงาน
agent คือระบบที่ทำงานไปสู่เป้าหมายโดยที่คุณไม่ต้องนั่งอยู่หน้าจอ มันค้นพบสิ่งที่ต้องทำ วางแผน ดำเนินการ ตรวจสอบผลลัพธ์ และถ้ายังไม่เสร็จ - ก็ลองอีกครั้ง คุณกำหนดทิศทาง agent ทำหน้าที่
"Claude Code ไปจากศูนย์ถึงรายได้ 400 ล้านดอลลาร์ในเวลาไม่กี่เดือน มันเริ่มต้นจากโปรเจกต์แฮกกาธอน และยังคงใช้แค่ API สาธารณะเท่านั้น" -
Boris Cherny, หัวหน้า Claude Code
API เดียวกันกับที่คุณมีอยู่ในตอนนี้ โมเดลเดียวกัน ความแตกต่างอยู่ที่สถาปัตยกรรมรอบๆ โมเดล

02. 5 ส่วนประกอบของ agent ที่แท้จริง
ทุก agent ที่ทำงานได้จริง - Claude Code, Devin, Codex, หรืออะไรก็ตามที่คุณสร้างเอง - ประกอบขึ้นจากห้าส่วน ขาดหนึ่งส่วนก็พัง

03. ชั้น API
ทุกอย่างเริ่มต้นที่นี่ คุณเรียก Claude, Claude ตอบกลับ แต่วิธีที่คุณเรียกจะเป็นตัวกำหนดว่าคุณจะได้แชทบอทหรือ agent

สามสิ่งที่สำคัญ: system prompt, structured output, และ temperature
System prompt ไม่ใช่การทักทาย มันคือคู่มือการทำงานของ agent ของคุณ กฎ ข้อจำกัด และพฤติกรรมทุกอย่างต้องอยู่ที่นี่ หากไม่มีมัน Claude จะเดาว่าคุณต้องการอะไร หากมีมัน Claude จะทำตามข้อกำหนดของคุณ
1import anthropic23client = anthropic.Anthropic()45response = client.messages.create(6 model="claude-sonnet-4-6",7 max_tokens=4096,8 system="""คุณคือ agent ที่ตรวจสอบโค้ด910กฎ:11- อ่าน diff ทั้งหมดก่อนแสดงความคิดเห็น12- แจ้งเฉพาะบั๊กจริง ไม่ใช่ความชอบด้านสไตล์13- หากไม่มีอะไรผิด ให้พูดว่า "LGTM" แล้วหยุด14- อย่าเสนอการเปลี่ยนแปลงที่คุณยังไม่ได้ทดสอบในใจ15- รูปแบบผลลัพธ์: JSON array ของ {file, line, issue, fix}""",16 messages=[{"role": "user", "content": diff_content}]17)
Structured output ทำให้การตอบกลับของ agent อ่านได้ด้วยเครื่อง ถ้า Claude ส่งข้อความอิสระ โค้ดของคุณต้องแยกวิเคราะห์มัน ถ้า Claude ส่ง JSON โค้ดของคุณสามารถใช้ได้โดยตรง
1# บังคับให้ส่ง JSON โดยบอก Claude ถึงรูปร่างที่แน่นอน2system = """คืนค่าเฉพาะ JSON ที่ถูกต้องเท่านั้น ไม่มี markdown ไม่มีคำอธิบาย3Schema:4{5 "status": "pass" | "fail",6 "issues": [{"file": str, "line": int, "issue": str}],7 "summary": str8}"""
Temperature. ตั้งเป็น 0 สำหรับ agents ที่ต้องทำงานแน่นอน ตั้งเป็น 0.3-0.5 สำหรับงานสร้างสรรค์ ค่าเริ่มต้น (1.0) จะเพิ่มความสุ่มที่คุณแทบไม่ต้องการใน agent
04. เครื่องมือ
โมเดลที่ไม่มีเครื่องมือสามารถคิดได้แต่ไม่สามารถลงมือทำได้ มันสามารถบอกคุณได้ว่าควรแก้ไขไฟล์ไหน แต่ไม่สามารถแก้ไขได้ มันสามารถอธิบาย query ได้แต่ไม่สามารถรันได้

เครื่องมือใช้ของ Claude ช่วยให้คุณกำหนดฟังก์ชันที่โมเดลสามารถเรียกใช้ได้ คุณอธิบายฟังก์ชัน Claude ตัดสินใจว่าจะเรียกเมื่อไหร่ คุณดำเนินการและส่งคืนผลลัพธ์ Claude ใช้ผลลัพธ์เพื่อคิดต่อ
1tools = [{2 "name": "run_sql",3 "description": "รัน SQL query แบบอ่านอย่างเดียวกับฐานข้อมูล",4 "input_schema": {5 "type": "object",6 "properties": {7 "query": {8 "type": "string",9 "description": "SQL SELECT query ที่จะรัน"10 }11 },12 "required": ["query"]13 }14},15{16 "name": "write_file",17 "description": "เขียนเนื้อหาลงในไฟล์บนดิสก์",18 "input_schema": {19 "type": "object",20 "properties": {21 "path": {"type": "string"},22 "content": {"type": "string"}23 },24 "required": ["path", "content"]25 }26}]
คำอธิบายเครื่องมือมีความสำคัญมากกว่าที่คุณคิด Claude อ่านมันเพื่อตัดสินใจว่าเมื่อไหร่และอย่างไรในการใช้เครื่องมือ คำอธิบายที่คลุมเครือหมายถึงการเรียกที่ผิด คำอธิบายที่แม่นยำหมายถึงการเรียกที่ถูกต้อง
เริ่มต้นด้วยเครื่องมือ 3-5 อย่าง อ่านไฟล์ เขียนไฟล์ รันคำสั่ง ค้นหา และเครื่องมือเฉพาะโดเมนอีกหนึ่งอย่างสำหรับกรณีการใช้งานของคุณ นั่นครอบคลุม 90% ของงาน agent

05. ลูป
นี่คือส่วนที่เปลี่ยนสคริปต์ให้เป็น agent หากไม่มีลูป โค้ดของคุณจะเรียก Claude ครั้งเดียวแล้วหยุด หากมีลูป โค้ดของคุณจะเรียก Claude ตรวจสอบผลลัพธ์ และเรียกอีกครั้งจนกว่างานจะเสร็จ

สามองค์ประกอบ:
- ตัวตรวจสอบ (Verifier) สิ่งที่ตรวจสอบว่าผลลัพธ์ดีหรือไม่ ชุดทดสอบ, ตัวตรวจสอบชนิด, linter, การเรียก Claude ครั้งที่สองพร้อมเกณฑ์ที่เข้มงวด หากไม่มีสิ่งนี้ agent จะเห็นด้วยกับตัวเองซ้ำไปซ้ำมา
- สถานะ (State) บันทึกสิ่งที่เกิดขึ้น อะไรใช้ได้ อะไรล้มเหลว อะไรควรลองต่อไป หากไม่มีสถานะ agent จะทำผิดพลาดซ้ำเดิมในทุกการวนซ้ำ
- เงื่อนไขหยุด (Stop condition) บรรลุเป้าหมาย หรือถึงขีดจำกัดที่กำหนดไว้ "หลังจาก N ครั้ง ให้หยุดและรายงาน" หากไม่มีเงื่อนไขนี้ ลูปจะทำงานตลอดไปและทำให้บัญชีของคุณหมด
1import json2from pathlib import Path34def run_agent(task: str, max_attempts: int = 5):5 state = {"task": task, "attempts": [], "done": False}67 for i in range(max_attempts):8 # Build context from state9 context = build_prompt(state)1011 # Call Claude with tools12 result = call_claude(context, tools)1314 # Execute any tool calls15 output = execute_tools(result)1617 # Verify the result18 check = verify(output)1920 # Update state21 state["attempts"].append({22 "attempt": i + 1,23 "action": result.summary,24 "passed": check.passed,25 "reason": check.reason26 })2728 if check.passed:29 state["done"] = True30 break3132 # Save state for next run33 Path("state.json").write_text(json.dumps(state, indent=2))34 return state
นี่คือโครงกระดูกที่สมบูรณ์ ทุก agent ที่ใช้งานจริงคือรูปแบบที่แตกต่างกันของรูปแบบนี้ รายละเอียดเปลี่ยนไป แต่โครงสร้างไม่เปลี่ยน
06. หน่วยความจำ
หากไม่มีหน่วยความจำ ทุกเซสชันจะเริ่มจากศูนย์ agent จะค้นพบโครงสร้างโปรเจกต์ของคุณใหม่ เรียนรู้ข้อตกลงของคุณใหม่ ทำผิดพลาดซ้ำที่มันทำเมื่อวาน

Claude agents ใช้หน่วยความจำสามชั้น:
CLAUDE.md คือไฟล์ markdown ที่รากของโปรเจกต์ของคุณ Claude Code จะอ่านมันโดยอัตโนมัติเมื่อเริ่มต้นทุกเซสชัน กฎของคุณ สแต็คของคุณ ข้อตกลงของคุณ เขียนครั้งเดียว อ่านตลอดไป
1# CLAUDE.md23## โปรเจกต์4Task management API. Python 3.12, FastAPI, PostgreSQL.56## กฎ7- การตอบกลับทั้งหมด: รูปแบบ {data, error, meta}8- ต้องมีการทดสอบสำหรับทุก endpoint ใหม่9- ข้อความ commit: type(scope): description10- ห้ามใช้ print() สำหรับการบันทึก ใช้ structlog1112## ปัญหาที่ทราบ13- Auth middleware คาดหวัง x-auth-token, ไม่ใช่ Authorization14- ชุดทดสอบใช้เวลา 45 วินาทีเต็ม ใช้ --filter สำหรับการวนซ้ำ
ทักษะ (Skills) จับภาพเวิร์กโฟลว์ทั้งหมด ไม่ใช่แค่ prompts - รูปร่างที่สมบูรณ์: รูปแบบอินพุต, ขั้นตอน, รูปแบบเอาต์พุต, กฎการตรวจสอบ ครั้งแรกใช้เวลา 20 นาที การเล่นซ้ำใช้เวลา 30 วินาที
ไฟล์เรียนรู้ (Learnings file) คือบันทึกข้อผิดพลาดที่เกิดขึ้นต่อเนื่อง agent เขียนลงไปหลังทุกเซสชัน เซสชันถัดไปอ่านมัน ข้อผิดพลาดจะเกิดขึ้นซ้ำจนกว่าจะถูกเขียนลงไป จากนั้นมันก็หยุด
1# learnings.md23- Payment API คาดหวัง idempotency key ใน header, ไม่ใช่ body4- PostgreSQL NOTIFY ต้องการ LISTEN ที่ชัดเจนใน connection pool5- Rate limiter นับต่อ key, ไม่ใช่ต่อ IP การทดสอบต้องใช้ keys ที่ไม่ซ้ำ
07. ประตูตรวจสอบ (Verification gate)
ประตูตรวจสอบเป็นส่วนที่สร้างยากที่สุดและง่ายที่สุดที่จะข้าม คนส่วนใหญ่ข้ามมัน นั่นคือเหตุผลที่ agents ส่วนใหญ่พังใน production

ประตูตรวจสอบคือสิ่งที่ตรวจสอบงานของ agent โดยที่ agent ไม่ได้ให้คะแนนตัวเอง โมเดลที่เขียนโค้ดจะใจดีเกินไปเมื่อตรวจสอบการบ้านของตัวเอง คุณต้องมีการตรวจสอบครั้งที่สอง
สามรูปแบบที่ใช้ได้:
1. การทดสอบอัตโนมัติ agent เขียนโค้ด ชุดทดสอบรัน ถ้าการทดสอบล้มเหลว agent จะได้รับผลลัพธ์ข้อผิดพลาดและลองอีกครั้ง นี่คือวิธีการทำงานภายในของ Claude Code
1def verify(output):2 # Run the test suite3 result = subprocess.run(4 ["pytest", "tests/", "-x", "--tb=short"],5 capture_output=True, text=True6 )7 return {8 "passed": result.returncode == 0,9 "reason": result.stdout if result.returncode != 0 else "all tests pass"10 }
2. ตัวตรวจสอบชนิด / linter รัน mypy, ruff, หรือ tsc --noEmit หลังทุกการเปลี่ยนแปลง จับบั๊กทั้งหมวดหมู่โดยไม่ต้องเขียนการทดสอบแม้แต่ตัวเดียว
3. โมเดลที่สองเป็นผู้ตรวจสอบ ใช้การเรียก Claude แยกต่างหากพร้อม system prompt ที่เข้มงวดซึ่งมองหาแต่ปัญหาเท่านั้น ผู้เขียนเร็วและถูก ผู้ตรวจสอบช้าและเข้มงวด การแยกนี้คือคุณภาพส่วนใหญ่
1# Reviewer prompt - separate from the builder2reviewer_system = """คุณคือผู้ตรวจสอบโค้ดที่เข้มงวด3งานเดียวของคุณคือค้นหาปัญหา45ตรวจสอบ:6- โค้ดตรงกับ spec หรือไม่?7- มี edge cases ที่ไม่ถูกจับหรือไม่?8- การทดสอบทั้งหมดทดสอบสิ่งที่ถูกต้องหรือไม่?910หากทุกอย่างถูกต้อง ให้ตอบ: {"passed": true}11หากมีอะไรผิด ให้ตอบ: {"passed": false, "issues": [...]}1213อย่าเสนอการปรับปรุง แค่แจ้งบั๊กจริงๆ"""
ผู้เขียนเร็วและถูก ผู้ตรวจสอบช้าและเข้มงวด การแยกนี้คือคุณภาพส่วนใหญ่
08. รวมทุกอย่างเข้าด้วยกัน
นี่คือ agent ที่สมบูรณ์ที่รับ URL issue ของ GitHub, อ่าน issue, เขียนโค้ด, รันการทดสอบ, และเปิด PR ห้าส่วนทำงานร่วมกัน
1import anthropic, subprocess, json2from pathlib import Path34client = anthropic.Anthropic()5CLAUDE_MD = Path("CLAUDE.md").read_text()6LEARNINGS = Path("learnings.md").read_text()78SYSTEM = f"""คุณคือ agent ที่เขียนโค้ด9อ่าน issue เขียนการแก้ไข รันการทดสอบ1011บริบทโปรเจกต์:12{CLAUDE_MD}1314ปัญหาที่ทราบ:15{LEARNINGS}1617กฎ:18- อ่าน codebase ทั้งหมดก่อนเปลี่ยนแปลงอะไร19- เขียนการทดสอบสำหรับทุกการเปลี่ยนแปลง20- ถ้าการทดสอบล้มเหลว ให้แก้ไขโค้ด ไม่ใช่การทดสอบ21- หยุดเมื่อการทดสอบทั้งหมดผ่าน"""2223TOOLS = [24 read_file_tool,25 write_file_tool,26 run_command_tool,27 search_codebase_tool,28]2930def run(issue_text, max_attempts=5):31 messages = [{"role": "user", "content": issue_text}]3233 for attempt in range(max_attempts):34 # Call Claude35 response = client.messages.create(36 model="claude-sonnet-4-6",37 max_tokens=8192,38 system=SYSTEM,39 tools=TOOLS,40 messages=messages41 )4243 # Execute tool calls44 messages = handle_tool_use(response, messages)4546 # Verify: run tests47 test_result = subprocess.run(48 ["pytest", "-x", "--tb=short"],49 capture_output=True, text=True50 )5152 if test_result.returncode == 0:53 print(f"เสร็จใน {attempt + 1} ครั้ง")54 return True5556 # Feed failure back into the loop57 messages.append({58 "role": "user",59 "content": f"การทดสอบล้มเหลว:\n{test_result.stdout}\nแก้ไขและลองใหม่"60 })6162 return False
นั่นคือ agent ที่ทำงานได้จริง ชั้น API พร้อม system prompt และ CLAUDE.md เครื่องมือสำหรับดำเนินการกับไฟล์ ลูปพร้อมลองใหม่ หน่วยความจำจาก learnings.md ประตูตรวจสอบผ่าน pytest
ไม่ถึง 50 บรรทัด สถาปัตยกรรมเดียวกับที่ Claude Code ใช้ภายใน
**
09. 5 ข้อผิดพลาดที่ทำลาย agent ทุกตัว
- ไม่มีประตูตรวจสอบ agent ให้คะแนนการบ้านตัวเอง มันเขียนโค้ด พูดว่า "ดูดี" แล้วเดินต่อไป ผลลัพธ์ดูถูกต้องแต่พังใน production
- ไม่มีเงื่อนไขหยุด ลูปทำงานจนกว่าบิล API ของคุณจะเป็น $200 หากไม่มีขีดจำกัดตายตัว agent จะลองซ้ำไม่รู้จบ เขียนไฟล์เดิมซ้ำ 40 ครั้ง ตั้งค่า max_attempts เสมอ
- ไม่มีไฟล์สถานะ ข้อผิดพลาดเดียวกันในครั้งที่ 1 และครั้งที่ 50 agent ไม่รู้ว่ามันลองอะไรไปแล้ว มันเสนอการแก้ไขที่พังเหมือนเดิมสามครั้งติดต่อกันเพราะไม่มีอะไรบันทึกความล้มเหลว
- เครื่องมือมากเกินไป คุณให้ Claude 20 เครื่องมือและมันเลือกผิด โมเดลที่มีเครื่องมือชัดเจน 5 อย่างเลือกได้ดีกว่าโมเดลที่มี 20 อย่างที่ทับซ้อนกัน เริ่มเล็กๆ เพิ่มเครื่องมือเมื่อ agent ชนกำแพงเท่านั้น
- System prompt คลุมเครือ "เป็นผู้ช่วยเขียนโค้ดที่ดี" ให้ผลลัพธ์ทั่วๆ ไป "การตอบกลับทั้งหมดต้องเป็น JSON ที่ถูกต้อง ต้องมีการทดสอบสำหรับทุกการเปลี่ยนแปลง ห้ามแก้ไขไฟล์นอก /src" ให้ agent ที่มีพฤติกรรมชัดเจน
สรุป:
agent ที่ทำงานได้จริงไม่ใช่ prompt ที่ดีกว่า แต่เป็นระบบ: API + เครื่องมือ + ลูป + หน่วยความจำ + ประตูตรวจสอบ ห้าส่วน ขาดหนึ่งส่วนก็พัง
คนส่วนใหญ่จะอ่านสิ่งนี้ บุ๊กมาร์กไว้ และใช้ Claude เป็นแชทบอทต่อไป พวกเขาจะวางคำถามทีละคำถามและคัดลอกคำตอบลงใน codebase ด้วยมือ
คนที่สร้างลูปจะส่งงานในขณะที่พวกเขาหลับ โมเดลเดียวกัน API เดียวกัน ราคาเดียวกัน สถาปัตยกรรมต่างกัน
โค้ดบล็อกทั้งหมดด้านบนใช้งานได้ คัดลอกไป รันมัน ปรับเปลี่ยนสำหรับกรณีการใช้งานของคุณ
สร้าง agent หนึ่งตัวในสัปดาห์นี้ ชี้ไปที่งานที่คุณทำทุกวัน ปล่อยให้มันทำงาน





