2 นาที

การย้อนกลับอัตโนมัติสำหรับผลกระทบของ agent

การย้อนกลับอัตโนมัติสำหรับผลกระทบของ agent ไม่อาจเลิกทำทุกการกระทำภายนอกได้ เรียนรู้ว่าสแนปช็อตสิ้นสุดตรงไหน และเมื่อใดจึงต้องเริ่มใช้การอนุมัติหรือการชดเชย

การย้อนกลับอัตโนมัติสำหรับผลกระทบของ agent

การย้อนกลับ agent สามารถกู้คืนโค้ด การตั้งค่า หรือข้อมูลแอปบางส่วนได้ แต่ไม่อาจทำให้องค์กรอื่นลืมคำขอ ดึงอีเมลที่ส่งถึงกล่องจดหมายแล้วกลับมา หรือทำเป็นว่ารายการเรียกเก็บบัตรไม่เคยไปถึงผู้ประมวลผลการชำระเงิน ทีมที่เรียกการดำเนินการทั้งหมดนี้ว่า «rollback» กำลังสร้างกลไกควบคุมที่ให้ความอุ่นใจ แต่ล้มเหลวในจังหวะที่ผลลัพธ์สำคัญที่สุด

การออกแบบที่ปลอดภัยแยกกลไกออกเป็นสี่ส่วน: สแนปช็อตแอป Git revert การกู้คืนฐานข้อมูล และการกระทำชดเชย แต่ละส่วนมีขอบเขตของตนเอง การกระทำที่ข้ามขอบเขตแอปต้องมีการอนุมัติ หลักฐาน กฎการลองใหม่ และเส้นทางกู้คืนของตัวเองก่อน agent จะทำงาน หากไม่มีใครอธิบายเส้นทางนั้นได้ในประโยคเดียว การกระทำนั้นยังไม่พร้อมให้ทำงานโดยไม่มีผู้ดูแล

Rollback มีสี่ความหมายที่แยกจากกัน

Rollback มีประโยชน์ก็ต่อเมื่อทีมระบุสถานะที่จะกู้คืนและสถานะที่แตะต้องไม่ได้ให้ชัด คำนี้มักซ่อนกลไกสี่แบบที่ให้การรับประกันต่างกันมาก

สแนปช็อตกู้คืนเวอร์ชันที่บันทึกไว้ของแอปหรือพื้นที่ทำงาน สแนปช็อตนั้นอาจรวมโค้ดที่สร้างขึ้น การตั้งค่า และสถานะที่ระบบจัดการบางส่วน ขึ้นอยู่กับผลิตภัณฑ์ แต่ไม่ได้กล่าวอะไรถึงบริการภายนอก เว้นแต่ข้อตกลงของสแนปช็อตจะรวมไว้โดยชัดเจน

Git revert บันทึกคอมมิตใหม่ที่ย้อนการเปลี่ยนแปลงของคอมมิตก่อนหน้า มันซ่อมประวัติซอร์สโดยไม่ลบประวัตินั้น และไม่ได้ติดต่อบริการที่โค้ดเก่าเรียกขณะทำงาน

การกู้คืนฐานข้อมูลเปลี่ยนระเบียนที่เก็บอยู่ในฐานข้อมูล การ rollback ของทรานแซกชันจะทิ้งการเขียนที่ยังไม่ commit ในทรานแซกชันเดียว การกู้คืนจากแบ็กอัปหรือ point-in-time recovery เป็นการดำเนินการที่ใหญ่กว่ามาก ซึ่งพาคลัสเตอร์ฐานข้อมูลย้อนใกล้สถานะก่อนหน้า ทั้งสองแบบไม่กระทบยอดระบบภายนอกฐานข้อมูลโดยอัตโนมัติ

การกระทำชดเชยสร้างผลกระทบใหม่เพื่อลดทอนผลเดิม การคืนเงินชดเชยการรับชำระเงิน คำขอยกเลิกชดเชยคำสั่งซื้อ อีเมลแก้ไขอาจบรรเทาความผิดพลาดของอีเมลเดิมได้ แต่ลบข้อความแรกไม่ได้ การชดเชยยอมรับความจริงที่ไม่สบายใจว่า การกระทำเดิมเกิดขึ้นแล้ว

ผมใช้ตารางความเป็นเจ้าของผลกระทบระหว่างการรีวิวการออกแบบ เพราะมันบังคับให้ตอบอย่างเจาะจง:

การเปลี่ยนแปลงผู้รับผิดชอบการกู้คืนกลไกที่ใช้บ่อยลบผลกระทบเดิมได้หรือไม่?
ซอร์สที่สร้างขึ้นแอปหรือรีโพซิทอรีกู้คืนสแนปช็อตหรือ Git revertโดยทั่วไป สำหรับการรันในอนาคต
แถวที่ commit แล้วผู้ดูแลฐานข้อมูลแก้ไขเชิงตรรกะหรือกู้คืนบางครั้งในระบบภายใน
อีเมลที่ส่งถึงแล้วผู้ให้บริการเมลและผู้รับส่งข้อความติดตามหรือระงับเมลที่ยังค้างไม่ได้
การรับชำระเงินแล้วผู้ประมวลผลการชำระเงินVoid หรือคืนเงินไม่ได้
คำขอ API ภายนอกบริการผู้รับยกเลิกหรือชดเชยตามผู้ให้บริการส่วนใหญ่ไม่ได้

คอลัมน์สุดท้ายสำคัญที่สุด การดำเนินการตรงข้ามไม่ใช่หลักฐานว่าผลเดิมหายไปแล้ว บันทึกตรวจสอบ สำเนาของผู้รับ รายการชำระบัญชี webhook และงานทางกายภาพอาจยังคงอยู่

