ข้ามไปยังเนื้อหาหลัก
OpenAI

11 กุมภาพันธ์ 2569

วิศวกรรม

การใช้วิศวกรรม Harness: การใช้ Codex ในโลกของเอเจนต์

โดย Ryan Lopopolo สมาชิกฝ่ายเทคนิค

กำลังโหลด…

ในช่วงห้าเดือนที่ผ่านมา ทีมของเราได้ทำการทดลอง: สร้างและเผยแพร่เวอร์ชันเบต้าภายในของผลิตภัณฑ์ซอฟต์แวร์ที่ไม่มีการเขียนโค้ดด้วยมือแม้แต่บรรทัดเดียว

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

มนุษย์เป็นผู้ควบคุมทิศทาง เอเจนต์ทำงาน

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

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

เราเริ่มต้นด้วย git repository ที่ว่างเปล่า

คอมมิตแรกใน Repository ที่ว่างเปล่าเกิดขึ้นในช่วงปลายเดือนสิงหาคม 2568

โครงสร้างพื้นฐานเบื้องต้น โครงสร้างของที่เก็บข้อมูล การกำหนดค่า CI กฎการจัดรูปแบบ การตั้งค่าตัวจัดการแพ็กเกจ และเฟรมเวิร์กแอปพลิเคชัน สร้างขึ้นโดย Codex CLI โดยใช้ GPT‑5 โดยมีเทมเพลตที่มีอยู่จำนวนหนึ่งเป็นแนวทาง แม้แต่ไฟล์ AGENTS.md เริ่มต้นที่แนะนำเอเจนต์เกี่ยวกับวิธีการทำงานใน Repository ก็ยังเขียนโดย Codex เอง

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

ห้าเดือนต่อมา Repository ดังกล่าวมีโค้ดอยู่ประมาณหนึ่งล้านบรรทัด ครอบคลุมทั้งตรรกะของแอปพลิเคชัน โครงสร้างพื้นฐาน เครื่องมือ เอกสาร และยูทิลิตี้สำหรับนักพัฒนาภายในองค์กร ตลอดช่วงเวลาดังกล่าว มีการเปิดและผสาน pull request ราว 1,500 รายการ โดยมีทีมขนาดเล็กที่มีวิศวกรเพียงสามคนเป็นผู้ขับเคลื่อน Codex ซึ่งหมายถึงอัตราการประมวลผลเฉลี่ย 3.5 PRs ต่อวิศวกรต่อวัน และที่น่าประหลาดใจคืออัตราการประมวลผลได้เพิ่มขึ้นเมื่อทีมเติบโตขึ้นจนตอนนี้มีวิศวกร 7 คน ที่สำคัญ นี่ไม่ใช่การสร้างผลลัพธ์เพียงเพื่อให้มีผลลัพธ์: ผลิตภัณฑ์นี้ถูกใช้งานโดยผู้ใช้ภายในหลายร้อยคน รวมถึงผู้ใช้ระดับมือโปรที่ใช้งานทุกวัน

ตลอดกระบวนการพัฒนา มนุษย์ไม่เคยมีส่วนร่วมในการเขียนโค้ดโดยตรง กลายเป็นหลักการสำคัญของทีม: ไม่เขียนโค้ดด้วยตนเอง

การกำหนดนิยามใหม่ให้กับบทบาทของวิศวกร

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

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

ในทางปฏิบัติ หมายถึงการทำงานแบบเจาะลึก: การแบ่งเป้าหมายขนาดใหญ่เป็นส่วนประกอบย่อยๆ (การออกแบบ การเขียนโค้ด การตรวจสอบ การทดสอบ ฯลฯ) กระตุ้นให้เอเจนต์สร้างส่วนประกอบย่อยเหล่านั้น และใช้ส่วนประกอบย่อยเหล่านั้นเพื่อปลดล็อกงานที่ซับซ้อนยิ่งขึ้น เมื่อมีบางอย่างล้มเหลว วิธีแก้ไขแทบจะไม่ใช่ “พยายามให้มากขึ้น” เพราะวิธีเดียวที่จะทำให้เกิดความก้าวหน้าคือให้ Codex ทำงาน วิศวกรมนุษย์จึงมักจะเข้ามารับงานและถามว่า ความสามารถอะไรที่ยังขาดอยู่ และเราจะทำให้มันทั้งอ่านเข้าใจได้และบังคับใช้ได้สำหรับเอเจนต์อย่างไร

