Knowledge Hub

วิธีใช้งาน AgentLoop

ขั้นตอนตั้งแต่เตรียมเครื่อง รัน worker ส่งงาน ตรวจผล จนถึงให้ agent แก้ repo จริงบน branch แยก พร้อมคำสั่งที่คัดลอกไปรันได้

AgentLoopอ่าน 12 นาทีเผยแพร่ 14 ตุลาคม 2569

เลือกวิธีรัน

AgentLoop รับงานเป็นไฟล์ JSON เรียกว่า spec (goal, checks, เงื่อนไขหยุด) แล้ววนทำจนตรวจผ่านหรือถึงเงื่อนไขหยุด มี 3 วิธีใช้

วิธี ใช้เมื่อ งานไปอยู่ที่ไหน
รัน spec เดียว ลองของ ทดสอบ spec ใหม่ sandbox\<id>\workspace
Worker 24 ชั่วโมง ส่งงานต่อเนื่อง ปล่อยทิ้งไว้ได้ <root>\sandboxes\<job_id>\workspace
โหมด repo จริง ให้ agent แก้โค้ดใน git repo ของคุณ worktree + branch agentloop/<job_id>

โหมด repo จริงใช้ผ่าน worker เท่านั้น (spec ที่มี repo ส่งเข้า inbox ได้ตามปกติ)

เตรียมเครื่อง

ต้องมี ตรวจอย่างไร
Python 3.14 ที่ C:\Python314\python.exe C:\Python314\python.exe --version
Claude CLI ที่ login แล้ว (ใช้ session ที่ login ไม่ใช้ API key) claude --version
โฟลเดอร์ D:\MY\AI_POC\01_POC_PythonCallClaudeCLI (มี claude_cli.py) ถ้าย้ายที่ ตั้ง env CLAUDE_CLI_DIR
git (เฉพาะโหมด repo จริง) git --version

Note AgentLoop ตัด ANTHROPIC_API_KEY ที่ใช้ไม่ได้ออกให้เอง ถ้าอยากใช้ API key จริงให้ใส่ --use-api-key

ทุกคำสั่งรันจากโฟลเดอร์โปรเจกต์ และตั้ง UTF-8 ก่อน (กัน console ภาษาไทยพัง)

cd D:\MY\AI_POC\AgentLoop
$env:PYTHONIOENCODING = 'utf-8'

วิธีที่ 1 รัน spec เดียว

ใช้ spec ตัวอย่างที่มีอยู่แล้วใน goals\

python -m agent_loop goals\slugify.json
python -m agent_loop goals\slugify.json --sandbox D:\temp\sb --model claude-sonnet-5-5
python -m agent_loop goals\discount_ask.json --no-advisor
Option ความหมาย
--sandbox <dir> โฟลเดอร์ทำงาน (ค่าเริ่มต้น sandbox\<id>)
--model <name> เปลี่ยนโมเดลที่ลงมือแก้
--no-advisor ไม่ปรึกษา Opus เมื่อ agent ถามคน ถ้าถามจะหยุดแทน
--use-api-key ใช้ ANTHROPIC_API_KEY แทน session ที่ login

จบแล้วพิมพ์ summary เป็น JSON (outcome, rounds, llm_calls, message) คืนค่า exit 0 เมื่อ outcome เป็น PASSED

หยุดกลางทาง: สร้างไฟล์ชื่อ STOP ในโฟลเดอร์ sandbox

วิธีที่ 2 Worker 24 ชั่วโมง

Worker เฝ้า inbox\ เก็บงานลง SQLite รันทีละ job และเก็บ checkpoint ทุกรอบ จึงหยุดแล้วทำต่อได้

เลือก root

Root คือโฟลเดอร์เก็บทุกอย่างของ worker (ฐานข้อมูล ผลลัพธ์ log) ในตัวอย่างใช้ D:\MY\AI_POC\AgentLoopData ให้อยู่นอกโฟลเดอร์โปรเจกต์ เพราะ sandbox\ ของโปรเจกต์ถูก gitignore ไว้เฉพาะงานทดลอง

เริ่ม worker

# แบบธรรมดา (หน้าต่างนี้ค้างไว้)
python -m agent_loop.worker --root D:\MY\AI_POC\AgentLoopData

