วงจรชีวิตการสั่งงานเอเจนต์
การสั่งงานคืออะไร
หัวข้อที่มีชื่อว่า “การสั่งงานคืออะไร”การสั่งงานคือการรันหนึ่งครั้งของเอเจนต์หนึ่งตัว ในบทสนทนาหนึ่งบท บนอะแดปเตอร์หนึ่งตัว ทุกอย่างที่เกี่ยวกับมันเกิดขึ้นบน cc_server: ไคลเอนต์ส่งข้อความแล้วเฝ้าดูเหตุการณ์ที่สตรีมกลับมา ไม่มีเส้นทางการสั่งงานอยู่ในไคลเอนต์ใดเลย
เอเจนต์ถูกปลุกด้วยเหตุผลหกประการ ซึ่งการรันจะพกติดไปเป็น บริบทการปลุก เพื่อให้เอเจนต์รู้ว่า_ทำไม_มันจึงถูกปลุกขึ้นมา:
| เหตุผลการปลุก | ตัวกระตุ้น |
|---|---|
userMessage |
มีคนส่งข้อความในสเปซ หรือกล่าวถึงเอเจนต์ |
assignment |
มีตั๋วงานถูกมอบหมายให้เอเจนต์ |
pipelineStep |
ขั้นตอนไปป์ไลน์สั่งงานมัน |
childCompleted |
ตั๋วงานลูกทำงานเสร็จ |
followUp |
ฮาร์ตบีตติดตามผลตามกำหนดเวลา |
recovery |
เส้นทางการกู้คืนสั่งงานซ้ำหลังจากเกิดความล้มเหลว |
บริบทการปลุกพา id ต่าง ๆ ที่มาพร้อมเหตุผลนั้นไปด้วย — ตั๋วงาน, สเปซ, ข้อความ, รันไปป์ไลน์ — และ id เหล่านั้นถูกฉีดเข้าไปในสภาพแวดล้อมและพรอมต์ของเอเจนต์
การประกอบพรอมต์
หัวข้อที่มีชื่อว่า “การประกอบพรอมต์”พรอมต์ถูกสร้างขึ้นเป็นชั้น ๆ โดยแต่ละชั้นเป็นส่วนที่มีป้ายกำกับ:
- ตัวตน — id, ชื่อ และ id ของเวิร์กสเปซของเอเจนต์เอง พร้อมคำสั่งชัดเจนให้ส่ง UUID เหล่านั้นแบบตรงตัวไปยังเครื่องมือที่จำกัดขอบเขตตามเวิร์กสเปซ เวิร์กสเปซเป็นส่วนที่ฝังอยู่ในตัวเอเจนต์เอง จึงมีอยู่เสมอ
- แค็ตตาล็อกเครื่องมือและโปรโตคอลทรัพยากร จากนั้นเป็น โครงร่างของเวิร์กสเปซ
- พรอมต์ระบบที่เขียนทับ หากเอเจนต์มี จากนั้นเป็น เพอร์โซนา (กำหนดพารามิเตอร์ตามบทบาท) และ บรีฟของทีม
- สกิล — ชื่อต่าง ๆ ที่ผูกอยู่กับเอเจนต์
- สัญญาการดำเนินงานและขั้นตอนปฏิบัติ สำหรับโหมดปัจจุบัน
- บริบทการปลุก และ บริบทการกล่าวถึง: ใครเป็นผู้เรียกเอเจนต์ และรายชื่อผู้เข้าร่วมที่อยู่รอบตัวมัน
- บล็อกโหมด — สร้างขึ้นจากโปรไฟล์ขีดความสามารถของโหมด และรายการเครื่องมือที่ถูกทำให้เกิดขึ้นจริง ดังนั้นพรอมต์จึงไม่มีทางระบุชื่อเครื่องมือที่การรันไม่มีอยู่จริงได้
- บริบทหน่วยความจำ — ข้อเท็จจริงที่ถูกดึงมาสำหรับงานนั้น
- บริบทการสนทนา — ประวัติสเปซล่าสุด จำกัดไว้ที่หน้าต่างข้อความแบบคำต่อคำ 50,000 ตัวอักษร โดยไม่สนใจขนาดบริบทที่กำหนดค่าไว้ของเอเจนต์ ประวัติที่เก่ากว่าจะไม่ถูกตัดทิ้ง: เอเจนต์ดึงมันมาเมื่อต้องการด้วย
get_messagesและข้อความเก่าที่เกี่ยวข้องเชิงความหมายก็ยังปรากฏขึ้นได้
คำสั่งถูกแยกจัดการในสองที่ /todo และ /compact ถูกดักจับในช่องเขียนข้อความ และจงใจไม่ถูกบันทึกเป็นข้อความหรือส่งไปยังเอเจนต์เลย — การบันทึก /compact จะทำให้จุดตัดของการย่อประวัติถอยกลับไปหนึ่งรอบและปนเปื้อนทรานสคริปต์ /plan ถูกจัดการทั้งสองที่: ช่องเขียนข้อความสลับโหมดของสเปซ ซึ่งเป็นสิ่งที่ทำให้ชุดเครื่องมือ, พรีเซ็ตของกฎคุม และพรอมต์สอดคล้องกันสำหรับรอบนี้และทุกรอบถัดไป /goal, /loop และ /skill:<name> ถูกจัดการภายในตัวการรันเอง และเฉพาะบนฮาร์เนสในตัวเท่านั้น — /goal และ /loop เริ่มงานอัตโนมัติด้วยงบประมาณต้นทุน และชื่อที่ขึ้นต้นด้วย skill: จะถูกค้นหาเป็นสกิลที่เนื้อหา SKILL.md กลายเป็นคำสั่งกำกับของรอบนั้น เนมสเปซคือสิ่งที่แยกคำศัพท์สองชุดนี้ออกจากกัน: การแก้ชื่อเปล่าเทียบกับสกิลหมายความว่าสกิลชื่อ plan หรือ compact ถูกบดบังโดยคำสั่งในตัวอย่างถาวร ชื่อเปล่าที่ไม่ใช่คำสั่งในตัวยังคงถูกแก้ได้ สำหรับข้อความที่เขียนไว้ก่อนมีเนมสเปซ ชื่อที่ไม่รู้จักก็จะถูกส่งผ่านไปเป็นข้อความธรรมดา
การจัดเตรียม worktree
หัวข้อที่มีชื่อว่า “การจัดเตรียม worktree”ก่อนที่อะไรจะเริ่มรัน บทสนทนาจะได้รูทการทำงานของตัวเอง พร้อม worktree แบบคัดลอกเมื่อเขียนที่แยกออกจากกันหนึ่งชุดต่อหนึ่งรีโปภายใต้รูทนั้น โดยค่าเริ่มต้นคือทุกรีโปที่เชื่อมกับเวิร์กสเปซ สเปซของ PR — หรือสเปซที่สร้างขึ้นพร้อมการเลือกอย่างชัดเจน — จะจัดเตรียมเฉพาะรีโปที่อยู่ในรายการที่อนุญาต และบทสนทนารีวิว PR จะตรึงรีโปของตนเพียงหนึ่งเดียวไว้ที่ head ref ของ pull request ขณะที่รีโปอื่น ๆ อยู่บนสาขาเริ่มต้นของตน เช็กเอาต์ต้นทางไม่ถูกแก้ไขเลย และไดเรกทอรีบทสนทนาทั้งหมดจะถูกเรียกคืนเมื่อสเปซถูกลบ
การคัดลอกเมื่อเขียนเป็นวิธีใช้งานเดียวในทุกที่ที่มี rift มาด้วย โดยหนุนด้วยเนทีฟที่บันเดิลมา ระบบไฟล์ที่ไม่สามารถ reflink ได้ — หรือไดเรกทอรีข้อมูลที่อยู่คนละวอลุ่มกับรีโป — จะทำให้การจัดเตรียมล้มเหลวแทนที่จะถอยไปใช้วิธีสำรอง git worktree เป็นแบ็กเอนด์บน Windows ซึ่งไม่มีแบ็กเอนด์การคัดลอกเมื่อเขียนให้สร้าง และมันไม่ใช่การลดระดับแบบเงียบ ๆ บนโฮสต์อื่น การที่ rift หายไปบนแพลตฟอร์มที่มีมันมาด้วยถือเป็นการติดตั้งที่พัง — เซิร์ฟเวอร์จะปฏิเสธการบูตแทนที่จะถอยกลับอย่างเงียบ ๆ เพราะการถอยกลับแบบเงียบจะซ่อนความเสียหายไว้เบื้องหลังเส้นทางที่ช้ากว่าตลอดไป
ตัวตนและข้อมูลรับรอง
หัวข้อที่มีชื่อว่า “ตัวตนและข้อมูลรับรอง”ตัวตนสองแบบถูกกำหนดต่อการรันหนึ่งครั้ง ก่อนที่โปรเซสใดจะเริ่มรัน
ความเป็นผู้เขียนของ Git คอมมิตที่เอเจนต์สร้างจะถูกระบุผู้เขียน เป็นตัวเอเจนต์เอง — <Name> (agent) <agentId@agents.control-center.local> ทั้งใน GIT_AUTHOR_* และ GIT_COMMITTER_* — ไม่ปลอมตัวเป็นมนุษย์เลย ส่วนหน้าเครื่องหมาย @ คือ UUID ของเอเจนต์ ไม่ใช่ slug ของชื่อมัน มนุษย์ผู้ร้องขอจะได้รับเครดิตผ่านบรรทัดท้าย Co-Authored-By: ซึ่งพกไปในสภาพแวดล้อมและสั่งกำกับไว้ในพรอมต์ระบบ ตัวตนที่ผู้เรียกระบุไว้อย่างชัดเจนจะชนะทั้งสองแบบเสมอ
ตัวตนบนโฮสต์โค้ด ข้อมูลรับรอง GitHub ของการรันเป็นของโบรกเกอร์เท่านั้นเสมอ — โทเคนการติดตั้งของ App ที่จำกัดขอบเขตตามรีโป หรือ PAT สำรองจากสภาพแวดล้อมของมัน — ไม่ใช่โทเคนที่จัดเก็บไว้ของสมาชิกผู้ร้องขอเอง actingUserId จำกัดขอบเขตของ PAT สำรอง เพื่อให้สมาชิกที่ไม่ได้เป็นเจ้าของเซิร์ฟเวอร์ไม่ได้รับช่วงการเข้าถึงของเซิร์ฟเวอร์ไปด้วย มันไม่ได้ซ้อนทับโทเคนส่วนตัวลงบนสภาพแวดล้อมของเอเจนต์
ข้อมูลรับรองของผู้ให้บริการโมเดล ถูกกำหนดตามลำดับที่แน่นอน และลำดับนั้นสำคัญ:
- การเขียนทับสภาพแวดล้อมรายอะแดปเตอร์
- สภาพแวดล้อมของผู้เรียก
- ที่เก็บข้อมูลรับรองของเซิร์ฟเวอร์ (รีเฟรชโทเคน OAuth หากใกล้หมดอายุ)
- สภาพแวดล้อมของโปรเซส
เนื่องจากการเขียนทับรายอะแดปเตอร์มาเป็นอันดับแรก มันจึงชนะบัญชีผู้ให้บริการที่เชื่อมต่อไว้ในแอปอย่างเงียบ ๆ หากการรันเรียกเก็บเงินผิดบัญชี การเขียนทับนั้นคือที่แรกที่ควรตรวจดู ข้อมูลรับรองของผู้ให้บริการเป็นระดับโฮสต์ทั้งโฮสต์ — ใช้ร่วมกันในทุกเวิร์กสเปซของระบบที่ติดตั้งนี้
โทเคน GitHub ของการรันมาจากโบรกเกอร์ข้อมูลรับรอง: โทเคนแบบอ่านอย่างเดียวที่จำกัดขอบเขตกับรีโปของ worktree การพุชผ่านเกตเวย์การรันเอเจนต์ ซึ่งถามกฎ พุชไปยังรีโมต ก่อนส่งต่อ และไม่มีการฉีดคีย์ตั๋วงานใด ๆ ดูแซนด์บ็อกซ์และความปลอดภัย
การเริ่มรัน
หัวข้อที่มีชื่อว่า “การเริ่มรัน”การรันถูกเปิดขึ้นโดยมี worktree ของมันเป็นไดเรกทอรีทำงาน และ — สำหรับ Claude Code — มีคอนฟิก MCP ที่สร้างขึ้น เพื่อให้เอเจนต์เข้าถึงชุดเครื่องมือของ Control Center ได้ ACP และ bash ของฮาร์เนสจะได้สภาพแวดล้อมที่ถูกทำให้สะอาด ส่วน Claude Code ผ่าน NoSandboxAdapter จะสืบทอดสภาพแวดล้อมของโฮสต์
การสตรีม
หัวข้อที่มีชื่อว่า “การสตรีม”การรันสตรีมลำดับเหตุการณ์ที่มีชนิดข้อมูลกลับมา ซึ่งตัวประมวลผลสตรีมจะบันทึกเป็นเดลตาของข้อความ พับรวมเป็นเซกเมนต์ของทรานสคริปต์ และแปลงเป็นเหตุการณ์การส่งข้อความ:
| เหตุการณ์ | สิ่งที่มันนำมาด้วย |
|---|---|
thinking |
เอาต์พุตการให้เหตุผล แสดงแบบอินไลน์ |
text |
เอาต์พุตที่มองเห็นได้ |
toolCall |
การเรียกใช้เครื่องมือ พร้อม id และอาร์กิวเมนต์เชิงโครงสร้าง |
toolResult |
ผลลัพธ์ที่ตรงกัน พร้อมแฟล็กเมื่อเกิดข้อผิดพลาดหรือเป็นสตรีมบางส่วน |
usage |
จำนวนโทเคนและต้นทุนสำหรับช่วงการวัด |
error |
ข้อผิดพลาด พร้อมรหัสเชิงโครงสร้างของอะแดปเตอร์เมื่อมีการรายงาน |
sandboxViolation |
ระบบปฏิบัติการปฏิเสธการเรียกใช้ระบบ จะถูกส่งออกเฉพาะเมื่อมีแซนด์บ็อกซ์ห่อหุ้มโปรเซสอยู่จริงเท่านั้น — ดูหมายเหตุด้านบน |
debug |
การวินิจฉัยขณะรัน (เครื่องหมายการเริ่มรัน การตัดสินใจของกฎคุม การกระตุ้นตามสัญญา) |
done |
การรันเสร็จสิ้น |
สิ่งที่จำกัดขอบเขตของการรัน
หัวข้อที่มีชื่อว่า “สิ่งที่จำกัดขอบเขตของการรัน”จงใจให้ไม่มีเพดานจำนวนรอบในที่ใดเลย การนับจำนวนรอบแบบตายตัวจะฆ่างานยาวที่ชอบธรรม (การไมเกรต, การเก็บกวาดงานแบบกระจาย) และไม่ได้จับอะไรที่ตัวป้องกันด้านล่างจับได้เร็วกว่าเลย การรันสิ้นสุดลงเมื่อ:
- โมเดลหยุดเอง
- มนุษย์หยุดมัน หรือเข้าควบคุมบทสนทนา (ซึ่งจะหยุดฮาร์เนสในตัวชั่วคราว ณ ขอบเขตรอบที่สะอาดรอบถัดไปของมัน — ส่วนการรันของ Claude Code ซึ่งไม่มีขอบเขตที่ปลอดภัย จะถูกหยุดแทน)
- ตัวเฝ้าระวังความเงียบทำงาน หากไม่มีเอาต์พุตเกินเกณฑ์ที่กำหนด เซสชันจะถูกยุติด้วยความล้มเหลว
silentRunค่าเริ่มต้นคือ 15 นาที ลดลงเหลือ 10 นาทีในโหมดที่อ่านเป็นหลัก (รีวิวและแผน) เอเจนต์อาจเขียนทับค่านี้ได้ระหว่าง 1 ถึง 240 นาที ตัวเฝ้าระวังจะถูกติดตั้งเมื่อโปรเซสลูกรายงาน PID ของมัน ดังนั้นมันจึงครอบคลุม Claude Code CLI — ไม่ใช่ฮาร์เนสในตัว ซึ่งไม่ได้เปิดโปรเซสใดเลย - เพดานค่าใช้จ่ายเข้าขบ — แต่เฉพาะกับคำสั่งแบบอัตโนมัติเท่านั้น
ตัวป้องกันการวนซ้ำซากไม่ใช่ตัวสั่งยุติ: การเรียกเครื่องมือที่เหมือนกันสามครั้งติดต่อกัน แล้วลูปจะ_บังคับทิศทาง_ให้เอเจนต์เปลี่ยนแนวทาง
เมื่อนำมารวมกัน รอบแบบอินเทอร์แอกทีฟธรรมดาบนฮาร์เนสในตัวจะไม่มีเพดานจำนวนรอบ ไม่มีเพดานค่าใช้จ่าย และไม่มีตัวเฝ้าระวังความเงียบ มันจบลงเมื่อโมเดลหยุดหรือเมื่อคุณสั่งให้หยุด นั่นเป็นการแลกเปลี่ยนที่จงใจ — ทางเลือกอื่นล้วนฆ่างานยาวที่ชอบธรรม — แต่มันก็หมายความว่าการรันแบบอินเทอร์แอกทีฟที่ไม่มีคนเฝ้าจะมีเพียงวิจารณญาณของโมเดลเองเป็นขอบเขต
ระหว่างการรัน ข้อความที่ส่งไปยังเอเจนต์ที่กำลังทำงานจะถูกจัดคิวเป็นการบังคับทิศทาง และถูกดึงออกไปที่ขอบเขตรอบถัดไป คุณจึงสามารถกระตุ้นการรันโดยไม่ต้องฆ่ามันได้ การบังคับทิศทาง การหยุดชั่วคราว เอเจนต์ย่อย และสัญญาการทำงานให้เสร็จเป็นคุณสมบัติของฮาร์เนสในตัว; Claude Code ไม่มีสิ่งเหล่านี้เลย
การรันถูกบันทึกอย่างไร
หัวข้อที่มีชื่อว่า “การรันถูกบันทึกอย่างไร”การสั่งงานทุกครั้งเขียน AgentRunLog: เวลาเริ่มและสิ้นสุด, สรุป, จำนวนโทเคนและต้นทุนโดยประมาณ (รวมถึงต้นทุนที่รวบรวมมาจากเอเจนต์ย่อย), อะแดปเตอร์และโมเดล, process id และเส้นทางบันทึก, บทสนทนา และตั๋วงานหรือรันไปป์ไลน์ใด ๆ ที่มันสังกัดอยู่ พร้อมด้วยฟิลด์การจำแนกสองฟิลด์ที่บอกความจริงส่วนใหญ่ไว้
- สถานะ เป็นแบบหยาบ:
pending,running,completed,error - ความมีชีวิต เป็นการอ่านที่ละเอียดกว่า:
alive,productive,completed,blocked,empty,looping,failed,stalled,dead - ตระกูลข้อผิดพลาด จัดกลุ่มความล้มเหลวได้อย่างมีประโยชน์:
transientUpstream,sandboxInfrastructure,budgetExceeded,processLost,silentRun,unknown
การปิดการรันจะเผยแพร่ AgentRunCompleted และมีอะไรอีกมากที่ขึ้นอยู่กับมัน: การรวบรวมต้นทุนของไปป์ไลน์, การทำงานต่อของขั้นตอนไปป์ไลน์ที่รอการรันนี้อยู่, การปิดตั๋วงานที่รองรับ, การแมปการประสานงานไปยังสถานะสิ้นสุด, การตัดสินใจว่าจะทำงานต่อหรือหยุดของผู้กำกับเป้าหมาย, บทบาทผู้ตรวจสอบ และการประเมินงบประมาณหลังการรัน ทำเนียบสถานะออนไลน์จะตามมาภายหลังแยกต่างหาก โดยเฝ้าดูบันทึกการรันล่าสุดแทนที่จะดูเหตุการณ์ การแจ้งเตือน “เอเจนต์เสร็จแล้ว” ไม่ได้อยู่ในรายการนั้น: เหตุการณ์นี้เกิดขึ้นเมื่อสตรีมของโปรเซสสิ้นสุดลง ก่อนที่คำตอบจะถูกเขียน การแจ้งเตือนจึงเป็น MessageReceived ของเทิร์นนั้น ซึ่งเผยแพร่เมื่อข้อความถูกบันทึกถาวรแล้ว
งบประมาณในภายหลัง
หัวข้อที่มีชื่อว่า “งบประมาณในภายหลัง”การบังคับใช้งบประมาณเป็น_ปฏิกิริยา_ ไม่ใช่ประตูด่าน เมื่อการรันเสร็จสิ้น ตัวประเมินจะเทียบค่าใช้จ่ายตั้งแต่ต้นเดือนถึงปัจจุบันของเอเจนต์กับเพดานที่มีผลบังคับใช้ของมัน (นโยบายงบประมาณที่เชื่อมไว้ หากมี มิฉะนั้นคือตัวเลขรายเดือนของเอเจนต์เอง; ศูนย์หมายถึงไม่จำกัด) การข้ามเกณฑ์อ่อนจะบันทึกอุบัติการณ์ระดับคำเตือน; การใช้งบประมาณจนหมดจะบันทึกอุบัติการณ์ระดับรุนแรง และพลิกสถานะวงจรชีวิตของเอเจนต์เป็น paused บนผังองค์กร การสั่งงานยังคงรับงานจากเอเจนต์นั้นอยู่ ทริกเกอร์ไปป์ไลน์ BudgetThresholdCrossed สามารถเริ่มงานติดตามผลจากเหตุการณ์เดียวกันได้
สายการลองใหม่
หัวข้อที่มีชื่อว่า “สายการลองใหม่”บันทึกการรันทุกอันสามารถพกสายการลองใหม่ได้ — run id ของตัวแม่, ตัวนับจำนวนครั้งที่ลอง และสรุปการทำงานต่อ แผนภูมิต้นไม้การรันของการสนทนาจะแสดงหมายเลขครั้งที่ลองเมื่อมันไม่ใช่ศูนย์ การกด “ลองใหม่” จากแชทถือเป็นการสั่งงานใหม่ที่มีบันทึกการรันใหม่
แนวคิดที่เกี่ยวข้อง
หัวข้อที่มีชื่อว่า “แนวคิดที่เกี่ยวข้อง”- โมเดลเอเจนต์: สิ่งที่อะแดปเตอร์บังคับใช้ได้และไม่ได้
- โหมด: ชุดเครื่องมือและสัญญาการทำงานให้เสร็จมาจากที่ใด
- กฎคุม: นโยบายตามคลาสผลลัพธ์ที่การเรียกที่มีประตูทุกครั้งต้องผ่าน
- แซนด์บ็อกซ์และความปลอดภัย: เรื่องราวการแยกส่วนแบบเต็ม
- การทำงานร่วมกันแบบหลายคน: การบังคับทิศทาง การเข้าควบคุม และปุ่มปรับระดับความเป็นอิสระ
- เหตุการณ์โดเมน: สิ่งที่
AgentRunCompletedไปจุดชนวน