การ revert โค้ดเปลี่ยนโปรแกรม ไม่ได้เปลี่ยนอดีต

การ revert โค้ดป้องกันหรือเปลี่ยนพฤติกรรมในอนาคต ไม่ได้ย้อนพฤติกรรมที่เวอร์ชันเก่าก่อไว้แล้ว หลักการนี้ใช้เหมือนกันไม่ว่าทีมจะใช้ Git สแนปช็อตแพลตฟอร์ม หรือ deployment rollback

เอกสาร Git อธิบาย git revert ว่าเป็นการบันทึกคอมมิตที่ย้อนการเปลี่ยนแปลงจากคอมมิตก่อนหน้า ถ้อยคำนี้แม่นยำ: Git ใช้แพตช์ตรงข้ามกับเนื้อหาในรีโพซิทอรี Git ไม่รู้เรื่องอีเมล การชำระเงิน ทรัพยากรคลาวด์ ทิกเก็ตซัพพอร์ต หรือ API ของพาร์ตเนอร์ที่สร้างขึ้นตอนคอมมิตที่ถูก revert ทำงาน

สมมติว่า agent แก้ฟังก์ชันเรียกเก็บเงิน ดีพลอย แล้วเรียกใช้สองครั้งก่อนระบบมอนิเตอร์พบข้อบกพร่อง การ revert คอมมิตหยุดไม่ให้ฟังก์ชันผิดพลาดทำงานอีกได้ แต่ยังทิ้งความพยายามชำระเงินสองครั้งไว้ที่ผู้ประมวลผล หากฐานข้อมูลภายในบันทึกไว้เพียงครั้งเดียว การ revert อาจยิ่งทำให้การสืบสวนยากขึ้น เพราะลบเส้นทางโค้ดที่เข้าใจการตอบกลับครั้งที่สอง

Deployment rollback มีขอบเขตเดียวกัน การย้ายทราฟฟิกกลับไปยัง build ก่อนหน้าจะกู้คืนพฤติกรรมที่รันได้ แต่คำขอที่ build ซึ่งถูกแทนที่รับไปแล้วจะยังคงผลของมัน งานในคิวอาจอยู่รอดจากการดีพลอยและทำงานตามสมมติฐานเดิมกับเวอร์ชันที่กู้คืนแล้ว

ก่อน revert ให้เก็บหลักฐานการปฏิบัติงานที่ build เก่าสร้างไว้:

  • Deployment identifier และ source commit
  • Agent run และ intent identifier
  • Queue message identifier และสถานะ lease
  • External request identifier
  • การตอบกลับและเวลาแสตมป์จากผู้ให้บริการ

จากนั้นหยุดการทำงานใหม่ กระทบยอดรายการที่ยังไม่สมบูรณ์ แล้วค่อยกู้คืนโค้ด การ revert ก่อนแล้วค่อยถามคำถาม มักทำลายทางที่ง่ายที่สุดในการเข้าใจว่าผลกระทบใดหลุดออกไป

สแนปช็อตอาจครอบคลุมกว่าคอมมิต Git แต่กฎเดิมยังใช้ ข้อตกลงสแนปช็อตต้องบอกให้ชัดว่ารวมทรัพยากรใดบ้าง หากรวมโค้ดและการตั้งค่า ก็เรียกมันว่ากลไกกู้คืนโค้ดและการตั้งค่า อย่ายกระดับเป็นปุ่มเลิกทำสากลด้วยข้อความในหน้าจอที่อาศัยความหวัง

การกู้คืนฐานข้อมูลมีหน้าที่แคบกว่าที่หลายคนคิด

การกู้คืนฐานข้อมูลกู้คืนสถานะฐานข้อมูล ไม่ใช่ความเป็นจริงทางธุรกิจของผู้เข้าร่วมทุกระบบในทรานแซกชัน ทรานแซกชันอาจเป็น atomic ภายในฐานข้อมูลเดียว ขณะที่การดำเนินการโดยรอบยังแยกอยู่ในหลายระบบ

พิจารณาลำดับนี้:

  1. Agent เพิ่มแถวใบแจ้งหนี้
  2. เรียก payment API
  3. ผู้ประมวลผลรับรายการเรียกเก็บเงิน
  4. การ commit ฐานข้อมูลล้มเหลว

การ rollback ภายในลบแถวใบแจ้งหนี้ แต่รายการเรียกเก็บเงินยังอยู่ การลองดำเนินการทั้งหมดใหม่โดยไม่กระทบยอดอาจเก็บเงินลูกค้าอีกครั้ง นี่คือความล้มเหลวแบบ dual write: แอปพยายามทำให้การกระทำทางธุรกิจหนึ่งเป็น atomic ข้ามระบบที่ไม่ได้ใช้ transaction coordinator ร่วมกัน

การสลับลำดับก็ไม่แก้ปัญหา หากแอป commit ใบแจ้งหนี้ก่อนแล้วการเรียกชำระเงินล้มเหลว ฐานข้อมูลจะมีใบแจ้งหนี้ที่ยังไม่ชำระ สถานะนี้ตรวจสอบง่ายกว่า แต่แอปยังต้องมี state machine ที่แยก payment_pending, payment_confirmed, payment_failed และ payment_unknown