มนุษย์สื่อสารกับระบบผ่านการเขียนพรอมต์เป็นหลัก โดยวิศวกรจะอธิบายงานที่ต้องการ รันเอเจนต์ขึ้นมา แล้วปล่อยให้ระบบจัดการเปิด Pull Request ให้ เพื่อให้การดำเนินการ PR เสร็จสมบูรณ์ เราได้กำหนดให้ Codex ตรวจสอบการเปลี่ยนแปลงของตนเองในเครื่อง จากนั้นจึงขอให้เอเจนต์อื่นช่วยรีวิวต่อทั้งในเครื่องและบนคลาวด์ พร้อมปรับปรุงตามคำแนะนำเพิ่มเติมจากมนุษย์หรือเอเจนต์อื่น และดำเนินการวนซ้ำไปเรื่อยๆ จนกว่าเอเจนต์ที่รีวิวทั้งหมดจะพอใจ (กระบวนการนี้เรียกว่า Ralph Wiggum Loop(เปิดในหน้าต่างใหม่)) Codex สามารถใช้งานเครื่องมือพัฒนามาตรฐานของเราได้โดยตรง (ไม่ว่าจะเป็น gh, สคริปต์ในเครื่อง หรือทักษะที่ฝังอยู่ใน Repository) เพื่อรวบรวมบริบทที่จำเป็นไม่จำเป็นต้องเสียเวลาคัดลอกและวางข้อมูลลงใน CLI อีกต่อไป

มนุษย์อาจตรวจสอบ pull request แต่ไม่จำเป็นต้องทำก็ได้ เมื่อเวลาผ่านไป เราได้ผลักดันให้ความพยายามในการตรวจทานเกือบทั้งหมดถูกจัดการโดยเอเจนต์ต่อเอเจนต์

การเพิ่มความชัดเจนในการอ่านของแอปพลิเคชัน

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

ตัวอย่างเช่น เราทำให้แอปสามารถบูตได้ตาม git worktree เพื่อให้ Codex สามารถเปิดใช้งานและจัดการอินสแตนซ์หนึ่งต่อการเปลี่ยนแปลงหนึ่งครั้ง เรายังได้เชื่อมต่อ Chrome DevTools Protocol เข้ากับรันไทม์ของเอเจนต์ และสร้างทักษะสำหรับการทำงานกับสแนปช็อต DOM ภาพหน้าจอ และการนำทาง สิ่งนี้ทำให้ Codex สามารถจำลองข้อบกพร่อง ตรวจสอบการแก้ไข และวิเคราะห์พฤติกรรมของ UI ได้โดยตรง

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

เราทำแบบเดียวกันสำหรับเครื่องมือการตรวจสอบระบบ บันทึก เมตริก และร่องรอยสามารถเข้าถึงได้โดย Codex ผ่านสแตกการสังเกตการณ์ในเครื่องที่เป็นแบบชั่วคราวสำหรับแต่ละ worktree Codex ทำงานบนเวอร์ชันของแอปนั้นที่แยกออกจากกันอย่างสมบูรณ์ รวมถึงบันทึกและเมตริก ซึ่งจะถูกลบออกเมื่อทำงานนั้นเสร็จสิ้น เอเจนต์สามารถคิวรีบันทึกล็อกด้วย LogQL และคิวรีตัวชี้วัดด้วย PromQL เมื่อมีบริบทนี้แล้ว พรอมต์ต่างๆ เช่น “ตรวจสอบให้แน่ใจว่าการเริ่มต้นบริการเสร็จสมบูรณ์ภายใน 800 มิลลิวินาที” หรือ “ช่วงเวลาในขั้นตอนการใช้งานที่สำคัญทั้งสี่ขั้นตอนต้องไม่เกินสองวินาที” ก็จะสามารถจัดการได้ง่ายขึ้น

แผนภาพชื่อ “การให้ Codex มีสแต็กการสังเกตการณ์แบบครบชุดในสภาพแวดล้อมการพัฒนาแบบโลคัล” แอปจะส่งบันทึก เมตริก และร่องรอยไปยัง Vector ซึ่งจะกระจายข้อมูลไปยังสแตกการสังเกตการณ์ที่ประกอบด้วย Victoria Logs, Metrics และ Traces โดยแต่ละส่วนจะถูกคิวรีผ่าน API ของ LogQL, PromQL หรือ TraceQL Codex ใช้สัญญาณเหล่านี้ในการสืบค้น เชื่อมโยง และให้เหตุผล จากนั้นจึงดำเนินการแก้ไขในฐานโค้ด รีสตาร์ทแอป รันเวิร์กโหลดซ้ำ ทดสอบการทำงานของ UI และทำซ้ำในวงจรป้อนกลับ

