เลือกวิธีรัน
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 |