เอกสาร PostgreSQL อธิบาย point-in-time recovery ว่าเป็นการกู้คืน base backup แล้วเล่นซ้ำ write ahead log ไปยังเป้าหมายการกู้คืนที่เลือก นี่เป็นขั้นตอนของผู้ดูแลเพื่อกู้คืนคลัสเตอร์ฐานข้อมูล ไม่ใช่การเลิกทำเฉพาะ agent run หนึ่งครั้ง และสั่งผู้ประมวลผลการชำระเงินหรือบริการเมลให้ย้อนกลับไปเวลาเดียวกันไม่ได้

การพาฐานข้อมูลย้อนกลับอาจทำให้เกิดความไม่ตรงกันรอบสอง ลองนึกถึงการกู้คืนไปที่ 10:00 หลังระบบขัดข้อง ผู้ให้บริการรับคำขอถึง 10:07 แต่ฐานข้อมูลที่กู้คืนไม่มีระเบียนเหล่านั้นแล้ว agent ที่เห็นแถว «หายไป» อาจสร้างงานทั้งเจ็ดนาทีซ้ำ จึงต้องมีกระบวนการกระทบยอดภายนอกก่อนให้ worker กลับมาทำงาน

รูปแบบ outbox ช่วยลดช่องว่างอันตรายจุดหนึ่ง แอป commit การเปลี่ยนแปลงทางธุรกิจและเจตนาของผลกระทบในการทำธุรกรรมภายในเดียวกัน:

BEGIN;

INSERT INTO invoices (invoice_id, customer_id, status)
VALUES ('inv_2048', 'cust_91', 'payment_pending');

INSERT INTO effect_intents
  (intent_id, operation, subject_id, status)
VALUES
  ('eff_7f31', 'capture_payment', 'inv_2048', 'pending');

COMMIT;

จากนั้น worker จะรับ eff_7f31 เรียกผู้ให้บริการด้วยค่า idempotency ที่คงที่ และบันทึกผล outbox ไม่ได้ทำให้การเรียกภายนอกเป็น atomic แต่มอบหลักฐานที่คงอยู่ได้ว่างานนั้นตั้งใจให้เกิด จึงลองใหม่และกระทบยอดได้

การกระทำภายนอกต้องมีการชดเชย และบางอย่างไม่มีทางชดเชย

ผลกระทบภายนอกต้องมีการชดเชยเฉพาะผู้ให้บริการ หรือระบุอย่างชัดเจนว่าไม่มีการชดเชยที่มีความหมาย การถือว่าทุกการกระทำย้อนกลับได้แย่กว่าการยอมรับว่าบางอย่างต้องขออนุมัติ

อีเมลเป็นตัวอย่างง่ายที่สุด ก่อนผู้ให้บริการรับข้อความ แอปอาจยกเลิกงานในคิวได้ หลังรับแล้ว ผู้ให้บริการอาจยกเลิกได้ในช่วงภายในสั้น ๆ แต่ไม่มีการรับประกันเรียกคืนได้ทั่วไปข้ามผู้รับและระบบเมล เมื่อส่งถึงแล้ว ข้อความที่สองแก้ไขข้อมูลได้ แต่ลบข้อความแรกไม่ได้ ข้อมูลอ่อนไหว หนังสือแจ้งทางกฎหมาย และความเสียหายต่อชื่อเสียงยังถูกเปิดเผยอยู่

การชำระเงินมีหลายสถานะที่ทีมมักรวมเป็นคำว่า «ถูกเรียกเก็บแล้ว» การ authorize คือการกันวงเงิน การ capture คือคำขอเคลื่อนย้ายเงินตามการกันวงเงินนั้น Void อาจปล่อยการกันวงเงินที่ยังไม่ชำระบัญชี Refund สร้างรายการการเงินภายหลังเพื่อคืนเงินหลัง capture การดำเนินการเหล่านี้ต่างกันทั้งเวลา ค่าธรรมเนียม สิทธิ์ และผลกระทบต่อลูกค้า เครื่องมือ undo_payment แบบทั่วไปซ่อนข้อมูลที่ agent ต้องใช้เพื่อทำงานอย่างปลอดภัย

API อื่น ๆ อาจจัดการยากกว่า คำขออาจสั่งสินค้า จัดเตรียมโครงสร้างพื้นฐาน เผยแพร่เนื้อหา ให้สิทธิ์ ส่งพัสดุ หรือกระตุ้นให้คนเริ่มงาน Endpoint DELETE ไม่ได้พิสูจน์ว่าย้อนกลับได้ การลบทรัพยากรอาจยังทิ้งบันทึกตรวจสอบ ข้อมูลที่คัดลอก การแจ้งเตือน ทรัพยากรที่พึ่งพา หรือผลทางกายภาพ

จัดประเภทการชดเชยตามสิ่งที่ทำได้จริง:

  • การย้อนกลับภายในแบบตรงตัว ทำให้สถานะที่ควบคุมได้กลับสู่ค่าเดิม
  • การยกเลิกของผู้ให้บริการ หยุดงานที่ยังไม่เสร็จ
  • การชดเชยทางการเงิน สร้างรายการคืนเงินหรือเครดิต
  • การสื่อสารแก้ไข ยอมรับว่าข้อความแรกยังมองเห็นได้
  • การแก้ไขโดยคน จัดการผลกระทบที่บริบทไม่อาจใส่ลงในกฎอัตโนมัติที่ปลอดภัย

การชดเชยก็ล้มเหลวได้ Endpoint คืนเงินอาจหมดเวลา ช่วงเวลายกเลิกอาจปิดลง ที่อยู่ผู้รับอาจปฏิเสธข้อความแก้ไข บัญชีที่ agent ใช้อาจไม่มีสิทธิ์ ดังนั้นระบบต้องติดตามการชดเชยเป็นการดำเนินการอีกแบบ พร้อม intent identifier สถานะ จำนวนครั้ง หลักฐาน และนโยบายอนุมัติของตัวเอง