เรามักจะเห็นการรัน Codex แบบเดี่ยวทำงานกับงานเดียวได้นานกว่า 6 ชั่วโมง (บ่อยครั้งในขณะที่มนุษย์กำลังนอนหลับ)

เราได้ทำให้ความรู้ใน Repository เป็นระบบบันทึกข้อมูลหลัก

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

เราได้ลองใช้ “วิธีเก็บทุกอย่างไว้ในไฟล์ AGENTS.md (เปิดในหน้าต่างใหม่)ไฟล์เดียวดูแล้ว” แนวทาง มันล้มเหลวด้วยรูปแบบที่เราคาดการณ์ไว้ได้อยู่แล้ว:

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

ดังนั้นแทนที่จะถือว่า AGENTS.md เป็นสารานุกรม เราถือว่าเป็นสารบัญ

ฐานความรู้ของ Repository อยู่ในไดเรกทอรี docs/ ที่มีโครงสร้างและถือเป็นแหล่งข้อมูลอ้างอิงหลักของระบบ AGENTS.md แบบสั้น (ประมาณ 100 บรรทัด) ถูกแทรกเข้าไปในบริบทและทำหน้าที่หลักเป็นแผนที่ โดยมีตัวชี้ไปยังแหล่งข้อมูลที่ลึกกว่าในที่อื่น

ข้อความธรรมดา

1
AGENTS.md
2
ARCHITECTURE.md
3
docs/
4
├── design-docs/
5
│ ├── index.md
6
│ ├── core-beliefs.md
7
│ └── ...
8
├── exec-plans/
9
│ ├── active/
10
│ ├── completed/
11
│ └── tech-debt-tracker.md
12
├── generated/
13
│ └── db-schema.md
14
├── product-specs/
15
│ ├── index.md
16
│ ├── new-user-onboarding.md
17
│ └── ...
18
├── references/
19
│ ├── design-system-reference-llms.txt
20
│ ├── nixpacks-llms.txt
21
│ ├── uv-llms.txt
22
│ └── ...
23
├── DESIGN.md
24
├── FRONTEND.md
25
├── PLANS.md
26
├── PRODUCT_SENSE.md
27
├── QUALITY_SCORE.md
28
├── RELIABILITY.md
29
└── SECURITY.md

เค้าโครงของคลังความรู้ภายใน Repository

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

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

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

เราบังคับใช้นี้โดยอัตโนมัติ ลินเตอร์เฉพาะทางและงาน CI ตรวจสอบว่าฐานความรู้ทันสมัย เชื่อมโยงข้ามกัน และมีโครงสร้างที่ถูกต้อง เอเจนต์ “doc-gardening” ที่ทำงานเป็นประจำจะสแกนหาเอกสารที่ล้าสมัยหรือไม่สะท้อนพฤติกรรมจริงของโค้ด และเปิด pull request เพื่อแก้ไข

ความชัดเจนในการอ่านของเอเจนต์คือเป้าหมาย

เมื่อโค้ดเบสพัฒนาไป กรอบการตัดสินใจด้านการออกแบบของ Codex ก็จำเป็นต้องพัฒนาไปด้วยเช่นกัน

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

จากมุมมองของเอเจนต์ อะไรก็ตามที่ไม่สามารถเข้าถึงได้ในบริบทขณะทำงาน ก็ถือว่าไม่มีอยู่จริง ความรู้ที่อยู่ใน Google Docs เธรดแชท หรือในความคิดของผู้คน ไม่สามารถเข้าถึงได้โดยระบบ อาร์ติแฟกต์ที่อยู่ใน Repository และมีการกำหนดเวอร์ชัน (เช่น โค้ด, Markdown, Schema, แผนการทำงานที่รันได้) คือทั้งหมดที่สามารถมองเห็นได้

ไดอะแกรมชื่อ “ขีดจำกัดของความรู้ของเอเจนต์: สิ่งที่ Codex มองไม่เห็นก็ไม่มีอยู่จริง” ความรู้ของ Codex ถูกแสดงเป็นฟองที่มีขอบเขตจำกัด ด้านล่างนี้คือตัวอย่างของความรู้ที่ไม่เคยเห็นมาก่อน—Google Docs, ข้อความ Slack และความรู้โดยนัยของมนุษย์ ลูกศรระบุว่าเพื่อให้ Codex มองเห็นข้อมูลนี้ จำเป็นต้องเข้ารหัสข้อมูลนี้ลงในโค้ดเบสเป็น markdown

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

