Fundamentals
ลูปเอเจนต์
ลูปแบบเอเจนต์คือการรัน "จริง" แบบเต็มของเอเจนต์: การรับเข้า → การประกอบบริบท → การอนุมานของโมเดล → การเรียกใช้เครื่องมือ → การสตรีมคำตอบ → การคงข้อมูล เป็นเส้นทางที่เชื่อถือได้ซึ่งเปลี่ยนข้อความ ให้เป็นการกระทำและคำตอบสุดท้าย พร้อมรักษาสถานะเซสชันให้สอดคล้องกัน
ใน OpenClaw ลูปคือการรันแบบลำดับเดียวต่อเซสชัน ซึ่งปล่อยเหตุการณ์วงจรชีวิตและสตรีม ขณะที่โมเดลคิด เรียกเครื่องมือ และสตรีมผลลัพธ์ เอกสารนี้อธิบายวิธีเชื่อมลูปจริงนั้น ตั้งแต่ต้นจนจบ
จุดเข้าใช้งาน
- Gateway RPC:
agentและagent.wait - CLI: คำสั่ง
agent
วิธีทำงาน (ภาพรวมระดับสูง)
- RPC
agentตรวจสอบพารามิเตอร์ แก้ไขเซสชัน (sessionKey/sessionId) คงข้อมูลเมตาเซสชัน และส่งคืน{ runId, acceptedAt }ทันที agentCommandรันเอเจนต์:- แก้ไขค่าเริ่มต้นของโมเดล + thinking/verbose/trace
- โหลดสแนปช็อต Skills
- เรียก
runEmbeddedAgent(รันไทม์เอเจนต์ OpenClaw) - ปล่อย lifecycle end/error หากลูปแบบฝังไม่ได้ปล่อยเหตุการณ์นั้น
runEmbeddedAgent:- จัดลำดับการรันผ่านคิวต่อเซสชัน + คิวส่วนกลาง
- แก้ไขโมเดล + โปรไฟล์ auth และสร้างเซสชัน OpenClaw
- สมัครรับเหตุการณ์รันไทม์และสตรีมเดลตาของผู้ช่วย/เครื่องมือ
- บังคับใช้ timeout -> ยกเลิกการรันหากเกินกำหนด
- สำหรับเทิร์น app-server ของ Codex จะยกเลิกเทิร์นที่รับแล้วซึ่งหยุดสร้างความคืบหน้า app-server ก่อนเกิดเหตุการณ์สิ้นสุด
- ส่งคืนเพย์โหลด + เมตาดาตาการใช้งาน
subscribeEmbeddedAgentSessionเชื่อมเหตุการณ์รันไทม์เอเจนต์ไปยังสตรีมagentของ OpenClaw:- เหตุการณ์เครื่องมือ =>
stream: "tool" - เดลตาของผู้ช่วย =>
stream: "assistant" - เหตุการณ์วงจรชีวิต =>
stream: "lifecycle"(phase: "start" | "end" | "error")
- เหตุการณ์เครื่องมือ =>
agent.waitใช้waitForAgentRun:- รอ lifecycle end/error สำหรับ
runId - ส่งคืน
{ status: ok|error|timeout, startedAt, endedAt, error? }
- รอ lifecycle end/error สำหรับ
การเข้าคิว + ภาวะพร้อมกัน
- การรันถูกจัดลำดับต่อคีย์เซสชัน (เลนเซสชัน) และอาจผ่านเลนส่วนกลางด้วย
- สิ่งนี้ป้องกันการแข่งขันของเครื่องมือ/เซสชัน และรักษาประวัติเซสชันให้สอดคล้องกัน
- ช่องทางรับส่งข้อความสามารถเลือกโหมดคิว (steer/followup/collect/interrupt) ที่ป้อนเข้าสู่ระบบเลนนี้ ดู คิวคำสั่ง
- การเขียนทรานสคริปต์ยังได้รับการป้องกันด้วยล็อกการเขียนเซสชันบนไฟล์เซสชัน ล็อกนี้
รับรู้กระบวนการและอิงไฟล์ จึงจับตัวเขียนที่ข้ามคิวภายในกระบวนการหรือมาจาก
กระบวนการอื่นได้ ตัวเขียนทรานสคริปต์เซสชันรอได้สูงสุด
session.writeLock.acquireTimeoutMsก่อนรายงานว่าเซสชันไม่ว่าง ค่าเริ่มต้นคือ60000มิลลิวินาที - ล็อกการเขียนเซสชันไม่เป็นแบบ reentrant โดยค่าเริ่มต้น หากตัวช่วยตั้งใจซ้อนการยึด
ล็อกเดียวกันโดยยังรักษาตัวเขียนเชิงตรรกะหนึ่งตัวไว้ จะต้องเลือกใช้โดยชัดเจนด้วย
allowReentrant: true
การเตรียมเซสชัน + เวิร์กสเปซ
- เวิร์กสเปซถูกแก้ไขและสร้างขึ้น การรันแบบ sandbox อาจเปลี่ยนเส้นทางไปยังรากเวิร์กสเปซ sandbox
- Skills ถูกโหลด (หรือนำกลับมาใช้จากสแนปช็อต) และฉีดเข้า env และ prompt
- ไฟล์ bootstrap/context ถูกแก้ไขและฉีดเข้าในรายงาน system prompt
- มีการยึดล็อกการเขียนเซสชัน จากนั้นเปิดและเตรียม
SessionManagerก่อนเริ่มสตรีม เส้นทาง การเขียนทรานสคริปต์ใหม่ การทำ Compaction หรือการตัดทอนในภายหลัง ต้องใช้ล็อกเดียวกันก่อนเปิดหรือ เปลี่ยนแปลงไฟล์ทรานสคริปต์
การประกอบ prompt + system prompt
- system prompt ถูกสร้างจาก prompt พื้นฐานของ OpenClaw, prompt ของ Skills, บริบท bootstrap และการแทนที่รายรัน
- บังคับใช้ขีดจำกัดเฉพาะโมเดลและโทเค็นสำรองสำหรับ Compaction
- ดู System prompt เพื่อดูว่าโมเดลเห็นอะไร
จุด hook (ตำแหน่งที่คุณดักแทรกได้)
OpenClaw มีระบบ hook สองแบบ:
- hook ภายใน (hook ของ Gateway): สคริปต์ขับเคลื่อนด้วยเหตุการณ์สำหรับคำสั่งและเหตุการณ์วงจรชีวิต
- hook ของ Plugin: จุดขยายภายในวงจรชีวิตเอเจนต์/เครื่องมือและ pipeline ของ gateway
hook ภายใน (hook ของ Gateway)
agent:bootstrap: รันขณะสร้างไฟล์ bootstrap ก่อนสรุป system prompt ใช้สิ่งนี้เพื่อเพิ่ม/ลบไฟล์บริบท bootstrap- hook คำสั่ง:
/new,/reset,/stopและเหตุการณ์คำสั่งอื่นๆ (ดูเอกสาร Hooks)
ดู Hooks สำหรับการตั้งค่าและตัวอย่าง
hook ของ Plugin (วงจรชีวิตเอเจนต์ + gateway)
สิ่งเหล่านี้รันภายในลูปเอเจนต์หรือ pipeline ของ gateway:
before_model_resolve: รันก่อนเซสชัน (ไม่มีmessages) เพื่อแทนที่ provider/model อย่างกำหนดได้แน่นอนก่อนการแก้ไขโมเดลbefore_prompt_build: รันหลังโหลดเซสชัน (พร้อมmessages) เพื่อฉีดprependContext,systemPrompt,prependSystemContextหรือappendSystemContextก่อนส่ง prompt ใช้prependContextสำหรับข้อความไดนามิกต่อเทิร์น และใช้ฟิลด์ system-context สำหรับคำแนะนำคงที่ที่ควรอยู่ในพื้นที่ system promptbefore_agent_start: hook ความเข้ากันได้แบบเดิมที่อาจรันในเฟสใดเฟสหนึ่ง ควรใช้ hook แบบชัดเจนด้านบนbefore_agent_reply: รันหลังการกระทำแบบ inline และก่อนการเรียก LLM ช่วยให้ Plugin รับเทิร์นนี้และส่งคืนคำตอบสังเคราะห์หรือปิดเสียงเทิร์นทั้งหมดagent_end: ตรวจสอบรายการข้อความสุดท้ายและเมตาดาตาการรันหลังเสร็จสิ้นbefore_compaction/after_compaction: สังเกตหรือใส่หมายเหตุรอบการทำ Compactionbefore_tool_call/after_tool_call: ดักพารามิเตอร์/ผลลัพธ์ของเครื่องมือbefore_install: ตรวจสอบวัสดุการติดตั้ง skill หรือ Plugin ที่จัดเตรียมแล้ว หลังนโยบายติดตั้งของผู้ปฏิบัติการรัน เมื่อ hook ของ Plugin ถูกโหลดในกระบวนการ OpenClaw ปัจจุบันtool_result_persist: แปลงผลลัพธ์เครื่องมือแบบซิงโครนัสก่อนเขียนลงในทรานสคริปต์เซสชันที่ OpenClaw เป็นเจ้าของmessage_received/message_sending/message_sent: hook ข้อความขาเข้า + ขาออกsession_start/session_end: ขอบเขตวงจรชีวิตเซสชันgateway_start/gateway_stop: เหตุการณ์วงจรชีวิต gateway
กฎการตัดสินใจของ hook สำหรับตัวกันขาออก/เครื่องมือ:
before_tool_call:{ block: true }เป็นสถานะสิ้นสุดและหยุด handler ที่มีลำดับความสำคัญต่ำกว่าbefore_tool_call:{ block: false }เป็น no-op และไม่ล้างการบล็อกก่อนหน้าbefore_install:{ block: true }เป็นสถานะสิ้นสุดและหยุด handler ที่มีลำดับความสำคัญต่ำกว่าbefore_install:{ block: false }เป็น no-op และไม่ล้างการบล็อกก่อนหน้า- ใช้
security.installPolicyไม่ใช่before_installสำหรับการตัดสินใจอนุญาต/บล็อกการติดตั้งที่ผู้ปฏิบัติการเป็นเจ้าของ ซึ่งต้องครอบคลุมเส้นทางการติดตั้งและอัปเดตผ่าน CLI message_sending:{ cancel: true }เป็นสถานะสิ้นสุดและหยุด handler ที่มีลำดับความสำคัญต่ำกว่าmessage_sending:{ cancel: false }เป็น no-op และไม่ล้างการยกเลิกก่อนหน้า
ดู hook ของ Plugin สำหรับ API ของ hook และรายละเอียดการลงทะเบียน
harness อาจปรับ hook เหล่านี้แตกต่างกัน harness app-server ของ Codex รักษา hook ของ Plugin OpenClaw เป็นสัญญาความเข้ากันได้สำหรับพื้นผิว mirror ที่จัดทำเอกสารไว้ ขณะที่ hook native ของ Codex ยังคงเป็นกลไก Codex ระดับต่ำกว่าแยกต่างหาก
การสตรีม + คำตอบบางส่วน
- เดลตาของผู้ช่วยถูกสตรีมจากรันไทม์เอเจนต์และปล่อยเป็นเหตุการณ์
assistant - การสตรีมบล็อกสามารถปล่อยคำตอบบางส่วนได้ทั้งที่
text_endหรือmessage_end - การสตรีม reasoning สามารถปล่อยเป็นสตรีมแยกหรือเป็นคำตอบแบบบล็อกได้
- ดู การสตรีม สำหรับพฤติกรรมการแบ่งชิ้นและคำตอบแบบบล็อก
การเรียกใช้เครื่องมือ + เครื่องมือรับส่งข้อความ
- เหตุการณ์เริ่ม/อัปเดต/จบของเครื่องมือถูกปล่อยบนสตรีม
tool - ผลลัพธ์เครื่องมือถูกทำให้ปลอดภัยด้านขนาดและเพย์โหลดรูปภาพก่อนบันทึก/ปล่อยเหตุการณ์
- การส่งผ่านเครื่องมือรับส่งข้อความถูกติดตามเพื่อระงับการยืนยันของผู้ช่วยที่ซ้ำกัน
การจัดรูปคำตอบ + การระงับ
- เพย์โหลดสุดท้ายถูกประกอบจาก:
- ข้อความผู้ช่วย (และ reasoning ที่เป็นทางเลือก)
- สรุปเครื่องมือแบบ inline (เมื่อ verbose + อนุญาต)
- ข้อความข้อผิดพลาดของผู้ช่วยเมื่อโมเดลเกิดข้อผิดพลาด
- โทเค็นเงียบที่ตรงตัว
NO_REPLY/no_replyถูกกรองออกจากเพย์โหลด ขาออก - รายการซ้ำจากเครื่องมือรับส่งข้อความถูกลบออกจากรายการเพย์โหลดสุดท้าย
- หากไม่มีเพย์โหลดที่เรนเดอร์ได้เหลืออยู่และเครื่องมือเกิดข้อผิดพลาด จะปล่อยคำตอบข้อผิดพลาดเครื่องมือสำรอง (เว้นแต่เครื่องมือรับส่งข้อความได้ส่งคำตอบที่ผู้ใช้เห็นได้ไปแล้ว)
Compaction + การลองใหม่
- Auto-compaction ปล่อยเหตุการณ์สตรีม
compactionและสามารถกระตุ้นการลองใหม่ - เมื่อลองใหม่ บัฟเฟอร์ในหน่วยความจำและสรุปเครื่องมือจะถูกรีเซ็ตเพื่อหลีกเลี่ยงผลลัพธ์ซ้ำ
- ดู Compaction สำหรับ pipeline ของ Compaction
สตรีมเหตุการณ์ (ปัจจุบัน)
lifecycle: ปล่อยโดยsubscribeEmbeddedAgentSession(และเป็น fallback โดยagentCommand)assistant: เดลตาที่สตรีมจากรันไทม์เอเจนต์tool: เหตุการณ์เครื่องมือที่สตรีมจากรันไทม์เอเจนต์
การจัดการช่องแชต
- เดลตาของผู้ช่วยถูกบัฟเฟอร์เป็นข้อความ
deltaของแชต - ปล่อย
finalของแชตเมื่อเกิด lifecycle end/error
Timeout
- ค่าเริ่มต้นของ
agent.wait: 30 วินาที (เฉพาะการรอ) พารามิเตอร์timeoutMsจะแทนที่ - รันไทม์เอเจนต์: ค่าเริ่มต้นของ
agents.defaults.timeoutSecondsคือ 172800 วินาที (48 ชั่วโมง); บังคับใช้ในตัวจับเวลา abort ของrunEmbeddedAgent - รันไทม์ Cron:
timeoutSecondsของ agent-turn ที่แยกโดดเดี่ยวเป็นของ cron ตัว scheduler เริ่มตัวจับเวลานั้นเมื่อการดำเนินการเริ่มขึ้น ยกเลิกการรันพื้นฐานเมื่อถึงกำหนดเวลาที่กำหนดค่าไว้ จากนั้นรันการล้างข้อมูลแบบมีขอบเขตก่อนบันทึก timeout เพื่อไม่ให้เซสชันลูกค้างเก่าทำให้เลนติดค้าง - การวินิจฉัยความมีชีวิตของเซสชัน: เมื่อเปิดใช้ diagnostics,
diagnostics.stuckSessionWarnMsจะจัดประเภทเซสชันprocessingที่ใช้เวลานานและไม่มี reply, tool, status, block หรือความคืบหน้า ACP ที่สังเกตได้ การรันแบบฝัง การเรียกโมเดล และการเรียกเครื่องมือที่ active จะรายงานเป็นsession.long_running; การเรียกโมเดลแบบเงียบที่มีเจ้าของยังคงเป็นsession.long_runningจนถึงdiagnostics.stuckSessionAbortMsเพื่อไม่ให้ provider ที่ช้าหรือไม่สตรีมถูกรายงานว่าค้างเร็วเกินไป งานที่ active แต่ไม่มีความคืบหน้าล่าสุดจะรายงานเป็นsession.stalled; การเรียกโมเดลที่มีเจ้าของจะเปลี่ยนเป็นsession.stalledเมื่อถึงหรือหลังเกณฑ์ abort และกิจกรรมโมเดล/เครื่องมือเก่าที่ไม่มีเจ้าของจะไม่ถูกซ่อนไว้ในฐานะ long-runningsession.stuckสงวนไว้สำหรับการทำบัญชีเซสชันเก่าที่กู้คืนได้ รวมถึงเซสชันที่อยู่ในคิวและ idle พร้อมกิจกรรมโมเดล/เครื่องมือเก่าที่ไม่มีเจ้าของ การทำบัญชีเซสชันเก่าจะปล่อยเลนเซสชันที่ได้รับผลกระทบทันทีหลังผ่าน recovery gate; การรันแบบฝังที่ stalled จะถูก abort-drain หลังdiagnostics.stuckSessionAbortMsเท่านั้น (ค่าเริ่มต้น: อย่างน้อย 5 นาทีและ 3 เท่าของเกณฑ์เตือน) เพื่อให้งานที่เข้าคิวกลับมาทำงานต่อได้โดยไม่ตัดการรันที่เพียงแค่ช้าออก การกู้คืนปล่อยผลลัพธ์ requested/completed แบบมีโครงสร้าง และสถานะ diagnostic จะถูกทำเครื่องหมาย idle เฉพาะเมื่อ generation การประมวลผลเดียวกันยังเป็นปัจจุบันอยู่ diagnosticsession.stuckที่เกิดซ้ำจะ back off ขณะที่เซสชันยังไม่เปลี่ยนแปลง - Timeout ขณะโมเดล idle: OpenClaw ยกเลิกคำขอโมเดลเมื่อไม่มีชิ้นส่วนคำตอบมาถึงก่อนครบหน้าต่าง idle
models.providers.<id>.timeoutSecondsขยายตัวเฝ้าระวัง idle นี้สำหรับ provider ในเครื่อง/โฮสต์เองที่ช้า แต่ยังถูกจำกัดโดยagents.defaults.timeoutSecondsหรือ timeout เฉพาะการรันที่ต่ำกว่า เพราะสิ่งเหล่านั้นควบคุมการรันเอเจนต์ทั้งหมด มิฉะนั้น OpenClaw ใช้agents.defaults.timeoutSecondsเมื่อกำหนดค่าไว้ โดยจำกัดไว้ที่ 120 วินาทีตามค่าเริ่มต้น การรันโมเดลบนคลาวด์ที่ถูก Cron กระตุ้นโดยไม่มี timeout ของโมเดลหรือเอเจนต์แบบชัดเจนจะใช้ตัวเฝ้าระวัง idle ค่าเริ่มต้นเดียวกัน; เมื่อมี timeout การรัน cron แบบชัดเจน การค้างของสตรีมโมเดลบนคลาวด์จะถูกจำกัดที่ 60 วินาที เพื่อให้ model fallback ที่กำหนดค่าไว้รันได้ก่อนกำหนดเวลาภายนอกของ cron การรันโมเดลในเครื่องหรือโฮสต์เองที่ถูก Cron กระตุ้นจะปิดใช้ตัวเฝ้าระวังโดยนัย เว้นแต่กำหนดค่า timeout แบบชัดเจนไว้ และ timeout การรัน cron แบบชัดเจนยังคงเป็นหน้าต่าง idle สำหรับ provider ในเครื่อง/โฮสต์เอง ดังนั้น provider ในเครื่องที่ช้าควรตั้งmodels.providers.<id>.timeoutSeconds - Timeout คำขอ HTTP ของ provider:
models.providers.<id>.timeoutSecondsใช้กับการ fetch HTTP ของโมเดลของ provider นั้น รวมถึง connect, headers, body, timeout คำขอ SDK, การจัดการ abort ของ guarded-fetch ทั้งหมด และตัวเฝ้าระวัง idle ของสตรีมโมเดล ใช้สิ่งนี้สำหรับ provider ในเครื่อง/โฮสต์เองที่ช้า เช่น Ollama ก่อนเพิ่ม timeout ของรันไทม์เอเจนต์ทั้งหมด และคง timeout ของเอเจนต์/รันไทม์ให้สูงอย่างน้อยเท่ากันเมื่อคำขอโมเดลต้องรันนานขึ้น
ตำแหน่งที่สิ่งต่างๆ อาจจบก่อนกำหนด
- หมดเวลาของเอเจนต์ (ยกเลิก)
- AbortSignal (ยกเลิก)
- Gateway ตัดการเชื่อมต่อหรือ RPC หมดเวลา
- หมดเวลา
agent.wait(รอเท่านั้น ไม่หยุดเอเจนต์)
ที่เกี่ยวข้อง
- เครื่องมือ — เครื่องมือเอเจนต์ที่มีให้ใช้
- Hooks — สคริปต์ที่ขับเคลื่อนด้วยเหตุการณ์ ซึ่งถูกทริกเกอร์โดยเหตุการณ์ในวงจรชีวิตของเอเจนต์
- Compaction — วิธีสรุปการสนทนาที่ยาว
- การอนุมัติ Exec — จุดควบคุมการอนุมัติสำหรับคำสั่งเชลล์
- การคิด — การกำหนดค่าระดับการคิด/การให้เหตุผล