อย่าสร้างฟีเจอร์ «rollback การ rollback» แบบวนซ้ำ ให้จำลองประวัติเป็นสมุดบัญชีการกระทำ หากการชดเชยก่อข้อผิดพลาดใหม่ ให้ออกการกระทำใหม่อย่างชัดเจนหลังตรวจทานสถานะปัจจุบัน ประวัติจะยาวขึ้น แต่ยังเข้าใจได้ระหว่างเหตุการณ์

Idempotency หยุดการทำซ้ำ แต่ไม่ย้อนความสำเร็จ

วางแผนการเปลี่ยนแปลงที่เสี่ยงให้เร็วขึ้น
วางแผนการเปลี่ยนแปลงใน Koder.ai ก่อนสร้าง เพื่อให้ขอบเขตแอปชัดเจนก่อนดีพลอย

Idempotency ปกป้องการลองใหม่ไม่ให้สร้างผลกระทบตามเจตนาซ้ำ แต่ไม่ได้เลิกทำผลกระทบแรกที่สำเร็จ ทีมมักสับสนสองเรื่องนี้ แล้วพบความต่างหลังเกิด timeout

RFC 9110 นิยาม request method แบบ idempotent ว่าการส่งคำขอเหมือนกันหลายครั้งมีผลตามเจตนาเท่ากับส่งเพียงครั้งเดียว โดยระบุว่า PUT, DELETE และ safe methods เป็น idempotent ในระดับความหมายของโปรโตคอล POST ไม่ได้เป็น idempotent โดยทั่วไป แม้ API จะเพิ่มพฤติกรรม idempotency ผ่านข้อตกลงของตัวเองได้

ข้อจำกัดนี้สำคัญ DELETE ที่เป็น idempotent ยังอาจสร้าง log metric หรือ response ใหม่ทุกครั้ง การทำ idempotency ของผู้ให้บริการอาจหมดอายุ จำกัดตัวระบุไว้ต่อบัญชี ปฏิเสธพารามิเตอร์ที่เปลี่ยน หรือแคชผลลัพธ์เพียงบางชนิด อ่านข้อตกลงของผู้ให้บริการแทนการเดาจาก HTTP verb

effect intent ทุกตัวควรได้รับค่า idempotency ที่คงที่หนึ่งค่า ก่อนความพยายามครั้งแรก การลองใหม่สำหรับ intent เดิมต้องใช้ค่านั้นซ้ำ เจตนาทางธุรกิจใหม่ใช้ค่าใหม่ ห้ามสร้างค่าจากพารามิเตอร์ที่เปลี่ยนได้ เช่น ลูกค้า ยอดเงิน และวันที่ בלבד เพราะการซื้อสองครั้งที่ถูกต้องอาจมีค่าเหล่านี้เหมือนกัน

Timeout คือผลลัพธ์ที่ไม่ทราบ ไม่ใช่ความล้มเหลว ให้ทำตามลำดับนี้:

  1. ทำเครื่องหมายความพยายามเป็น outcome_unknown และอย่าสร้าง intent ทดแทน
  2. ค้นหากับผู้ให้บริการด้วยค่า idempotency หรือข้อมูลอ้างอิงการดำเนินการ
  3. หากผู้ให้บริการยืนยันความสำเร็จ ให้บันทึกความสำเร็จนั้นในระบบภายใน
  4. หากยืนยันว่าไม่มีการดำเนินการ ให้ลองใหม่ด้วยค่าเดิม
  5. หากตอบไม่ได้ ให้พักการดำเนินการไว้เพื่อกระทบยอดหรือให้คนตรวจทาน

รูปแบบคำตอบนี้ให้ข้อมูล agent เพียงพอสำหรับแยกการยอมรับคำขอออกจากความไม่แน่นอนของเครือข่าย:

{
  "intent_id": "eff_7f31",
  "attempt": 2,
  "idempotency_key": "eff_7f31",
  "transport_status": "timeout",
  "provider_status": "unknown",
  "provider_reference": null,
  "next_action": "reconcile"
}

ค่า idempotency ควรถูกส่งต่อผ่าน log ข้อความในคิว header API และ metadata ของผู้ให้บริการเมื่อรองรับ หากผู้ปฏิบัติงานค้นหาด้วยค่านี้ไม่ได้ทั้งสองฝั่งของขอบเขต พวกเขาจะต้องเดาระหว่างการกู้คืน

การอนุมัติควรอยู่ตรงขอบเขตของผลกระทบ

ต้องขออนุมัติหลัง agent สร้างการกระทำภายนอกที่แน่นอนแล้ว และก่อนคำขอที่ย้อนกลับไม่ได้ครั้งแรกออกจากระบบ การอนุมัติตั้งแต่ต้นของงานกว้าง ๆ เปิดช่องให้ agent เปลี่ยนผู้รับ จำนวนเงิน ขอบเขต หรือเครื่องมือภายหลังได้มากเกินไป

«จัดการบัญชีของลูกค้ารายนี้» ไม่ใช่การอนุมัติที่เพียงพอสำหรับตัดบัตรหรือส่งอีเมลถึงผู้ใช้ทุกคน การอนุมัติที่ถูกต้องระบุการดำเนินการจริง: ผู้รับ จำนวนเงินและสกุลเงิน สรุปข้อความหรือ payload บัญชีเป้าหมาย เครื่องมือ เวลาหมดอายุ และจำนวนครั้งที่อนุญาต หากฟิลด์ที่อนุมัติเปลี่ยน การอนุมัตินั้นใช้ไม่ได้อีก