# แบบมีตัวเฝ้า restart เองเมื่อ crash (แนะนำสำหรับรันยาว)
powershell -File D:\MY\AI_POC\AgentLoop\run_worker.ps1 -Root D:\MY\AI_POC\AgentLoopData -DailyCap 300
Option ของ worker ความหมาย
--daily-cap N เพดานจำนวนครั้งเรียก LLM ต่อวัน (ตรวจระหว่าง job)
--poll S ตรวจ inbox ทุกกี่วินาที (ค่าเริ่มต้น 15)
--no-advisor ปิดการปรึกษา Opus
--stop-when-idle จบเมื่อ inbox ว่าง (ใช้ตอนทดสอบ)
--status พิมพ์ status.json แล้วออก

ตัวเฝ้า run_worker.ps1 รัน worker ซ้ำเมื่อ crash แต่หยุดเมื่อ worker จบปกติหรือมีคนต้องดู และเลิกเองถ้า crash ถี่เกินกำหนด (5 ครั้งใน 10 นาที)

ส่งงาน

มี 2 ทาง ผลเหมือนกัน

# ทาง A: วางไฟล์ลง inbox (worker หยิบเองภายใน --poll วินาที)
Copy-Item goals\slugify.json D:\MY\AI_POC\AgentLoopData\inbox\

# ทาง B: ส่งผ่าน CLI
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData submit goals\slugify.json

Note seed_dir ใน spec ที่เป็น path สัมพัทธ์ จะอ้างจากโฟลเดอร์ของไฟล์ spec ตอนส่งผ่านทาง B และจากโฟลเดอร์ inbox ตอนวางไฟล์ทาง A ถ้ามี seed ให้เขียน path เต็มใน spec

Note คำสั่ง jobctl อื่นนอกจาก submit ต้องมีฐานข้อมูลอยู่แล้ว (<root>\state\agentloop.db) ถ้า --root ผิดจะแจ้ง error แทนการสร้างฐานข้อมูลเปล่า

ดูสถานะ

python -m agent_loop.worker --root D:\MY\AI_POC\AgentLoopData --status
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData list
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData list --status held --limit 10
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData show <job_id>

สถานะของ job ที่ list แสดง

สถานะ ความหมาย
queued รอคิว
running กำลังรัน
held ถูกพักไว้ รอ resume
done ตรวจผ่าน
failed ล้มเหลว (ดู result.outcome และ message)
needs_human ต้องให้คนตัดสินใจ
cancelled ยกเลิกแล้ว

ผลลัพธ์

ที่ มีอะไร
<root>\done\, failed\, needs_human\ ไฟล์ <job_id>.result.json ของแต่ละ job
<root>\sandboxes\<job_id>\workspace\ ไฟล์ที่ agent ทำ
<root>\sandboxes\<job_id>\runs\ log รายรอบ
<root>\lessons.md บทเรียนที่ agent จดไว้ใช้ในงานถัดไป
<root>\state\events.log เหตุการณ์ของ worker (เริ่ม หยุด LLM ล่ม งานจบ)
<root>\state\crash.log traceback เมื่อ worker crash
<root>\state\status.json สถานะปัจจุบันของ worker

พัก ทำต่อ ยกเลิก

python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData hold   <job_id> --reason "รอตรวจ"
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData resume <job_id>
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData cancel <job_id>
  • hold ตอน job กำลังรัน จะหยุดที่ขอบรอบถัดไป (LLM call หรือ check ที่ค้างอยู่ทำให้จบก่อน) แล้วเก็บ workspace กับ checkpoint ไว้
  • resume ทำต่อจากรอบสุดท้ายที่เสร็จ แม้ restart worker หรือเครื่องไปแล้ว
  • cancel ใช้ได้กับ job ที่ queued หรือ held เท่านั้น ถ้ากำลังรันให้ hold ก่อน

หยุด worker

ต้องการ ทำอย่างไร
หยุดทั้ง worker (kill switch) สร้างไฟล์ D:\MY\AI_POC\AgentLoopData\STOP
หยุดเฉพาะ job เดียว สร้างไฟล์ STOP ใน <root>\sandboxes\<job_id>\
ทำต่อหลังหยุดทั้ง worker ลบไฟล์ STOP แล้วเริ่ม worker ใหม่
New-Item -ItemType File D:\MY\AI_POC\AgentLoopData\STOP

เขียน spec