การให้บริบทเพิ่มเติมแก่ Codex หมายถึงการจัดระเบียบและเปิดเผยข้อมูลที่เหมาะสม เพื่อให้เอเจนต์สามารถใช้เหตุผลกับข้อมูลนั้นได้ แทนที่จะทำให้เอเจนต์สับสนด้วยคำสั่งเฉพาะกิจจำนวนมาก ในทำนองเดียวกับที่คุณจะเริ่มงานให้เพื่อนร่วมทีมใหม่เกี่ยวกับหลักการของผลิตภัณฑ์ บรรทัดฐานด้านวิศวกรรม และวัฒนธรรมทีม (รวมถึงความชอบเรื่องอีโมจิด้วย) การให้ข้อมูลนี้กับเอเจนต์จะนำไปสู่ผลลัพธ์ที่สอดคล้องกันมากขึ้น

กรอบนี้ช่วยชี้แจงข้อแลกเปลี่ยนหลายประการ เราให้ความสำคัญกับการพึ่งพาและนามธรรมที่สามารถทำให้เป็นส่วนภายในได้อย่างสมบูรณ์ และสามารถทำความเข้าใจและให้เหตุผลได้ภายในที่เก็บโค้ด เทคโนโลยีที่มักถูกอธิบายว่า “น่าเบื่อ” มักจะทำให้เอเจนต์สร้างโมเดลได้ง่ายกว่า เนื่องจากความสามารถในการประกอบ ความเสถียรของ API และการมีตัวแทนในชุดข้อมูลฝึกอบรม ในบางกรณี การให้เอเจนต์นำชุดย่อยของฟังก์ชันการทำงานกลับไปทำใหม่มีต้นทุนถูกกว่าการหาทางเลี่ยงพฤติกรรมต้นน้ำที่ไม่โปร่งใสจากไลบรารีสาธารณะ ตัวอย่างเช่น แทนที่จะดึงแพ็กเกจสไตล์ p-limitแบบทั่วไปมาใช้ เราได้พัฒนาตัวช่วย map-with-concurrency ของเราเอง: โดยผสานรวมอย่างแนบแน่นกับเครื่องมือ OpenTelemetry ของเรา มีการทดสอบครอบคลุม 100% และทำงานได้ตรงตามที่ระบบของเราคาดหวัง

การดึงส่วนต่างๆ ของระบบให้อยู่ในรูปแบบที่เอเจนต์สามารถตรวจสอบ ตรวจยืนยัน และแก้ไขได้โดยตรง จะเพิ่มอำนาจในการทำงาน ไม่ใช่แค่สำหรับ Codex เท่านั้น แต่ยังรวมถึงเอเจนต์อื่นๆ ด้วย (เช่น Aardvark) ที่กำลังทำงานกับโค้ดเบสด้วยเช่นกัน

การบังคับใช้สถาปัตยกรรมและรสนิยม

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

เอเจนต์จะทำงานได้ดีที่สุดในสภาพแวดล้อมที่มีขอบเขตชัดเจนและโครงสร้างที่คาดเดาได้(เปิดในหน้าต่างใหม่) เราจึงออกแบบแอปพลิเคชันนี้ขึ้นมาโดยยึดตามโมเดลสถาปัตยกรรมที่ค่อนข้างเคร่งครัด แต่ละโดเมนธุรกิจถูกแบ่งออกเป็นเลเยอร์ที่ชัดเจน เราตรวจสอบทิศทางการพึ่งพากันของแต่ละส่วนอย่างเคร่งครัด และควบคุมการเชื่อมต่อต่างๆ ให้อยู่ในขอบเขตที่เรากำหนดไว้ ข้อจำกัดเหล่านี้จะถูกบังคับใช้โดยอัตโนมัติผ่าน Linter ที่ปรับแต่งขึ้นโดยเฉพาะ (ซึ่งแน่นอนว่า Codex เป็นผู้สร้างขึ้น) รวมถึงการทดสอบเชิงโครงสร้างของระบบ