นโยบายที่ดีจัดลำดับผลกระทบตามผลลัพธ์ ไม่ใช่ตาม agent หรือโมเดลที่ร้องขอ การอ่านข้อมูลอาจเปิดเผยข้อมูลส่วนตัว แต่ไม่ก่อปัญหาการกู้คืนแบบเดียวกับการส่งออก การร่างอีเมลอยู่ภายในและย้อนกลับได้ การส่งอีเมลข้ามขอบเขต การสร้างข้อเสนอชำระเงินอยู่ภายใน การตัดเงินข้ามขอบเขต

ต้องขออนุมัติอย่างชัดเจนสำหรับการกระทำที่:

  • เคลื่อนย้ายเงินหรือสร้างภาระทางการเงิน
  • ส่งข้อมูลให้บุคคลหรือองค์กรภายนอก
  • เผยแพร่ ลบ หรือเปิดเผยข้อมูลนอกพื้นที่เก็บข้อมูลที่ควบคุมได้
  • เปลี่ยนตัวตน สิทธิ์ ความเป็นเจ้าของ หรือการตั้งค่าความปลอดภัย
  • เริ่มงานทางกายภาพหรือกระบวนการอื่นที่เรียกคืนได้ไม่แน่นอน

การกระทำซ้ำ ๆ ที่มีผลกระทบต่ำอาจใช้การอนุมัติล่วงหน้าแบบมีขอบเขต ขอบเขตต้องระบุจำนวนเงินสูงสุด กลุ่มผู้รับ เครื่องมือที่อนุญาต เวลาหมดอายุ อัตรา และจำนวนการดำเนินการรวม «อนุมัติสำหรับการเรียกเก็บเงิน» ไม่มีขอบเขตที่บังคับใช้ได้

การอนุมัติต้องป้องกันการนำมาใช้ซ้ำด้วย ผูกมันกับ digest ที่เปลี่ยนไม่ได้ของการดำเนินการ และทำเครื่องหมายว่าใช้แล้วเมื่ออนุญาตให้ทำได้เพียงครั้งเดียว หากผลลัพธ์ไม่ทราบ อย่าขออนุมัติใหม่แล้วสร้าง intent ที่สอง ให้กระทบยอด intent ที่อนุมัติแล้วก่อน

หน้าจออนุมัติควรบอกความจริงเรื่องการกู้คืนด้วยภาษาธรรมดา «ข้อความนี้เรียกคืนไม่ได้หลังส่งถึงแล้ว» มีประโยชน์ ส่วน «การดำเนินการนี้ย้อนกลับได้» ทำให้เข้าใจผิด หากการกู้คืนจริงคือการคืนเงินที่ใช้เวลาและยังอยู่ในรายการทางการเงิน

สัญญาเครื่องมือควรเปิดเผยวงจรชีวิตของผลกระทบทั้งหมด

กู้คืนชั้นแอปพลิเคชัน
ใช้สแนปช็อตและการย้อนกลับเพื่อกู้คืนแอป Koder.ai หลังการเปลี่ยนโค้ดหรือการตั้งค่าที่ผิดพลาด

สัญญาเครื่องมือของ agent ควรอธิบาย intent การดำเนินการ การตรวจสอบ และการชดเชยเป็นงานแยกกัน ฟังก์ชันเดียวที่ทำผลกระทบและคืน success: true ให้หลักฐานน้อยเกินไปสำหรับการลองใหม่ การอนุมัติ หรือการรับมือเหตุการณ์

ส่วนของนโยบายต่อไปนี้เล็กพอจะบังคับใช้ และชัดพอจะรีวิว:

tools:
  send_email:
    effect: irreversible
    approval: required
    idempotency_field: intent_id
    evidence_field: provider_message_id
    compensation: null

  capture_payment:
    effect: compensatable
    approval: required
    idempotency_field: intent_id
    evidence_field: provider_payment_id
    compensation: refund_payment

  update_draft:
    effect: local_reversible
    approval: none
    compensation: restore_version

effect บอก planner ว่าต้องใช้ชั้นการกู้คืนใด approval บล็อกการดำเนินการจนกว่าอาร์กิวเมนต์ที่แน่นอนจะได้รับอนุญาต ฟิลด์ idempotency ทำให้การลองใหม่ใช้ตัวตนเดิม ฟิลด์ evidence บอกผู้ปฏิบัติงานว่าต้องเก็บอะไรไว้ ฟิลด์ compensation ชี้ไปที่เครื่องมือแยกต่างหาก แทนการแสร้งว่าคำขอเดิมรันย้อนกลับได้

การดำเนินการควรรับ envelope ที่เปลี่ยนไม่ได้:

{
  "intent_id": "eff_7f31",
  "operation": "capture_payment",
  "arguments": {
    "invoice_id": "inv_2048",
    "amount_minor": 12900,
    "currency": "USD"
  },
  "approval": {
    "approval_id": "apr_662",
    "scope_hash": "sha256:8b4f...",
    "expires_at": "2026-07-27T18:00:00Z"
  }
}

executor คำนวณ digest ของการดำเนินการ เปรียบเทียบกับ scope_hash ตรวจเวลาหมดอายุ จอง intent แล้วจึงติดต่อผู้ให้บริการ มันเก็บ metadata ของคำขอก่อนเรียก และเก็บการตอบกลับหลังจากนั้น หากล่มระหว่างการเขียนสองครั้ง intent ที่คงอยู่ยังพร้อมให้กระทบยอด