Spec คือไฟล์ JSON ที่มนุษย์เป็นคนเขียน โมเดลแก้ spec ไม่ได้ checks ก็กำหนดโดยคน agent ตัดสินผลตัวเองไม่ได้

ฟิลด์ จำเป็น ความหมาย
id ใช่ ชื่อ goal
goal ใช่ งานที่ต้องการ เขียนให้วัดผลได้
constraints ไม่ ข้อห้ามและข้อบังคับ (list ของข้อความ)
checks ใช่ เกณฑ์ตรวจผลจากภายนอก ดูตารางถัดไป
seed_dir ไม่ โฟลเดอร์ไฟล์เริ่มต้น คัดลอกเข้า workspace และเป็น read-only ทุกไฟล์
repo ไม่ โหมด repo จริง ใช้แทน seed_dir (ใส่คู่กันไม่ได้)
stop ไม่ เงื่อนไขหยุด

ชนิดของ check

type ฟิลด์ ผ่านเมื่อ
file_exists path มีไฟล์นั้น
file_contains path, text ไฟล์มีข้อความนั้น
json_valid path ไฟล์เป็น JSON ถูกต้อง
command argv, timeout, stdout_contains, cwd คำสั่ง exit 0 (และ stdout มีข้อความที่ระบุ ถ้าใส่)

python ตัวแรกใน argv จะถูกแทนด้วย Python ตัวที่รัน worker

เงื่อนไขหยุด (stop)

ฟิลด์ ค่าเริ่มต้น เพดานที่ worker ยอมให้
max_rounds 10 20
max_seconds 900 3600
max_llm_calls 15 40
max_advisor_calls 2 5
max_verify_fail_streak 3 ไม่มีเพดาน

ถ้า spec ขอเกินเพดาน worker ลดให้และบันทึก SPEC_CLAMPED ใน events.log

ตัวอย่าง spec แบบ seed (สร้างไฟล์ใหม่)

{
  "id": "slugify",
  "goal": "Create slugify.py exposing slugify(text: str) -> str that turns a title into a URL slug. All tests in test_slugify.py must pass.",
  "constraints": ["Python standard library only", "Do not modify test_slugify.py", "Write only slugify.py"],
  "seed_dir": "D:/MY/AI_POC/AgentLoop/goals/slugify_seed",
  "checks": [
    { "name": "slugify.py exists", "type": "file_exists", "path": "slugify.py" },
    { "name": "unit tests pass",   "type": "command", "argv": ["python", "-m", "unittest", "-q"], "timeout": 60 }
  ],
  "stop": { "max_rounds": 10, "max_seconds": 900, "max_llm_calls": 15 }
}

โหมด repo จริง

Agent แก้โค้ดใน git repo ของคุณโดยไม่แตะ checkout ที่คุณใช้อยู่ ทำงานใน worktree แยก บน branch agentloop/<job_id> เมื่อ checks ผ่านจะ commit ลง branch นั้น ไม่ merge ไม่ push คุณตรวจแล้ว merge เอง

ขั้นที่ 1 เขียน spec

{
  "id": "fix-discount",
  "goal": "apply_discount in pricing/discount.py returns the discount amount instead of the price after the discount, and does not validate percent. Fix it so every test in tests/test_discount.py passes. Do not change any other behavior.",
  "constraints": ["Python standard library only", "Do not modify tests", "Change only pricing/discount.py"],
  "repo": {
    "path": "D:/MY/shop",
    "writable": ["pricing/**"],
    "protected": ["tests/**"],
    "context": ["pricing/**", "tests/**"],
    "setup": [],
    "max_files_changed": 20,
    "commit_message": "แก้ไข \"การคำนวณราคาหลังหักส่วนลด\""
  },
  "checks": [
    { "name": "unit tests pass", "type": "command", "argv": ["python", "-m", "unittest", "discover", "-s", "tests", "-q"], "timeout": 60 }
  ],
  "stop": { "max_rounds": 8, "max_seconds": 900, "max_llm_calls": 10 }
}
ฟิลด์ใน repo ความหมาย
path repo ต้นทาง (ต้องเป็น git repo)
writable glob ที่ agent เขียนได้ บังคับใส่ ไม่ใส่หรือเว้นว่างจะ error
protected ไฟล์ที่ใช้ตัดสิน agent เช่น tests agent อ่านได้แต่แก้ไม่ได้
context ไฟล์ที่แสดงให้ agent เห็นเต็มทุกรอบ
base_ref จุดเริ่ม (ค่าเริ่มต้น HEAD) แก้ไขอยู่จาก commit นี้ ไม่ใช่งานที่ยังไม่ commit
setup list ของ argv รันครั้งเดียวใน worktree ใหม่ เช่น [["npm","ci"]]
setup_timeout วินาทีต่อคำสั่ง setup (ค่าเริ่มต้น 900 เพดาน 1800)
max_files_changed เกินจำนวนนี้จะไม่ commit และส่งให้คน (ค่าเริ่มต้น 20 เพดาน 50)
commit_message ว่างได้ ค่าเริ่มต้นคือ แก้ไข "<id>"

