ไปป์ไลน์และระบบอัตโนมัติ
ไปป์ไลน์คือส่วนที่แน่นอนตายตัวของ Control Center เอเจนต์ตัดสินใจว่าจะพูดอะไร ส่วนไปป์ไลน์ตัดสินใจว่าจะเกิดอะไรต่อไป เหมือนเดิมทุกครั้ง ไปป์ไลน์คือ DAG ของขั้นตอน ที่สั่งงานเอเจนต์ รันสคริปต์ แยกสาขาตามเงื่อนไข กระจายงานไปทั่วคอลเลกชัน และส่งข้อมูล ระหว่างขั้นตอน — บันทึกไว้ต่อเนื่อง กู้รันต่อได้ และคิดต้นทุนไว้แล้ว
ไปป์ไลน์มีอยู่ด้วยเหตุผลสามข้อ: เพื่อร้อยเรียงกระบวนการหลายขั้นตอนที่ทำซ้ำ ๆ เข้าด้วยกัน เพื่อประสานเอเจนต์หลายตัวตามลำดับหรือพร้อมกัน และเพื่อตอบสนองต่อสิ่งที่เกิดขึ้นโดยไม่มี มนุษย์อยู่ตรงนั้น
เทมเพลตและรัน
หัวข้อที่มีชื่อว่า “เทมเพลตและรัน”เทมเพลต (PipelineDefinition) คือ DAG แบบประกาศ: ขั้นตอน อินพุตที่ประกาศไว้ และ
การตั้งค่า มันอยู่ในฐานข้อมูลของเวิร์กสเปซเอง รัน (PipelineRun) คือการทำงานหนึ่งครั้ง
ของเทมเพลตนั้น ซึ่งพกที่เก็บสถานะที่แก้ไขได้ ยอดรวมต้นทุนและโทเค็น และสถานะของแต่ละ
ขั้นตอน
เทมเพลตหนึ่งตัวมีได้หลายรัน รันอยู่รอดข้ามการรีสตาร์ต: เอนจินโหลดรันที่กำลังทำงานอยู่ กลับมาและทำงานต่อจากจุดที่หยุดไว้
มีกลไกกันพลาดสองข้อที่จงใจทำให้ทั้งรันล้มเหลวแทนที่จะรันขั้นตอนต่อ เพราะการรันต่อจะแย่ กว่าการหยุด:
- ขั้นตอนที่ถูก
suspendedนานเกินsuspendedStepTimeout(ค่าเริ่มต้น 24 ชั่วโมง) กำลังรอตั๋วงานที่จะไม่มีวันไปถึงสถานะสิ้นสุด จึงถูกทำให้ล้มเหลวเพื่อปลดรัน ข้อยกเว้นคือextras['awaitApproval'] == true— นั่นคือเกตการอนุมัติบางส่วนorchestration.awaitApprovalhuman.gateไม่ได้รับข้อยกเว้น - ขั้นตอนที่ประกาศ
extras: {'idempotent': false}และกำลังทำงานอยู่ตอนเซิร์ฟเวอร์หยุด อาจใช้ผลข้างเคียงของมันไปแล้ว (การสควอชเมิร์จ การล้าง worktree) การรันซ้ำอาจใช้ผลซ้ำ สองครั้ง เอนจินจึงทำให้มันล้มเหลวและปล่อยการลองใหม่ไว้ให้คุณตัดสินใจ
ชนิดจัดตาราง บอดีลงมือทำงาน
หัวข้อที่มีชื่อว่า “ชนิดจัดตาราง บอดีลงมือทำงาน”ขั้นตอนหนึ่งมีสองส่วนที่เป็นอิสระจากกัน และการแยกสองส่วนนี้ออกจากกันคือสิ่งที่ทำให้ เอนจินเล็กอยู่ได้
ชนิด (StepKind) บอกเอนจินว่า เมื่อใด ขั้นตอนจะพร้อมรันเมื่อเทียบกับขั้นตอนต้นทาง
ของมัน — นั่นคือสิ่งเดียวที่ตัวจัดตารางต้องรู้ มีหกชนิด: trigger, listen, join,
router, forEach และ terminal บอดี (bodyKey) คือ งาน ที่ขั้นตอนทำเมื่อถูก
จัดตารางแล้ว บอดีคือคลอเชอร์ที่ลงทะเบียนไว้ตามคีย์ตอนเริ่มเซิร์ฟเวอร์ ขั้นตอนต่างชนิดกัน
หลายตัวจึงใช้บอดีเดียวกันได้ เช่นขั้นตอน listen หลายตัวที่ล้วนรัน
conversation.promptAgent
เพราะความหมายของการจัดตารางอยู่ในหกชนิดนี้ แค็ตตาล็อกของพฤติกรรมจึงเพิ่มขึ้นได้โดยไม่มี ใครต้องแตะตัวจัดตาราง ดูขั้นตอนไปป์ไลน์สำหรับ แค็ตตาล็อกฉบับเต็มของชนิด บอดี และการตั้งค่าของมัน
ผลสืบเนื่องสองข้อของการออกแบบแบบทะเบียนที่ควรรู้ก่อนเขียนเทมเพลตด้วยมือ:
- ขั้นตอนที่
bodyKeyไม่ได้ลงทะเบียนไว้จะสร้าง คำเตือนตอนโหลดเทมเพลต แล้วไม่ทำงาน เลย ไม่มีอะไรล้มเหลวให้เห็นตอนรัน ขั้นตอนtriggerและterminalได้รับยกเว้นจาก คำเตือนนั้น: ทริกเกอร์ยังรันบอดีpipeline.triggerที่ไม่ทำอะไร เพื่อให้ตัวฟังปลายทาง ทำงาน ส่วนขั้นตอนterminalไม่มีบอดีและเป็นเครื่องหมายเฉพาะของตัวจัดตาราง - คีย์ในแมป
extrasของโหนดต้อง ตรงกันเป๊ะ มิฉะนั้นจะถูกละเลยโดยไม่แจ้ง มีเพียงextras['spaceId']เท่านั้นที่วางงานของขั้นตอนเอเจนต์ลงในบทสนทนาที่มีอยู่แล้วextras['mode'](chat/plan/review) ถูกอ่านที่โหนดที่ เปิด ห้อง (messaging.createSpace, ค่าเริ่มต้นreview) — ขั้นตอนเอเจนต์ที่ตามมาทีหลังไม่ สามารถเปลี่ยนสิทธิ์การสนทนาที่มันได้เข้าร่วมไปแล้ว การสะกดแบบอื่นของคีย์ใดคีย์หนึ่งจะ ถูกละเลย
สถานะและการไหลของข้อมูล
หัวข้อที่มีชื่อว่า “สถานะและการไหลของข้อมูล”ขั้นตอนต่าง ๆ ไม่เรียกหากันและกัน แต่ละตัวอ่านจากและเขียนลงในที่เก็บสถานะที่ใช้ร่วมกันบน
รัน: ขั้นตอนอ่านอินพุตของมันตามคีย์ ทำงาน แล้วเขียนเอาต์พุตกลับไปใต้ outputKey
ของตัวเอง StateReducer รวมการเขียนที่เกิดขึ้นพร้อมกันเมื่อสาขาที่รันขนานกันเขียน
คีย์เดียวกัน และ TemplateRenderer แทนที่ตัวยึดตำแหน่ง {{...}} ในพรอมป์ต์และสคริปต์
จากสถานะเดียวกันนั้น
นี่คือเหตุผลที่ไปป์ไลน์ตรวจสอบย้อนหลังได้ — ที่เก็บสถานะคือเรื่องราวทั้งหมดของรัน
อะไรทำให้รันเริ่มขึ้น
หัวข้อที่มีชื่อว่า “อะไรทำให้รันเริ่มขึ้น”แถว PipelineTrigger ประกาศว่าเทมเพลตเริ่มเองเมื่อใด มีสี่ชนิด:
| ทริกเกอร์ | เริ่มรันเมื่อ |
|---|---|
| เหตุการณ์โดเมน | เกิดเหตุการณ์โดเมนที่ตรงกัน เช่น PullRequestPublished หรือ TicketAssigned |
| ตารางเวลา | นิพจน์ cron/ช่วงเวลาถึงกำหนด |
| ด้วยตนเอง | คุณรันด้วยมือ การมีทริกเกอร์แบบด้วยตนเองที่เปิดใช้นั้นคือสิ่งที่ทำให้เทมเพลตปรากฏในตัวเลือกการรัน |
| Webhook | ระบบภายนอกส่ง POST ไปที่ /webhooks/<token> บนพอร์ต HTTP ของเซิร์ฟเวอร์ |
ทริกเกอร์แบบเหตุการณ์เป็นชุดปิดตายตัว: มี 16 ชนิดเหตุการณ์ที่ตัวกระจายรู้จักและแสดงใน
ตัวเลือก (EventPayloadMapper.knownEventTypes) และไม่มีอย่างอื่นเริ่มไปป์ไลน์ได้ ใน 16
ชนิดนั้นมี 14 ชนิดที่มีการแมปเพย์โหลด อีกสองชนิด — TicketCreated และ
TicketStatusChanged — ไม่มีการแมป ดังนั้นทริกเกอร์บนสองชนิดนี้จะเปิดอยู่แต่ไม่เคย
ทำงาน ดูเหตุการณ์โดเมนสำหรับรายการฉบับเต็ม
โทเค็น webhook ทำหน้าที่เป็นซีเคร็ต HMAC ไปด้วย: เฮดเดอร์
X-Hub-Signature-256: sha256=<hex> ของคำขอจะถูกตรวจสอบกับ
HMAC-SHA256(body, token) การส่งที่ไม่ผ่านการตรวจสอบจะถูกปฏิเสธและเล่นซ้ำไม่ได้
ส่วนรายการซ้ำจะถูกตัดออกด้วย dedupe_key เพราะแถวทริกเกอร์ไม่ซ้ำกันเมื่อเทียบ
(เวิร์กสเปซ, ชนิดเหตุการณ์, เทมเพลต) เทมเพลตหนึ่งตัวจึงมีทริกเกอร์ webhook ได้ไม่เกิน
หนึ่งตัว และมีทริกเกอร์ได้ไม่เกินหนึ่งตัวต่อหนึ่งชนิดเหตุการณ์โดเมน
เทมเพลตในตัวติดตั้ง ทริกเกอร์แบบด้วยตนเองและแบบเหตุการณ์ให้เปิดไว้ ส่วน ทริกเกอร์ตามตารางเวลาติดตั้งมาแบบปิด งานกวาดซ้ำตามรอบจึงต้องเปิดเองเสมอ
เทมเพลตที่มาพร้อมสถานะปิด
หัวข้อที่มีชื่อว่า “เทมเพลตที่มาพร้อมสถานะปิด”เทมเพลตไปป์ไลน์สิบสามตัวถูกติดตั้งไว้ในทุกเวิร์กสเปซ และ แปดตัวมาพร้อมสถานะปิด:
external_pr_welcome, cross_review, ticket_to_pr, pr_triage, pre_merge_gate,
release_notes, dep_audit และ pr_digest
นี่คือส่วนที่ทำให้คนแปลกใจ ทริกเกอร์ของเทมเพลตเหล่านี้ติดตั้งมาแบบ เปิด แต่
PipelineEngine.start ปฏิเสธเทมเพลตที่ปิดอยู่และคืนค่า null — ทริกเกอร์จึงทำงานไป
อย่างไร้ผลและไม่มีรันปรากฏขึ้น สวิตช์อยู่ที่เทมเพลต ไม่ใช่ที่ทริกเกอร์ เปิดใช้งานที่
การตั้งค่า → เวิร์กสเปซ → เทมเพลตไปป์ไลน์ ก่อนจะคาดหวังให้แปดตัวนั้นทำอะไรได้
การติดตั้งซ้ำในเวิร์กสเปซจะเก็บสิ่งที่คุณเลือกไว้: การตั้งค่า isEnabled และแถวทริกเกอร์
ที่มีอยู่ของคุณจะคงอยู่ มีข้อยกเว้นโดยเจตนาอยู่หนึ่งข้อพอดี — ตารางเวลารายวันของ
pr_merged_cleanup จะถูกบังคับให้เปิด แม้ก่อนหน้านี้จะปิดอยู่ เพราะมันคือการเก็บขยะ
หากไม่มีมัน แถว worktree พาร์ทิชันของกราฟโค้ด และสำเนาแบบ copy-on-write จะพอกพูนขึ้น
และนั่นไม่เคยตั้งใจให้เป็นทางเลือกของผู้ใช้
ความไม่สมมาตรอีกข้อที่ควรรู้: เทมเพลตในตัว pr_review จงใจไม่โพสต์ขึ้น GitHub อีกต่อไป
การเผยแพร่รีวิวเป็นขั้นตอนแยกต่างหากที่ผู้ใช้ต้องอนุมัติเอง และไปป์ไลน์ที่โพสต์โดยตรงจะ
เผยแพร่ซ้ำสองครั้ง แต่ cross_review, ticket_to_pr และ pr_triage ยังคงโพสต์
ความคิดเห็นตรงขึ้นไปยัง GitHub เมื่อทำงาน
สิ่งที่เอนจินรู้
หัวข้อที่มีชื่อว่า “สิ่งที่เอนจินรู้”PipelineEngine สร้างบันทึกรัน จัดตารางโหนดเริ่มต้นที่ตรงกับชนิดเหตุการณ์ของรัน แล้วไล่
ไปตาม DAG: เมื่อขั้นตอนต่าง ๆ เสร็จ มันจะประเมินทริกเกอร์ปลายทาง แก้สาขาของ router รอ
join ปรับใช้นโยบายลองใหม่และ continue-on-fail และบันทึกสถานะ ต้นทุน และข้อผิดพลาดไว้
ทุกขั้นตอน เส้นเชื่อมที่ออกจากจุดเริ่มต้นอีกจุดจะถูกละเลยสำหรับรันนั้น การทำงานจาก
ตารางเวลาจึงไม่ต้องรอเงื่อนไขที่เป็นแบบด้วยตนเองเท่านั้น
สิ่งที่มัน ไม่ รู้คือเรื่องใด ๆ เกี่ยวกับระบบตั๋วงาน การสั่งงาน GitHub หรือการรับส่ง
ข้อความ รอยต่อขยายเพียงจุดเดียวของมันคือ PipelineBodyRegistry บอดีที่ลงทะเบียนที่นั่น
คือสิ่งที่ถือ AgentDispatchPort, MessagingPort และพอร์ตอื่นในตระกูลเดียวกัน —
นี่คือเหตุผลที่การเพิ่มความสามารถให้ไปป์ไลน์ไม่เคยต้องแก้ตัวจัดตาราง
การจัดการข้อผิดพลาด
หัวข้อที่มีชื่อว่า “การจัดการข้อผิดพลาด”ขั้นตอนที่ล้มเหลวจะบันทึกข้อความข้อผิดพลาดของมันแล้วเปลี่ยนไปเป็น failed หากขั้นตอนนั้น
ประกาศ continueOnFail ขั้นตอนปลายทางจะดำเนินต่อไปและข้อผิดพลาดจะถูกพักไว้ในสถานะของ
รัน มิฉะนั้นรันจะล้มเหลว ขั้นตอนที่มี StepRetryPolicy จะถูกลองใหม่ก่อน ด้วยการหน่วง
แบบเชิงเส้นหรือแบบเอกซ์โพเนนเชียล ก่อนที่สองกรณีข้างต้นจะบังคับใช้
ดูเพิ่มเติม
หัวข้อที่มีชื่อว่า “ดูเพิ่มเติม”- เหตุการณ์โดเมน: ทริกเกอร์แบบเหตุการณ์รอฟังอะไรอยู่
- การประสานงาน: แผนที่คุณอนุมัติ แล้วถูกคอมไพล์เป็นไปป์ไลน์แบบหนึ่งในนี้
- ตั๋วงานและการมอบหมาย: สิ่งที่ขั้นตอนไปป์ไลน์สร้างและทำจนเสร็จ
- ขั้นตอนไปป์ไลน์: แค็ตตาล็อกฉบับเต็มของชนิด บอดี และการตั้งค่า
- สร้างไปป์ไลน์แรกของคุณ
- สร้างเทมเพลตไปป์ไลน์
- รันไปป์ไลน์ด้วยตนเอง
- ติดตามรันไปป์ไลน์
- ตั้งทริกเกอร์ไปป์ไลน์