executor ควรปฏิเสธสี่เงื่อนไขโดยไม่ด้นสด: อาร์กิวเมนต์เปลี่ยน การอนุมัติหมดอายุ การนำ intent ไปใช้กับการดำเนินการอื่น และความพยายามชดเชยผลกระทบที่ยังไม่ยืนยันว่าทำสำเร็จ agent เก่งในการหาทางไปต่อที่ฟังดูน่าเชื่อถือ การควบคุมการเงินและการสื่อสารต้องเลือกการหยุดที่มองเห็นได้แทนการเดาที่ดูน่าเชื่อถือ

ให้การตรวจสอบมีเครื่องมือของตัวเอง เช่น get_payment_status(intent_id) การตรวจสอบไม่ควรสร้างผลกระทบ การแยกไว้ทำให้ agent แก้ผลลัพธ์กำกวมได้ โดยไม่ต้องให้สิทธิ์ลองการกระทำเดิมใหม่

การรันที่ล้มเหลวครั้งเดียวข้ามทุกขอบเขตการกู้คืนได้

แยกโฮสติ้งออกจากผลกระทบ
ใช้โดเมนและโฮสติ้งแบบกำหนดเองสำหรับแอป พร้อมเก็บการอนุมัติผลกระทบภายนอกไว้ในสัญญาเครื่องมือ

agent run เดียวอาจทิ้งโค้ด ระเบียนฐานข้อมูล และระบบภายนอกไว้คนละช่วงเวลา การไล่ดูความล้มเหลวนี้ก่อนเปิดใช้งาน จะเผยช่องว่างที่ปุ่ม rollback ทั่วไปซ่อนไว้

สมมติว่า agent สร้างแอปสมาชิก ดีพลอยการเปลี่ยนแปลง นำเข้ารายชื่อลูกค้า เรียกเก็บค่าสมาชิกรายปี และส่งอีเมลต้อนรับ งานดูเหมือนเป็นหนึ่งเดียว แต่ข้ามขอบเขตการกู้คืนอย่างน้อยสี่จุด

เวลา 14:00 agent ดีพลอยโค้ดที่คำนวณค่าธรรมเนียมรายปีจากคอลัมน์ผิด เวลา 14:02 มันเขียน payment intent และฉบับร่างอีเมล 40 รายการลงฐานข้อมูล เวลา 14:03 worker ตัดชำระเงินหลายรายการ เวลา 14:04 ผู้ให้บริการเมลรับข้อความต้อนรับที่มีค่าธรรมเนียมผิด เวลา 14:05 ระบบมอนิเตอร์หยุด worker การเรียกชำระเงินบางรายการ timeout หลังไปถึงผู้ประมวลผล จึงไม่รู้จากสถานะภายในว่าทำสำเร็จหรือไม่

การกู้คืนสแนปช็อตโค้ดเวลา 13:59 หยุดการคำนวณผิดในครั้งต่อไป แต่ไม่เปลี่ยนค่าธรรมเนียมที่คัดลอกไว้ใน intent เดิม Git revert บันทึกการแก้ไขซอร์ส แต่มีขีดจำกัดเดียวกัน

การกู้คืนฐานข้อมูลไปที่ 13:59 จะลบ intent ภายในที่มีข้อมูลอ้างอิงผู้ให้บริการและค่า idempotency ทำให้ความไม่ตรงกันภายนอกแย่ลง การดำเนินการที่ดีกว่าคือการแก้ไขเชิงตรรกะ: เก็บ intent ไว้ ทำเครื่องหมายรายการไม่แน่ชัดเพื่อกระทบยอด และแก้แถวหลังจับคู่กับสถานะผู้ให้บริการแล้วเท่านั้น

จากนั้นทีมรับมือควรดำเนินการตามประเภทผลกระทบ สอบถามการชำระเงินที่ไม่แน่ชัดทุกครั้งด้วยตัวตนการดำเนินการที่คงที่ รายการที่ยืนยัน capture แล้วเข้าสู่การตรวจทานคืนเงิน ความพยายามที่ล้มเหลวยืนยันแล้วปิดโดยไม่ลองใหม่ และรายการที่ยังไม่คลี่คลายจะถูกบล็อก อีเมลที่ส่งถึงแล้วได้รับข้อความแก้ไขซึ่งอนุมัติอย่างรอบคอบ ข้อความในคิวที่ยังไม่ถึงผู้ให้บริการถูกยกเลิก การชดเชยทุกครั้งได้ intent ใหม่ที่เชื่อมกับรายการเดิม

ตัวอย่างนี้ยังแสดงว่าการชดเชยอัตโนมัติอาจอันตราย หากระบบคืนเงินทุกระเบียน payment_unknown ในระบบภายในทันที มันอาจคืนเงินให้รายการที่ไม่เคยเกิด หรือเรียก endpoint คืนเงินด้วยข้อมูลอ้างอิงผิด หากส่งอีเมลทุกฉบับที่ «หายไป» ซ้ำหลังการกู้คืนฐานข้อมูล ผู้รับอาจได้รับข้อความซ้ำ ต้องกระทบยอดก่อนชดเชยทุกครั้งที่สถานะภายในกับผู้ให้บริการไม่ตรงกัน

การรันจะเสร็จสมบูรณ์ก็ต่อเมื่อ intent ทุกตัวถึงสถานะปลายทาง เช่น succeeded, confirmed_failed, compensated หรือ manual_exception «แอปถูก rollback แล้ว» อธิบายเพียงส่วนแรกของเหตุการณ์