Glob เขียนแบบ .gitignore: ไม่มี / จะตรงทุกความลึก ลงท้าย / คือโฟลเดอร์ บน Windows ไม่สนตัวพิมพ์เล็กใหญ่

Important ไฟล์เหล่านี้ agent อ่านและเขียนไม่ได้ ไม่ว่า spec เขียนอย่างไร: .git, .env*, *.pem, *.key, *.pfx, id_rsa*, .ssh/, .aws/, .claude/, .npmrc, .netrc และไฟล์ credential ทำนองเดียวกัน โฟลเดอร์ node_modules, bin, obj, dist, build, .venv, __pycache__, .next อ่านได้แต่เขียนไม่ได้

ขั้นที่ 2 ส่งงานและรอ

python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData submit D:\MY\specs\fix-discount.json
python -m agent_loop.worker --root D:\MY\AI_POC\AgentLoopData --stop-when-idle   # หรือใช้ worker ที่รันอยู่แล้ว
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData list

ขั้นที่ 3 ตรวจสิ่งที่ agent แก้

python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData diff <job_id>          # สรุปไฟล์ที่เปลี่ยน
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData diff <job_id> --full   # patch เต็ม

diff แสดง branch, commit บน branch, ไฟล์ที่ยังไม่ commit และ diff เทียบกับ commit เริ่มต้น

ขั้นที่ 4 เก็บหรือทิ้ง

# เก็บ: merge เองจาก repo ของคุณ
cd D:\MY\shop
git log agentloop/<job_id>
git merge agentloop/<job_id>

# ทิ้ง: ลบ worktree กับ branch ของ job นั้น (ใช้ได้กับ job ที่จบแล้ว ต้องใส่ --yes)
python -m agent_loop.jobctl --root D:\MY\AI_POC\AgentLoopData discard <job_id> --yes

discard ลบเฉพาะ agentloop/<job_id> ไม่แตะ branch อื่น

ผลลัพธ์ที่เป็นไปได้ในโหมดนี้

ผล ความหมาย ทำอย่างไรต่อ
done + มี commit ตรวจผ่านและ commit แล้ว diff แล้ว merge
done ไม่มี commit ตรวจผ่านแต่ไม่มีไฟล์ใน writable เปลี่ยน ตรวจว่า goal ถูกทำไปแล้วหรือไม่
needs_human เกิน max_files_changed, hook ปฏิเสธ commit หรือ check ไปแก้ไฟล์ protected ดู message ใน result แล้วดู worktree
failed / REPO_ERROR git, worktree หรือ setup ล้ม ดู message แก้แล้วส่งใหม่

เมื่อ agent ถามสิ่งที่ตัดสินเองไม่ได้

เมื่อ agent เจอเรื่องที่ spec ไม่บอก (เช่นตัวเลขเกี่ยวกับเงิน) มันจะเขียนคำถามลง <root>\sandboxes\<job_id>\pending_questions.json ปรึกษา Opus 5.5 ใช้คำตอบนั้นเป็นข้อสันนิษฐานชั่วคราว แล้วทำต่อ

คุณตอบทีหลังได้ โดยเติม human_answer ในคำถามนั้น คำตอบของคนชนะคำตอบของ advisor ตั้งแต่รอบถัดไป

ไฟล์เป็น list ของคำถาม แต่ละข้อมีฟิลด์ question_id, asked_at, round_number, question, sensitive, status, advisor_answer, human_answer แก้เฉพาะ human_answer ของข้อที่ต้องการ

[
  {
    "question_id": 1,
    "round_number": 2,
    "question": "gold discount percent?",
    "sensitive": true,
    "status": "PENDING_HUMAN",
    "advisor_answer": "...",
    "human_answer": "gold ลด 15%"
  }
]