แผนภาพด้านล่างแสดงกฎ: ภายในแต่ละโดเมนธุรกิจ (เช่น การตั้งค่าแอป) โค้ดสามารถพึ่งพาได้เฉพาะแบบ “ไปข้างหน้า” ผ่านชุดเลเยอร์ที่กำหนดตายตัว (Types → Config → Repo → Service → Runtime → UI) ประเด็นสำคัญที่เกี่ยวข้องกับหลายส่วนงาน (การตรวจสอบสิทธิ์ ตัวเชื่อมต่อ ข้อมูลการวัดระยะทาง แฟล็กคุณสมบัติ) จะเข้ามาทางอินเทอร์เฟซเดียวที่กำหนดไว้อย่างชัดเจน นั่นคือ Providers สิ่งอื่นใดนอกเหนือจากนี้ไม่ได้รับอนุญาตและมีการบังคับใช้โดยอัตโนมัติ

แผนภาพชื่อ “สถาปัตยกรรมโดเมนแบบเลเยอร์ที่มีขอบเขตข้ามส่วนที่ชัดเจน” ภายในโดเมนตรรกะทางธุรกิจมีโมดูลดังนี้: Types → Config → Repo และ Providers → Service → Runtime → UI โดยมี App Wiring + UI อยู่ด้านล่าง โมดูล Utils อยู่ภายนอกขอบเขตและป้อนข้อมูลไปยัง Providers

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

ในทางปฏิบัติ เราบังคับใช้กฎเหล่านี้ด้วย linter แบบกำหนดเอง การทดสอบเชิงโครงสร้าง และชุดเล็ก ๆ ของ “ค่าคงที่ด้านรสนิยม” ตัวอย่างเช่น เราบังคับใช้การบันทึกเหตุการณ์แบบมีโครงสร้าง ข้อกำหนดการตั้งชื่อสำหรับ Schema และประเภท ขีดจำกัดขนาดไฟล์ และข้อกำหนดด้านความเชื่อถือได้เฉพาะแพลตฟอร์มด้วยลินต์แบบกำหนดเอง เนื่องจาก linter เป็นแบบกำหนดเอง เราจึงเขียนข้อความแสดงข้อผิดพลาดเพื่อแทรกคำแนะนำในการแก้ไขลงในบริบทของเอเจนต์

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

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

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

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

อัตราการประมวลผลเปลี่ยนหลักการด้านการรวม

เมื่ออัตราการประมวลผลของ Codex เพิ่มขึ้น บรรทัดฐานทางวิศวกรรมแบบดั้งเดิมหลายอย่างกลับกลายเป็นสิ่งที่ไม่เกิดประโยชน์

Repository ทำงานโดยมี merge gate ที่บล็อกน้อยที่สุด Pull request มีอายุการใช้งานสั้น ปัญหาการทดสอบที่ไม่เสถียรมักจะแก้ไขด้วยการรันติดตามผลมากกว่าการหยุดความคืบหน้าไว้ไม่มีกำหนด ในระบบที่อัตราการประมวลผลของเอเจนต์สูงกว่าความสนใจของมนุษย์อย่างมาก การแก้ไขมีต้นทุนต่ำ แต่การรอคอยมีต้นทุนสูง

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

“เอเจนต์สร้างขึ้น” หมายถึงอะไรจริงๆ

เมื่อเรากล่าวว่าโค้ดเบสถูกสร้างโดยเอเจนต์ Codex เราหมายถึงทุกสิ่งในโค้ดเบส

เอเจนต์ผลิต:

  • รหัสผลิตภัณฑ์และการทดสอบ
  • การกำหนดค่า CI และเครื่องมือการปล่อยซอฟต์แวร์
  • เครื่องมือพัฒนาภายใน
  • ประวัติการจัดทำเอกสารและการออกแบบ
  • ฮาร์เนสการประเมิน
  • ทบทวนความคิดเห็นและการตอบกลับ
  • สคริปต์ที่จัดการ Repository เอง
  • ไฟล์นิยามแดชบอร์ดการผลิต

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

เอเจนต์ใช้เครื่องมือพัฒนามาตรฐานของเราโดยตรง โดยดึงความคิดเห็นจากการรีวิว ตอบกลับแบบอินไลน์ ส่งอัปเดต และมักจะ squash และรวม pull request ของตัวเอง

ระดับความเป็นอิสระที่เพิ่มขึ้น