การกู้คืนได้ผลก็ต่อเมื่อหลักฐานยังอยู่

การควบคุมการกู้คืนล้มเหลวเมื่อ rollback ลบระเบียนที่จำเป็นต่อการตัดสินว่าเกิดอะไรขึ้น เก็บ effect ledger แบบ append-only ไว้นอกสถานะแอปที่สแนปช็อตหรือการกู้คืนตามปกติอาจเขียนทับได้ และเก็บหลักฐานจากผู้ให้บริการให้พอสำหรับกระทบยอดแต่ละรายการ

ledger ควรบันทึกการสร้าง intent, argument digest, การอนุมัติ, execution lease, ความพยายาม, ผลการส่งผ่าน, ข้อมูลอ้างอิงผู้ให้บริการ, สถานะผู้ให้บริการที่ตรวจพบ และลิงก์การชดเชย จำกัดการเปลี่ยนแปลงให้เป็น state transition แทนการให้ agent เขียนทับรายการเก่า การแก้ไขควรเพิ่ม event ไม่ใช่แก้ประวัติ

เฝ้าดูสถานะที่ยังไม่คลี่คลาย ไม่ใช่แค่ข้อผิดพลาดชัดเจน outcome_unknown ที่ค้างสิบนาทีอาจอันตรายกว่าการถูกปฏิเสธแบบชัดเจน เพราะผู้ปฏิบัติงานอาจลองใหม่ด้วยมือ ให้แจ้งเตือนเมื่อการอนุมัติหมดอายุระหว่างดำเนินการ ค่า idempotency ปรากฏพร้อม argument digest ที่ต่างกัน หรือการชดเชยล้มเหลว

ทำแบบฝึกหัดกู้คืนด้วยจุดล้มเหลวที่จงใจให้ยุ่งยาก หยุด worker หลังผู้ให้บริการรับคำขอ แต่ก่อนบันทึกความสำเร็จในระบบภายใน กู้คืนข้อมูลแอปจากสแนปช็อตก่อนหน้าโดยเก็บ effect ledger ไว้ ให้การอนุมัติหมดอายุระหว่างการวางแผนและการดำเนินการ ทำให้ observation API ใช้งานไม่ได้ แบบฝึกหัดผ่านเมื่อระบบหยุด กระทบยอด และแสดงการตัดสินใจที่ยังไม่คลี่คลายโดยไม่สร้างผลกระทบซ้ำ

เมื่อใช้ Koder.ai ให้ถือว่าสแนปช็อตและ rollback ของมันเป็นชั้นกู้คืนแอป แล้วออกแบบการควบคุมแยกต่างหากสำหรับประวัติฐานข้อมูลและทุกการกระทำภายนอกที่แอปทำได้ การส่งออกซอร์ส การควบคุมดีพลอย และ rollback ช่วยกู้คืนซอฟต์แวร์ ขณะที่สัญญาเครื่องมือของแอปยังรับผิดชอบการอนุมัติและการชดเชย

ปุ่ม rollback ควรบอกขอบเขตไว้ข้างปุ่ม: โค้ด การตั้งค่า ข้อมูลที่ระบบจัดการ หรือผลกระทบภายนอก หากหน้าจอทำให้ประโยคนั้นชัดเจนไม่ได้ ก็ไม่ควรสัญญาว่าจะ rollback ปุ่มที่ซื่อตรงอาจดูวิเศษน้อยกว่า แต่ให้สิ่งที่ทีมรับมือเหตุการณ์ต้องการตอนตีสอง: คำอธิบายที่เชื่อถือได้ว่าอะไรเปลี่ยน อะไรหลุดออกไป และการกระทำใดปลอดภัยที่จะทำต่อไป

คำถามที่พบบ่อย

การย้อนกลับ AI agent ทำให้ยกเลิกส่งอีเมลได้หรือไม่?

ไม่ได้ การย้อนกลับช่วยกู้คืนโค้ดหรือสแนปช็อตแอปที่มีอยู่ก่อนสั่งส่งอีเมลได้ แต่เรียกคืนข้อความที่ผู้ให้บริการอีเมลรับไปแล้วไม่ได้ ระบบจึงต้องมีการอนุมัติก่อนส่ง และเก็บบันทึกการตอบกลับจากผู้ให้บริการไว้อย่างถาวร

การย้อนกลับอัตโนมัติย้อนรายการเรียกเก็บบัตรเครดิตได้หรือไม่?

โดยทั่วไปไม่ได้ การย้อนกลับลบรายการชำระเงินที่ชำระบัญชีแล้วออกจากบันทึกของผู้ประมวลผลไม่ได้ ระบบต้องออกเงินคืนเป็นธุรกรรมการเงินใหม่ การกันวงเงินที่ยังไม่ถูกตัดอาจยกเลิกได้ แต่ก็ยังเป็นการดำเนินการชำระเงินโดยชัดแจ้ง ไม่ใช่การย้อนโค้ด

Git revert ย้อนอะไรได้จริง ๆ?

Git revert สร้างคอมมิตใหม่ที่ใช้การเปลี่ยนแปลงตรงข้ามกับการแก้โค้ดก่อนหน้า มันไม่กู้คืนแถวในฐานข้อมูล ยกเลิกคำขอ API ลบข้อความที่ส่งถึงแล้ว หรือคืนเงิน ให้มองว่าเป็นการซ่อมประวัติซอร์สโค้ดเท่านั้น

การ rollback ฐานข้อมูลย้อนการเรียก API ภายนอกได้หรือไม่?