ใช้ได้กับ job ที่ยังรันอยู่ หรือที่ hold แล้ว resume ต่อ job ที่จบแล้วต้องส่ง spec ใหม่ที่ใส่คำตอบไว้ใน goal หรือ constraints

Warning คำตอบของ advisor เป็นแค่ข้อสันนิษฐาน เรื่องเงินและสิทธิ์ควรเข้าไปตอบเองก่อนนำผลไปใช้จริง

โครงโฟลเดอร์ของ root

AgentLoopData\
  inbox\            วางไฟล์ spec ที่นี่
  ingested\         spec ที่ worker รับเข้าฐานข้อมูลแล้ว
  done\ failed\ needs_human\    <job_id>.result.json
  sandboxes\<job_id>\           workspace, runs, pending_questions.json
  lessons.md        บทเรียน (งาน repo จริงใช้ lessons\<repo>-<hash>.md แยกตาม repo)
  state\            agentloop.db, status.json, events.log, crash.log, worker.lock
  STOP              สร้างเพื่อหยุดทั้ง worker

เมื่อมีปัญหา

อาการ สาเหตุที่เป็นไปได้ ทำอย่างไร
worker exit 2 มี worker อื่นถือ lock อยู่ รอ lock หมดอายุ (ประมาณ 2 นาทีหลัง worker เดิมตาย) หรือหยุด worker เดิม
worker exit 3 job ล้มต่อเนื่องหลายงาน worker พักให้คนตรวจ ดู state\status.json และ events.log แก้ spec แล้วเริ่มใหม่
worker exit 1 crash อ่าน state\crash.log
events.log มี LLM_DOWN เรียก Claude ไม่ได้ worker รอเองและทำต่อเมื่อกลับมา ตรวจว่า claude ยัง login อยู่
job เป็น failed + INVALID_SPEC spec ผิดรูปแบบ มี key ที่ไม่รู้จัก หรือ repo กับ seed_dir ใส่คู่กัน แก้ spec ตามข้อความใน message
job เป็น failed + REPO_ERROR ไม่ใช่ git repo, setup ล้ม หรือ git ล้มกลางงาน ดู message
discard ปฏิเสธ job ยังไม่จบ หรือลืม --yes cancel หรือรอให้จบก่อน แล้วใส่ --yes
งานไม่ถูกหยิบ ไฟล์ยังเขียนไม่เสร็จ หรือนามสกุลไม่ใช่ .json ใช้ jobctl submit แทน

ข้อจำกัดที่ต้องรู้

  • คำสั่งใน checks และ repo.setup รันบนเครื่องจริง ไม่มี sandbox ระดับ OS ใส่เฉพาะคำสั่งที่คุณยอมรับให้โค้ดที่ agent เขียนถูกรันได้
  • งานที่ยังไม่ commit ใน checkout ของคุณ agent มองไม่เห็น เพราะ worktree เริ่มจาก commit ของ base_ref
  • เครื่องมืออย่าง npm ci หรือ dotnet restore ต้องใส่ใน repo.setup เอง
  • ข้อความ commit เป็น template หรือค่าจาก commit_message ไม่ได้ให้ LLM เขียน
  • การนับจำกัดตอนนี้นับจำนวนครั้งเรียก LLM ยังไม่มีการวัดเป็นเงิน
  • การแจ้งเตือนเป็นไฟล์เท่านั้น ไม่มี Telegram หรืออีเมล
  • Phase B (benchmark, holdout, strategy evolution) ยังไม่ได้ทำ ยังไม่รับประกันว่า "ดีขึ้นเรื่อย ๆ" นอกจากบทเรียนใน lessons.md

Summary

หัวข้อ สรุป
ลองของ python -m agent_loop goals\slugify.json
รันยาว run_worker.ps1 -Root <root> แล้วส่ง spec เข้า inbox\ หรือ jobctl submit
ตรวจสถานะ worker --status, jobctl list, jobctl show <job_id>
พัก ทำต่อ jobctl hold และ jobctl resume ทำต่อจากรอบสุดท้ายที่เสร็จ
แก้ repo จริง spec ที่มี repo.writable แล้ว jobctl diff ตรวจ และ merge เอง
หยุดฉุกเฉิน สร้างไฟล์ <root>\STOP
Facebook