เมื่อมีการเข้ารหัสส่วนต่างๆ ของวงจรการพัฒนาเข้าไปในระบบโดยตรงมากขึ้น อาทิ การทดสอบ การตรวจสอบความถูกต้อง การรีวิว การจัดการฟีดแบ็ก และการกู้คืน เมื่อไม่นานมานี้ Repository ได้ก้าวข้ามเกณฑ์สำคัญที่มีความหมาย ซึ่ง Codex สามารถขับเคลื่อนฟีเจอร์ใหม่ได้ตั้งแต่ต้นจนจบ

เมื่อได้รับคำสั่งเดียว เอเจนต์สามารถทำสิ่งต่อไปนี้ได้แล้ว:

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

พฤติกรรมนี้ขึ้นอยู่กับโครงสร้างและเครื่องมือเฉพาะของ Repository นี้เป็นอย่างมาก และไม่ควรสันนิษฐานว่าจะนำไปใช้ทั่วไปได้โดยไม่ต้องลงทุนในลักษณะเดียวกัน อย่างน้อยก็ยังไม่ใช่ตอนนี้

เอนโทรปีและการจัดการหน่วยความจำ

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

ในช่วงแรก มนุษย์จัดการเรื่องนี้ด้วยตนเอง ทีมของเราเคยใช้เวลาทุกวันศุกร์ (20% ของสัปดาห์) ในการจัดการกับ “AI slop” ไม่น่าแปลกใจเลยที่มันไม่สามารถปรับขนาดได้

เราหันมาใช้การกำหนด “กฎหลักพื้นฐาน” ตั้งแต่ต้น โดยใส่งไว้ใน Repository โดยตรง พร้อมกับวางระบบจัดการสะสางงานส่วนเกินแบบเป็นรอบต่อเนื่อง หลักการเหล่านี้เป็นกฎเชิงกลที่มีมุมมองชัดเจน ซึ่งช่วยให้โค้ดเบสอ่านเข้าใจได้และสอดคล้องกันสำหรับการรันเอเจนต์ในอนาคต ยกตัวอย่างเช่น (1) เราเลือกใช้แพ็กเกจยูทิลิตี้ส่วนกลางแทนการเขียนฟังก์ชันช่วยขึ้นมาเอง (hand-rolled) เพื่อให้เงื่อนไขสำคัญ (invariants) ถูกควบคุมไว้ที่จุดเดียว และ (2) เราไม่เดาสุ่มโครงสร้างข้อมูลแบบ “วัดดวง' (YOLO-style)” แต่เราจะตรวจสอบขอบเขตหรือใช้ SDK ที่ระบุชนิดข้อมูล เพื่อป้องกันไม่ให้เอเจนต์นำโครงสร้างข้อมูลที่คาดเดาไปเองมาสร้างตรรกะต่อ เราวางระบบให้ Codex ช่วยตรวจสอบโค้ดอยู่เบื้องหลังเป็นระยะๆ เพื่อดูว่ามีจุดไหนที่ไม่ตรงตามกฎหลักไหม พร้อมทั้งประเมินคะแนนคุณภาพ และส่งรายการขอแก้ไขโค้ดในส่วนที่ต้องปรับปรุงให้ทันที รายการแก้ไขส่วนใหญ่สามารถตรวจสอบเสร็จได้ภายในเวลาไม่ถึงนาที และระบบจะทำการรวมโค้ดให้โดยอัตโนมัติ

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

สิ่งที่เรายังคงเรียนรู้

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

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

สิ่งที่ชัดเจนคือ การสร้างซอฟต์แวร์ยังคงต้องการวินัย แต่ตอนนี้วินัยนั้นปรากฏในโครงสร้างรองรับมากกว่าตัวโค้ด เครื่องมือ การทำให้เป็นนามธรรม และวงจรข้อเสนอแนะที่ทำให้ฐานรหัสมีความสอดคล้องกันมีความสำคัญมากขึ้นเรื่อยๆ

ความท้าทายที่ยากที่สุดของเราในตอนนี้มุ่งเน้นไปที่การออกแบบสภาพแวดล้อม วงจรป้อนกลับ และระบบควบคุม ที่ช่วยให้ตัวแทนบรรลุเป้าหมายของเรา: การสร้างและบำรุงรักษาซอฟต์แวร์ที่ซับซ้อนและเชื่อถือได้ในขนาดใหญ่

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

ผู้เขียน

Ryan Lopopolo

การรับทราบ

ขอขอบคุณเป็นพิเศษแก่ Victor Zhu และ Zach Brock ที่มีส่วนร่วมในบทความนี้ รวมถึงทีมงานทั้งหมดที่ร่วมกันสร้างผลิตภัณฑ์ใหม่นี้