ทรานแซกชันฐานข้อมูลย้อนการเขียนในระบบภายในที่ยังไม่ commit ได้ หลัง commit การกู้คืนอาจพาฐานข้อมูลกลับไปยังสถานะก่อนหน้า แต่ก็อาจลบการเขียนที่ถูกต้องและไม่เกี่ยวข้อง และย้อนการกระทำในระบบภายนอกไม่ได้ ใช้มันเป็นขั้นตอนกู้คืน ไม่ใช่ปุ่มเลิกทำทุกอย่าง

idempotency key เหมือนกับ rollback หรือไม่?

ไม่ได้ Idempotency ป้องกันไม่ให้การพยายามซ้ำสร้างผลกระทบซ้ำ เมื่อผู้ให้บริการรองรับอย่างถูกต้อง แต่ไม่ได้ยกเลิกคำขอแรกที่สำเร็จ และไม่ได้รับประกันว่าคำขออื่นที่ใช้ตัวระบุเดียวกันจะปลอดภัย

การกระทำใดของ agent ควรต้องมีมนุษย์อนุมัติ?

ต้องขออนุมัติเมื่อการกระทำอาจก่อผลทางกฎหมาย การเงิน ความเป็นส่วนตัว ชื่อเสียง หรือการปฏิบัติงานนอกแอป ตัวอย่างเช่น ส่งข้อความ ตัดชำระเงิน เผยแพร่ข้อมูล เปลี่ยนสิทธิ์ สั่งซื้อสินค้า และเรียก API ที่เริ่มงานทางกายภาพ การอ่านข้อมูลและฉบับร่างในระบบมักไม่ต้องใช้ด่านเดียวกัน

agent ควรบันทึกอะไรบ้างก่อนเรียก API ภายนอก?

บันทึก intent identifier อาร์กิวเมนต์ที่แน่นอน การอนุญาต ขอบเขตการอนุมัติ ค่า idempotency หมายเลขครั้งที่พยายาม ข้อมูลอ้างอิงจากผู้ให้บริการ สถานะการตอบกลับ และสถานะการชดเชย เก็บบันทึกก่อนดำเนินการ แล้วอัปเดตหลังพยายามทุกครั้ง บันทึกล็อกของแอปอย่างเดียวสูญหายได้ง่ายระหว่างการย้อนกลับที่กำลังตรวจสอบ

agent จะลองคำขอที่หมดเวลาใหม่อย่างปลอดภัยได้อย่างไร?

การลองใหม่จะปลอดภัยเมื่อการดำเนินการมี idempotency จริง หรือบริการปลายทางรู้จักค่า idempotency ที่คงที่เท่านั้น การหมดเวลายังไม่ชัดเจน เพราะคำขอแรกอาจสำเร็จแม้ผู้เรียกไม่ได้รับคำตอบ หากทำได้ ให้ค้นหากับผู้ให้บริการด้วยตัวระบุการดำเนินการเดิมก่อนส่งคำขอใหม่

ควรให้การกระทำชดเชยทำงานอัตโนมัติเมื่อใด?

ใช้การชดเชยเมื่อการกระทำภายนอกรองรับผลตรงข้ามที่มีความหมายและนโยบายอนุญาต การคืนเงิน คำขอยกเลิก และข้อความแก้ไขคือการชดเชย เพราะเพิ่มประวัติใหม่แทนการลบประวัติเดิม อย่าทำอัตโนมัติโดยไม่ตรวจสอบ หากอาจสร้างการเรียกเก็บเงิน ข้อความ การเปลี่ยนสิทธิ์ หรือข้อผูกพันทางกฎหมายเพิ่มขึ้น

จะทดสอบความปลอดภัยของ rollback สำหรับเครื่องมือ agent ได้อย่างไร?

ทำแบบฝึกหัดใน staging ที่บังคับให้หมดเวลาหลังผู้ให้บริการรับคำขอ แต่ก่อน agent บันทึกความสำเร็จ ยืนยันว่าระบบกระทบยอดด้วยตัวระบุการดำเนินการ ไม่สร้างรายการซ้ำ และบันทึกการชดเชย นอกจากนี้ให้ทดสอบการอนุมัติที่หมดอายุ อาร์กิวเมนต์ที่เปลี่ยนไป ผู้ให้บริการล่มบางส่วน และการกู้คืนหลังคืนข้อมูลแอปแล้ว

Related posts

ราคา AI app builder ขึ้นอยู่กับว่าสิ่งใดถูกนับเป็นงาน

เปรียบเทียบราคา AI app builder สำหรับ 100 พรอมต์ต่อสัปดาห์ รวมการลองซ้ำและเอเจนต์เบื้องหลัง ด้วยสมุดบันทึกภาระงานเดียวและสูตรต้นทุนที่ชัดเจน

การทดสอบความปลอดภัยด้วย AI แทน SAST, DAST และ pentest ได้หรือไม่?

เรียนรู้ว่าการทดสอบความปลอดภัยด้วย AI พบข้อบกพร่องจริงตรงไหน SAST, DAST และ penetration test โดยมนุษย์ยังเหนือกว่าเรื่องใด และจะรวมทั้งหมดโดยไม่สร้างสัญญาณรบกวนซ้ำซ้อนได้อย่างไร

เปรียบเทียบแพลตฟอร์ม React และ Flutter สำหรับใช้งานจริง

เปรียบเทียบแพลตฟอร์ม React และ Flutter สำหรับใช้งานจริง ทั้งผลลัพธ์โค้ด แบ็กเอนด์ การทดสอบ การปรับใช้ และความเป็นเจ้าของ ก่อนเลือกสแตกปี 2026