Bỏ qua đến nội dung chính

Harness Engineering: How to Build Software When Humans Steer, Agents Execute — Ryan Lopopolo, OpenAI

TL;DR

  • Phát triển phần mềm đang chuyển đổi mạnh mẽ, với các tác nhân AI dần thay thế việc viết và bảo trì mã, khiến "mã là miễn phí". Điều này đòi hỏi kỹ sư phần mềm phải chuyển trọng tâm từ lập trình trực tiếp sang tư duy hệ thống và ủy quyền công việc cho AI.
  • "Kỹ thuật điều khiển" (harness engineering) trở thành kỹ năng cốt lõi, tập trung vào việc định nghĩa rõ ràng công việc tốt, xây dựng hàng rào bảo vệ và cung cấp tài liệu chi tiết để hướng dẫn các tác nhân hoạt động hiệu quả.
  • Để thành công, cần tối ưu hóa môi trường cho tác nhân, triển khai các tác nhân đánh giá liên tục, sử dụng các linter chuyên biệt, và coi lời nhắc (prompts) là công cụ điều khiển chính, thậm chí sử dụng tác nhân để tạo lời nhắc.

Điểm chính

  • Chuyển đổi vai trò kỹ sư: Kỹ sư phần mềm trở thành "kỹ sư cấp cao", tập trung vào thiết kế hệ thống, kiến trúc, và ủy quyền công việc cho tác nhân, thay vì viết mã trực tiếp.
  • Mã là tài nguyên dồi dào: Coi việc tạo, tái cấu trúc và xóa mã là miễn phí và dồi dào nhờ AI, cho phép giải quyết các tác vụ ưu tiên thấp (P3) một cách song song mà trước đây thường bị bỏ qua.
  • Ưu tiên tài liệu rõ ràng: Xây dựng tài liệu chi tiết, từ Architecture Decision Records (ADRs), nhật ký lịch sử, đến các định nghĩa về "công việc tốt" và yêu cầu phi chức năng (non-functional requirements), để làm ngữ cảnh và hướng dẫn cho tác nhân.
  • Cấu trúc mã cho tác nhân: Điều chỉnh cơ sở mã (codebase) để dễ đọc và dễ hiểu đối với tác nhân, tối ưu hóa việc sử dụng cửa sổ ngữ cảnh (context window) bằng cách giới hạn độ dài tệp và duy trì sự nhất quán.
  • Triển khai tác nhân đánh giá và linter: Sử dụng các tác nhân đánh giá tự động (ví dụ: về bảo mật, độ tin cậy) và các linter chuyên biệt để thực thi các yêu cầu phi chức năng và tiêu chuẩn mã hóa một cách liên tục trong quy trình CI/CD.
  • Tối ưu hóa kỹ thuật lời nhắc: Lời nhắc là công cụ điều khiển chính. Kỹ sư cần đầu tư vào việc tạo ra các lời nhắc chi tiết, hiệu quả, thậm chí sử dụng tác nhân để tự động tạo và cải tiến các lời nhắc khác.
  • Tạo phản hồi liên tục: Cung cấp thông báo lỗi rõ ràng và các bước khắc phục cụ thể để tác nhân và con người biết cách tiếp tục, giúp tác nhân tự học và giảm sự can thiệp của con người.

Từ vựng

  • harness engineering — kỹ thuật điều khiển
  • agent — tác nhân
  • token — mã thông báo
  • model — mô hình
  • operationalize — vận hành hóa
  • codebase — cơ sở mã
  • non-functional requirements — yêu cầu phi chức năng
  • prompt — lời nhắc
  • guardrails — hàng rào bảo vệ
  • context window — cửa sổ ngữ cảnh

Nội dung chi tiết

Giới thiệu: Kỹ thuật Điều khiển trong Phát triển Phần mềm với Tác nhân

Diễn giả sẽ trình bày về harness engineering (kỹ thuật điều khiển): cách xây dựng phần mềm khi con người dẫn dắt và các tác nhân thực thi. Xin mời chào đón Ryan LePopolo, Thành viên Ban Kỹ thuật tại OpenAI, lên sân khấu. Chào buổi sáng, London!

Tầm nhìn về Kỹ sư Phần mềm Tác nhân và Tương lai AGI

Tôi rất vui khi có mặt ở đây hôm nay. Tôi là Ryan LePopolo, và trong chín tháng qua, tôi đã có vinh dự xây dựng phần mềm độc quyền bằng các tác nhân. Tôi là một "tỷ phú mã thông báo", và tôi tin rằng để chúng ta đạt được tương lai AGI, chúng ta muốn mọi người đều trở thành "tỷ phú mã thông báo", sử dụng các mô hình để hoàn thành toàn bộ công việc. Điều đó có nghĩa là phải tin tưởng vào ý tưởng rằng các mô hình có khả năng trở thành một kỹ sư phần mềm hoàn chỉnh. Tôi đã trải nghiệm điều đó bằng cách cấm nhóm của mình không được chạm vào trình soạn thảo của họ, mà phải làm việc thông qua các mô hình để hoàn thành công việc. Hôm nay, tôi sẽ nói một chút về ý nghĩa của việc tin tưởng vào điều đó và vận hành hóa cách bạn làm việc, các code space bạn đang sử dụng, và các quy trình trong nhóm của bạn để các tác nhân hoàn thành toàn bộ công việc.

Sự Thay Đổi trong Phát triển Phần mềm: Mã là Miễn phí

Tôi tin rằng tôi đang nói với những người đã hiểu rõ khi tôi nói rằng cách chúng ta xây dựng phần mềm đã thay đổi. Trong sáu tháng qua, chúng ta đã chứng kiến các tác nhân lập trình chiếm lĩnh thế giới, và khả năng đã liên tục phát triển với tốc độ siêu nhanh để các mô hình này và các harness mà chúng tồn tại, thực hiện các hành động phức tạp hơn, làm việc khó khăn hơn với độ tin cậy cao hơn trong thời gian dài hơn.

Điểm chúng ta đã đạt đến ở đây là implementation không còn là tài nguyên khan hiếm trong công việc kỹ thuật phần mềm. là miễn phí. Chúng ta có rất nhiều để giải quyết các vấn đề mà chúng ta gặp phải hàng ngày khi điều hành các nhóm, xây dựng phần mềm và giải quyết vấn đề của người dùng. Việc tuyển dụng những người trực tiếp lập trình vào các nhóm của chúng ta chỉ bị giới hạn bởi dung lượng GPUngân sách mã thông báo. Mỗi kỹ sư hôm nay trong căn phòng này đều có quyền truy cập vào năng lực tương đương 5, 50, hoặc 5.000 kỹ sư, 24/7, mọi ngày trong năm. Điều duy nhất cần xảy ra là tìm cách triển khai hiệu quả các tài nguyên này vào và vào các nhóm của chúng ta để tận dụng năng lực mới này. Và trong thế giới này, các kỹ năng đang dịch chuyển nhiều hơn về tư duy hệ thống, thiết kế hệ thốngủy quyền để tận dụng năng lực dồi dào này để tạo giải quyết vấn đề.

Khoảnh Khắc Ma Thuật: GPT 5.2 và Giải phóng Mã Nguồn

Có ba lý do dẫn đến sự thay đổi này, tất cả đều xảy ra vào cuối năm 2025. Đối với tôi, khoảnh khắc kỳ diệu là GPT 5.2, khi nó ra mắt đã có thể đảm nhận toàn bộ công việc của một kỹ sư phần mềm. Các mô hình tại thời điểm này đủ tốt để chúng đồng hình với bạn và tôi về khả năng tạo ra chất lượng cao, giải quyết các vấn đề thực tế của người dùng trong các cơ sở mã thực.

là miễn phí, và tôi biết điều này có thể đáng sợ khi nghe, bởi vì mang theo gánh nặng bảo trì, nhưng nó miễn phí để sản xuất, miễn phí để tái cấu trúc, và không còn là điều phải bận tâm nữa. Chúng ta coi là gánh nặng vì nó đòi hỏi sự chú ý đồng bộ từ các kỹ sư con người trong nhóm của chúng ta. Nhưng các mô hình cực kỳ kiên nhẫn, chúng song song vô hạn, vì vậy khả năng sản xuất, bảo trì, tái cấu trúc và xóa không còn là yếu tố ép buộc trong việc tìm cách phân bổ tài nguyên cho các nhóm kỹ thuật của bạn. Vì vậy, để "thấm nhuần AGI" ở đây là tin rằng các mô hình có khả năng tạo ra mọi dòng mà chúng ta có thể cần. Việc tìm ra khi nào nên xóa chúng, khi nào nên tái cấu trúc chúng hoặc làm cho chúng đáng tin cậy hơn, và vai trò của bạn với tư cách là kỹ sư phần mềm là tìm cách gỡ bỏ các rào cản cho nhóm tác nhân và con người điều khiển các tác nhân đó, để họ có thể thực hiện công việc trên các dự án dài hạn và hoàn thành toàn bộ công việc.

Vai trò của Kỹ sư Cấp cao và Tài nguyên Khan hiếm

Ý tưởng ở đây là mỗi người trong số các bạn đều là một kỹ sư cấp cao. Bạn có thể điều khiển số lượng thành viên nhóm cùng lúc và có đủ mã thông báo để hỗ trợ. Bạn cần nhìn xa hơn một ngày, một tuần, sáu tháng vào tương lai để tìm ra những cấu trúc cần thiết để khai thác hiệu quả năng lực vô hạn này trong việc tạo .

Các tài nguyên khan hiếm trong thế giới chúng ta thấy ngày nay là ba thứ: thời gian con người, sự chú ý của con người và mô hình, và cửa sổ ngữ cảnh của mô hình. Trong thế giới mà thời gian và sự chú ý của con người là khan hiếm, vai trò là nghĩ về nơi thời gian đó đang được sử dụng, tìm cách tự động hóa hiệu quả và chuyển thời gian đồng bộ của con người đó vào các hoạt động có đòn bẩy cao hơn.

Trong một thế giới mà thời gian con người là khan hiếm và thời gian con người là cần thiết để sản xuất , chúng ta có một thứ hạng ưu tiên. Mọi thứ hoặc là p zero (ưu tiên cao nhất) hoặc p two, những p three (ưu tiên thấp) đó sẽ không bao giờ được hoàn thành. Tuy nhiên, trong một thế giới mà là miễn phí và dồi dào vô hạn, tất cả những p three đó sẽ được khởi động ngay lập tức, có thể là 4 lần song song, chúng ta chọn một cái giải quyết vấn đề và nó đi vào hoạt động.

Tôi đã có vinh dự xây dựng rất nhiều tác nhân nội bộ tại OpenAI để cải thiện năng suất của đồng nghiệp. Khi là miễn phí, tất cả những công cụ nội bộ này có thể có bản địa hóaquốc tế hóa tốt ngay từ đầu. Tôi có thể tạo công cụ mà các đồng nghiệp của tôi ở London, Dublin, Paris, Brussels, Zurich và Munich có thể trải nghiệm bằng ngôn ngữ bản địa của họ mà không thực sự phải đánh đổi với bất kỳ năng lực nào khác của nhóm tôi để tạo ra công cụ chất lượng cao. Chúng ta nên làm việc với giả định rằng những phần tốt nhất của kỹ thuật phần mềm mà tất cả chúng ta đều biết, sống và hít thở, luôn có sẵn trong bất kỳ sản phẩm nào mà chúng ta có thể xây dựng.

Tập trung vào Lời nhắc và Hàng rào bảo vệ

Con người không còn cần phải quan tâm đến implementation. Điều quan trọng không phải là , mà là lời nhắchàng rào bảo vệ đã giúp bạn đạt được nó. Đây là lý do tại sao việc để lại breadcrumbs, tài liệu, ADR (Architecture Decision Records), tài liệu định hướng persona về một công việc tốt trông như thế nào, tất cả các nhật ký lịch sử của các ticketđánh giá mã – đây chính là quy trình đã đưa bạn và các nhóm của bạn đến với và các sản phẩm bạn có ngày nay.

Và đây là điều cần phải xảy ra để các tác nhân của bạn cũng đạt được điều đó. Công việc của bạn là xây dựng các hệ thống, phần mềmcấu trúc cho phép nhóm của bạn thành công. Và để làm điều đó, chúng ta cần làm cho chúng dễ đọc (legible) đối với các tác nhân đang thực hiện implementation. Điều đó có nghĩa là cấu trúc chúng theo cách tự nhiên đối với các tác nhân, viết chúng theo cách tôn trọng ngữ cảnh khan hiếm, một tài nguyên khan hiếm khác ở đây. Và tìm ra cách để làm cho số lượng mã thông báo cần thiết để thực hiện công việc dễ dự đoán. Điều đó có nghĩa là làm mọi thứ càng giống nhau càng tốt để chúng ta có thể hạn chế lượng sự chú ýmô hình cần kích hoạt để thực hiện công việc.

Tái cấu trúc quy mô lớn trong thế giới này là miễn phí. Vì vậy, việc làm mọi thứ giống nhau là điều mà tất cả các bạn đều có thể làm. Sẽ không bao giờ có một quá trình di chuyển (migration) bị đình trệ trong sáu tháng vì bạn không thể khiến những phần cuối cùng của cơ sở mã hoàn thành nữa. Bởi vì bạn có thể chỉ cần khởi tạo 15 tác nhân để thúc đẩy công việc đó hoàn thành. Đây là ý nghĩa của một quá trình di chuyển, phải không? Chúng ta có thể hoàn thành chúng ngay bây giờ. Thôi nào, tốt lắm. Tốt lắm. Vỗ tay.

Định nghĩa "Công việc Tốt" cho Tác nhân

Có một câu hỏi siêu nhận thức luận ở đây về ý nghĩa của việc làm tốt công việc. Và làm tốt công việc với tư cách là một kỹ sư phần mềm là khó. Nó đòi hỏi chúng ta nhiều năm trong ngành để hoàn toàn nội hóa ý nghĩa của việc viết chất lượng cao, dễ bảo trì, đáng tin cậy mà các đồng đội của chúng ta có thể xây dựng dựa trên đó, và sẽ tạo đòn bẩy cho cơ sở mã. Để thực hiện tốt một bản vá duy nhất có lẽ cần 500 quyết định nhỏ trên đường đi xung quanh các yêu cầu phi chức năng chưa được chỉ định rõ ràng góp phần tạo ra tốt.

Các tác nhân, các mô hình trong quá trình huấn luyện của chúng đã thấy hàng nghìn tỷ dòng mã đã đưa ra mọi lựa chọn có thể về những yêu cầu phi chức năng mà bạn có thể tưởng tượng. Vì vậy, công việc của chúng ta là chỉ định những yêu cầu phi chức năng đó, viết chúng ra theo cách mà các tác nhân có thể thấy đây là một công việc tốt, chấp nhận được, sẽ tạo ra một bản vá đã hợp nhất. Và nếu các tác nhân không làm được điều đó, công việc của chúng ta là tìm cách tinh chỉnh và hạn chế đầu ra của chúng sao cho chúng viết là chấp nhận được. Bạn có thể chỉ đơn giản nói "đừng tạo ra sản phẩm cẩu thả". "Đừng chấp nhận sản phẩm cẩu thả". Bạn sẽ không nhận được sản phẩm cẩu thả trong cơ sở mã của mình.

Nhưng để làm điều đó đòi hỏi phải chấp nhận sụt giảm tốc độ ngắn hạn để lùi lại hoặc đi sâu vào một tác vụ để tìm hiểu xem các tác nhân đang gặp khó khăn gì trong môi trường của bạn. Đặt hàng rào bảo vệ vào đúng vị trí để chúng ngừng mắc những lỗi đó, sau đó tìm cách lùi lại và dành thời gian của bạn cho các hoạt động có đòn bẩy cao hơn sau khi bạn giải quyết một số rào cản trong thời gian ngắn.

Nâng cao Năng lực Nhóm thông qua Tài liệu và Kiến thức chia sẻ

Khi tôi nghĩ về việc trao quyền cho nhóm của mình theo cách này, mọi người đều là chuyên gia trong lĩnh vực họ mang lại. Tôi có một nhóm full stack đa dạng gồm các chuyên gia về kiến trúc front-end, khả năng mở rộng back-end, tư duy hướng sản phẩm, và mỗi persona khác nhau đó làm phong phú thêm bộ kỹ năng của nhóm tôi bằng cách mang lại một hiểu biết khác, một bộ giải pháp khác cho các yêu cầu phi chức năng đó. Việc khuyến khích các đồng đội viết những điều đó ra thực sự có nghĩa là mỗi kỹ sư điều khiển tác nhân sẽ nhận được những gì tốt nhất từ mỗi cá nhân trong nhóm của tôi. Tôi không cần phải chờ đợi các đánh giá mã tín hiệu thấp để học cách viết một kế hoạch QA tốt. Để một kỹ sư trong nhóm của tôi ghi lại điều đó một cách bền vững có nghĩa là mọi quỹ đạo tác nhân sẽ có một kế hoạch QA tốt, và chúng ta có thể làm điều này một lần theo cách có đòn bẩy cao mà chúng ta có thể xây dựng dựa trên.

Công cụ và Kỹ thuật để Tối ưu hóa Hiệu suất Tác nhân

Vậy làm thế nào để chúng ta khiến các tác nhân làm tốt công việc? Chúng ta có những công cụkỹ thuật nào để về cơ bản là prompt eject các tác nhân của mình và liên tục nhắc nhở chúng về ý nghĩa của việc đưa ra những lựa chọn cụ thể mà chúng ta mong đợi xoay quanh các yêu cầu phi chức năng đó.

Có nhiều cách để làm điều này. Chúng ta có thể viết các tệp agents.md tốt. Tuy nhiên, với nén ngữ cảnh tự động (auto compaction), một thứ đã tiếp tục được cải thiện, GPT 5.4Codex rất tuyệt vời trong việc nén ngữ cảnh tự động. Về cơ bản, tôi không bao giờ phải viết /new nữa. Tôi có một số hình ảnh trên Twitter về việc tôi buộc máy tính xách tay của mình vào ghế sau xe ô tô để tôi có thể tiếp tục chạy suy luận (running inference) khi đang đi lại từ và đến nơi làm việc. Và trong thế giới này, bạn phải xây dựng theo kỳ vọng rằng ngữ cảnh sẽ bị phân trang (paged out) theo thời gian. Chúng ta cần liên tục làm mới ngữ cảnh khi tác nhân thực hiện một tác vụ.

Và cách chúng ta có thể làm điều đó là bằng cách có các tác nhân đánh giá (reviewer agents) xem xét trên đường đi thông qua lăng kính của sự thành công. Đúng vậy. Chúng ta có các tác nhân đánh giá bảo mậtđộ tin cậy trong cơ sở mã của mình, chúng liên tục chạy như một phần của mỗi lần pushCI (Continuous Integration) để xem xét các tài liệu đó và bản vá đề xuất và thực hiện những việc đơn giản như kiểm tra xem có thời gian chờ (timeouts) và thử lại (retries) trên đoạn mã mạng này không, liệu được giới thiệu có một giao diện an toàn (secure interface) không thể bị lạm dụng không. Tôi chắc chắn mọi người ở đây đã từng bị thông báo (paged) vào một thời điểm nào đó vì mã mạng lỗi trong sản xuất gây ra một sự cố ngừng hoạt động (outage) mà có thể đã được khắc phục bằng một thử lại trong một thời gian chờ. Và tôi biết tôi có lỗi khi đặt thử lạithời gian chờ vào, hợp nhất bản sửa lỗi và bỏ qua rằng tôi không phải là một người đánh giá hoặc tác giả mã đáng tin cậy đối với yêu cầu phi chức năng này.

Tuy nhiên, dành thời gian để viết một số tài liệu, viết một linter chuyên biệt cho cơ sở mã của tôi sẽ kiểm tra mỗi khi tôi gọi fetch để đảm bảo rằng có một thử lạithời gian chờ được bọc xung quanh nó, có nghĩa là tôi đã giải quyết vấn đề này một cách bền vững và tôi có thể làm điều đó vì tôi dựa vào tiên đề này rằng là miễn phí, rằng các tác nhân có thể làm tốt công việc, rằng tôi có thể hoàn toàn di chuyển cơ sở mã để giải quyết vấn đề này một cách bền vững một lần và mãi mãi. Và để hoạt động theo cách này, chúng ta cần lùi lại và xem xét các loại lỗi bền vững mà các tác nhâncon người trong cơ sở mã đang mắc hết lần này đến lần khác, tìm ra lý do tại sao chúng ta dành thời gian cho nó, đề ra một giải pháp để loại bỏ loại hành vi sai trái này một cách có hệ thống, sau đó tiếp tục quan sát, tinh chỉnh và đưa ra các lựa chọn bổ sung về các yêu cầu phi chức năng đó.

Tối ưu hóa Ngữ cảnh và Kiểm thử Mã nguồn

Một mẹo rất hay mà tôi sử dụng ở đây là bạn có thể viết các bài kiểm thử về source code cũng như các bài kiểm thử riêng biệt với lints. Nếu chúng ta biết rằng ngữ cảnh bị giới hạn, chúng ta có thể viết một bài kiểm thử giới hạn việc các tệp không dài quá 350 dòng. Chúng tôi đang điều chỉnh codebase của mình cho phù hợp với harness và các mô hình để thực hiện một chút công việc engineering nhằm tối ưu hóa ngữ cảnh và khai thác tối đa năng lực mô hình mà chúng tôi có hiện tại.

Những điều khác chúng ta có thể cân nhắc là cung cấp các thông báo lỗi tốt, đưa ra các bước khắc phục thực tế cho mô hình và con người biết cách tiếp tục. Không đủ chỉ nói rằng chúng ta có một lỗi lint vì chúng ta đang chờ trong một vòng lặp hoặc chúng ta có một giá trị unknown ở phần sâu này của codebase và tại sao mô hình lại viết một hàm tên là is record. Điều chúng ta cần làm là cung cấp một lời nhắc thông qua một lint hoặc một lỗi kiểm thử rằng, "Không, không, không, bạn không nên có một giá trị unknown ở đây vì chúng ta parse, không validateedge, và bạn chắc chắn có một type ở đây được lấy từ cơ sở hạ tầng chịu tải ZOT cho tương lai AI của chúng ta." Bạn có thể chỉ cần lời nhắc mọi thứ; tất cả những gì tôi đã nói hôm nay đều là một lời nhắc. Bạn có thể làm điều này mà không cần chạm vào model weights chút nào.

Sức mạnh của Lời nhắc và Kỹ thuật Tác nhân

Một sự đi chệch hướng khá thú vị ở đây là dường như mỗi tiến bộ mà chúng ta đạt được trong độ phức tạp của cách chúng ta viết để tương tác với các mô hình này đều đến từ cả việc tăng năng lực của mô hình và những cách ngày càng ngách hơn để đưa lời nhắc vào các mô hình đó. Lời nhắc, tôi chắc bạn đã biết, là lời nhắc sức mạnh, lời nhắc tập tin quy tắc, lời nhắc kỹ năng, lời nhắc các thông báo lỗi lint mà tôi đang nói đến, lời nhắc tác nhân đánh giá. Điều đó chèn bình luận vào PR mà chúng ta yêu cầu tác nhân phải giải quyết trước khi có thể đề xuất để merge. Lời nhắc. Bạn sẽ tìm thấy rất nhiều cách để chèn lời nhắc vào của mình, và một cách bạn có thể làm điều đó là nhúng Agent SDKs vào các bài kiểm thử của bạn. Chúng sẽ xem xét codebase để đảm bảo tính chấp nhận được bằng cách sử dụng các lời nhắc được nhúng vào .

Và nếu tôi thấy mình dành quá nhiều thời gian để viết lời nhắc, chúng tôi thực sự có thể giao việc đó cho tác nhân. Tôi đã hướng Codex đến tất cả các sách hướng dẫn tạo lời nhắc mà chúng tôi có trên hướng dẫn dành cho nhà phát triển OpenAI và yêu cầu nó tổng hợp một kỹ năng từ chúng về cách viết lời nhắc. Điều này có nghĩa là, khi tôi cần viết lời nhắc để cải thiện hiệu suất tác nhân của mình tại chỗ trong , tôi sử dụng kỹ năng để viết các lời nhắc mà tôi đã viết cùng với tác nhân xem xét các lời nhắc để viết các lời nhắc.

Tất cả đòn bẩy mà bạn đang mã hóa vào kho lưu trữ của bạn, nhóm của bạn, và các tác nhân theo cách này tích lũy cực kỳ tốt để quay lại ý tưởng rằng một kỹ sưtư duy sản phẩm duy nhất trong nhóm của tôi đã có thể mang lại cho chúng tôi một sự thúc đẩy lớn. Họ biết ý nghĩa của việc viết một kế hoạch QA tốt. Tuy nhiên, để viết một kế hoạch QA tốt, bạn phải ghi lại tất cả các tính năng mà bạn có, các hành trình người dùng quan trọng, và cách người dùng tương tác với các ứng dụng, ứng dụng web, Giao diện lập trình ứng dụngdịch vụ của bạn. Một khi bạn đã viết ra cách để tạo một kế hoạch QA tốt với mong đợi rằng tất cả các công việc hướng tới người dùng đều có một kế hoạch QA, giờ đây một tác nhân đánh giá có thể khẳng định các mong đợi về ý nghĩa của việc chứng minh rằng bạn đã viết tính năng một cách hiệu quả. Một kế hoạch QA chỉ ra phương tiện nào nên được đính kèm vào PR để con người và tác nhân biết rằng bạn đã làm tốt công việc, điều này dẫn đến việc tôi tin tưởng đầu ra hơn, ít cần phải giám sát tác nhân hơn. Và loại bỏ bản thân khỏi vòng lặp nhiều hơn nữa để ủy quyền ngày càng nhiều công việc cho các tác nhân. Tất cả điều này chỉ nhằm đảm bảo các tác nhâncông cụ, mã thông báo, và ngữ cảnh để hoàn thành toàn bộ công việc, loại bỏ tôi khỏi vai trò là một người điều khiển đồng bộ. Các mô hình khao khát mã thông báo. Chúng ta có thể vận hành codebase của mình để cung cấp cho chúng mã thông báo, thúc đẩy chúng tiến lên bằng cách sử dụng các tác nhân con và tất cả các kỹ thuật khác để tinh chỉnh đầu ra tác nhân.

Tôi rất vui được cho tất cả các bạn biết hôm nay, theo cách mà tất cả các bạn làm, rằng bạn có thể cứ thế mà xây dựng mọi thứ. Đừng ngần ngại loại bỏ bản thân khỏi vòng lặp bằng cách để các tác nhân hoàn thành toàn bộ công việc, bởi vì chúng có thể làm được. Cảm ơn bạn.

Giới thiệu Khách mời và Tầm nhìn về Mã thông báo

Rất vui được giới thiệu khách mời của chúng ta. Hôm nay chúng ta có Ryan the Ppop-alow, người vừa phát biểu keynote. Một diễn giả rất thú vị. Anh ấy là một người hyper-engineering hết mình tại OpenAI. Một chút thông tin cơ bản: Chúng tôi đã có một tập latent space với anh ấy; chúng tôi đã phát hành nó mấy hôm trước. Câu chuyện là anh ấy đã viết một bài báo tuyệt vời tên là Harness Engineering, và chúng tôi đã nghĩ, "Chà, đây đúng là vàng ròng!" Chúng tôi mời anh ấy tham gia podcast. Anh ấy là một "tỷ phú mã thông báo", chi hơn một tỷ mã thông báo đầu ra mỗi ngày. Con số đó tương đương hơn một nghìn đô la. Vì vậy, bạn biết đấy, anh ấy thực sự đang sống với nó. Chúng ta muốn giữ cho buổi này hấp dẫn, hãy đặt những câu hỏi hay, những điều thú vị, những thứmọi người có thể học hỏi. Nhưng, bạn biết đấy, hãy chào đón Ryan lên sân khấu.

Chào mọi người, thế nào rồi? Rất vui được ở đây. Đây là một trải nghiệm tuyệt vời và tôi háo hức được chia sẻ về những gì chúng tôi làm và cách chúng tôi làm việc ở đây. Tôi nghĩ bạn đã phải đến đây. Tôi vừa đến đây nên bị chói mắt bởi mã QR, nhưng không sao. Vậy bối cảnh là chúng ta có khoảng một tiếng. Hãy quét mã QR này. Bạn sẽ có Slido. Slido sẽ cho phép bạn đặt câu hỏi. Nếu bạn thấy điều thú vị, bạn có thể thả tim cho chúng, và chúng tôi sẽ cố gắng trả lời. Thật không may, câu hỏi đầu tiên tôi không thể trả lời chi tiết được, nhưng chúng ta hãy bắt đầu nhé. Ryan, bạn có thể cho chúng tôi xem thiết lập làm việc thực tế của bạn không? Tôi đang ở đây, bãi biển Margarita tuyến tính, đúng không? Tôi sẽ nói, hãy xem podcast mà chúng tôi đã phát hành. Chúng tôi có đề cập đến một số công việc. Nhưng nếu bạn muốn nói về nó, tôi đoán là không cần phải trình bày trực quan, quy trình làm việc của bạn như thế nào? Thiết lập của bạn ra sao? Bạn tiếp cận một nhiệm vụ như thế nào?

Thiết lập Làm việc và Quy trình Phát triển Tác nhân

Chắc chắn rồi. Cách tôi và nhóm của tôi làm việc là bắt đầu với các ticket, đúng không? Chúng tôi có những phần công việc mà chúng tôi muốn làm, các tính năng chúng tôi muốn thêm vào ứng dụng của mình, công việc đảm bảo độ tin cậy mà chúng tôi muốn thực hiện. Chúng tôi giao ticket đó cho một tác nhân cùng với một vài kỹ năng cho phép nó thao tác với ứng dụng của chúng tôi. Chúng tôi muốn điểm vào của quy trình phát triểnCodex, chứ không phải một môi trường mà chúng tôi xây dựng xung quanh nó. Vì vậy, chúng tôi thực hiện mọi thứ bên ngoài nó, đúng không? Giống như Codexđiểm vào theo cách bạn sẽ là, và chúng tôi cung cấp cho nó công cụ, chúng tôi đưa cho nó hướng dẫn về cách vận hành. Vì vậy, thay vì tạo ra một shellứng dụng của chúng tôi và Codex được sinh ra bên trong, chúng tôi có một kỹ năng dạy Codex cách khởi chạy ứng dụng, dạy Codex cách khởi động stack khả năng quan sát cục bộ đó để cấp cho nó logging vào entry. Chúng tôi cung cấp cho nó một kỹ năng cho phép nó khởi động Chrome DevToolskết nối với ứng dụng bằng một giao diện dòng lệnh cục bộ sẽ kết nối thông qua một số Daemon mà chúng tôi có. Vì vậy, toàn bộ cách chúng tôi thiết lập repository và tất cả các DevTools cục bộ là để Codex gọi chúng trước tiên.

Điều đó có nghĩa là chúng tôi có một loạt các mini harness nhỏ trong codebase giúp chúng tôi dễ dàng thêm vào các Hàng rào bảo vệ bổ sung. Chúng tôi có một package lớn gồm các quy tắc ESLint tùy chỉnh được kết nối vào mỗi package PNPM trong workspace. Chúng tôi có một Dev harness cục bộ khác cho phép chúng tôi thêm các bài kiểm thử toàn diện cấp cao hơn để khẳng định cấu trúc của chính , hơn là cú pháp hoặc hành vi của . Những thứ như quyền riêng tư của package, các cạnh phụ thuộc giữa các lớp khác nhau của stack của chúng tôi, những loại thứ như vậy. Đảm bảo rằng trên nhiều tệp, các lược đồ lạ được khử trùng lặp để có một triển khai chính tắc duy nhất cho các hàm hỗ trợ async của chúng tôi, những loại thứ như vậy. Bởi vì cách chúng tôi đã thấy các tác nhân hoạt động là đôi khi tối ưu hóa cho tính gắn kết cục bộ của một package thay vì sử dụng các tiện ích chia sẻ của chúng tôi và những thứ tương tự. Vì vậy, sau khi quan sát hành vi đó, chúng tôi đã xây dựng một loạt các công cụ xác minh mã nguồn giả-linter nhỏ để loại bỏ một số hành vi xấu đó. Để con người không bị phân tâm chú ý đến điều đó và các đánh giá tương tự. Nhưng thiết lập này tối ưu hóa để tác nhân thực hiện công việc và để con người không phải theo dõi sự thay đổi lớn trong codebase.

Quản lý Kỹ năng Tác nhân

Chúng tôi tập trung đòn bẩy của mình vào khoảng năm đến mười kỹ năng. Chúng tôi không mở rộng kỹ năng quá nhiều, mà thích cải thiện các kỹ năng hiện có hơn vì ít nhất tôi thấy rằng cơ sở hạ tầng trong repository, tất cả các công cụ nhà phát triển cục bộ thay đổi rất thường xuyên. Và tôi thực sự không có đủ băng thông để theo dõi điều này. Vì vậy, chúng tôi giấu tất cả độ phức tạp đó dưới các kỹ năng mà con người phải gọi, và để tác nhân tự tìm cách giải quyết. Một điều khá hay ở đây là khi chúng tôi chuyển từ việc sử dụng trực tiếp giao thức Chrome DevTools sang có Daemon này, thì tôi đã không biết điều đó xảy ra trong khoảng ba tuần. Mọi chuyện vẫn hoàn toàn ổnCodex có thể thực hiện công việc với tài liệu và những thứ mà chúng tôi đã thiết lập. Một phần của điều này, bạn có thể tìm thấy chi tiết hơn trong các bài viết của mình. Về bối cảnh: Bạn đã viết một tác phẩm tuyệt vời tên là Harness Engineering. Có cả một phần trong đó về cách bạn đã suy nghĩ về kỹ năng—hàng nghìn kỹ năng so với việc đơn giản hóa nó xuống chỉ còn một vài.

Tránh Over-engineering và Tùy chỉnh Công cụ

Nhưng được rồi, tiếp tục, làm thế nào bạn ngăn mình over-engineering harnesses? Và một câu hỏi tiếp theo tương tự là, bạn có thường tự xây dựng các công cụ nhỏ cho mình không? Nếu có, bạn có xây dựng công cụ tùy chỉnh không? Vâng, tôi nghĩ điều này có vẻ đang ám chỉ đến "bài học cay đắng" ở đây, đúng không? Đó là, làm thế nào để tôi đảm bảo công việc mà tôi làm không bị lỗi thời hoàn toàn bởi sự gia tăng năng lực mô hình? Và cách tôi suy nghĩ về điều đó là thực hiện mức tối thiểu nhất trong quản lý ngữ cảnh để kéo các yêu cầu vào cho tác nhân thực hiện công việc chấp nhận được trong suốt quá trình làm việc của nó. Và ngữ cảnh là một thứ mà tôi không nghĩ sẽ bao giờ bị lỗi thời, đúng không? Giống như các mô hình phải được cho biết các yêu cầu của nhiệm vụ, Hàng rào bảo vệ nào cần chú ý, những loại thứ như vậy. Vì vậy, một harness tốt thực sự được vận hành xung quanh việc cung cấp văn bản mô hình vào đúng thời điểm để chúng ta có thể xem xét công việc nó đã làm và thông tin về một công việc tốt trông như thế nào.

Và bạn biết đấy, về cơ bản, các mô hình được huấn luyện để tuân theo hướng dẫn. Tất cả những gì harness nên làm là hiển thị hướng dẫn cho mô hình vào đúng thời điểm. Vì vậy, chúng ta cũng muốn giảm thiểu điều đó, đúng không? Bạn không muốn tải trước tất cả các hướng dẫn đó vì sau đó bạn sẽ giống như áp đảo tác nhân. Nhưng tất cả các yêu cầu này xoay quanh một công việc tốt cần được chú ý trong suốt quá trình của PR, đúng không? Vì vậy, tìm cách để trì hoãn hoặc hiển thị kịp thời các hướng dẫn đó chính là cách tôi sẽ làm.

Vì vậy, hướng dẫn là thứ mà một harness tốt nên làm, đúng không? Nếu bạn biết rằng bạn muốn các React component của mình được phân tách để chúng tạo ra các kiểm thử snapshot tốt cho các phần riêng lẻ, ít trạng thái hơn, đúng không? Bạn không cần phải tải trước điều đó. Thay vào đó, bạn nên để tác nhân tự do tạo nguyên mẫuthử nghiệm với giao diện người dùng mà bạn muốn xây dựng. Và sau đó, tại thời điểm lint hoặc kiểm thử, hãy nói, "Được rồi, bạn đã hoàn thành công việc. Để hoàn thành nó, bạn phải ngừng hỗ trợ để các component của bạn nhỏ." Và ngay khi bạn làm điều đó, bạn có thể làm điều đó.

So sánh với các Harness khác (Codex)

Vì vậy, bạn có thể làm điều đó cho một component nhỏít trạng thái nhất có thể, và có các phụ thuộc cục bộ vào hooks thay vì prop drilling hoặc bất cứ điều gì bạn muốn trông như thế nào. Và sau đó, tác nhân sẽ nói, "Ồ, đây là một hướng dẫn mới cho tôi. Hãy để tôi lấy patch đã viết, sửa đổi nó để đảm bảo nó tuân thủ các hướng dẫn, và sau đó nó sẽ được đẩy lên GitHub." Và loại điều này sẽ không phải là một ví dụ tốt về một harness tốt. Vì vậy, rất nhiều người đang hỏi về mô hình Codex, Codex harness. Nó so sánh với các harness khác như thế nào? Ví dụ như Claude Code, Open Code—các bạn đưa ra các quyết định này như thế nào? Bạn không trực tiếp làm việc trên Codex, nhưng nếu có điều gì bạn có thể nói về Codex harness, những gì các bạn thấy khi thiết kế kiến trúc nó.

Tận dụng Harness và Tập trung vào Hành vi của Tác nhân

Một điều tôi nghĩ là cực kỳ mạnh mẽ là ý niệm rằng các phòng thí nghiệm không chỉ post-training các mô hình mà còn post-training các mô hình trong ngữ cảnh của harness mà chúng được triển khai chính yếu, chẳng hạn như apply patch tool hoặc ngữ nghĩa trích dẫn cụ thể về cách gọi bash tool, hoặc trong vòng lặp của quy trình post-training cho các harness từ các phòng thí nghiệm. Điều này có nghĩa là có thể tận dụng lợi thế bằng cách phụ thuộc trực tiếp vào các harness của bên thứ nhất – ít nhất đó là những gì tôi tin. Do đó, việc có thể điều khiển chúng thông qua những thứ như SDK hoặc thao tác trực tiếp với Codex app server có nghĩa là bạn có thể tận dụng tất cả những lợi thế đó trong post-training, thay vào đó tập trung vào những phần bạn quan tâm, đó là mã đúng trông như thế nào.

Tôi khá tự tin rằng những thứ như Claude CodeCodex sẽ tiếp tục tốt hơn – đó là trách nhiệm của các nhóm làm việc trên các tác nhân lập trình này. Vì vậy, trong vai trò của mình, nơi tôi không thực sự muốn tập trung vào coding harness chút nào, là tìm cách tích hợp vào chúng theo những cách có thể steer (điều khiển) tác nhân. Điều này có nghĩa là công việc của tôi có thể nâng tầm lên việc suy nghĩ về sự khác biệt trong hành vi của mô hình giữa các bản phát hành. Do đó, tôi nghĩ thay vì hiểu sâu sắc về các chi tiết cốt lõi của harness, tôi có thể suy nghĩ về ý nghĩa của việc thúc đẩy hành vi mà tôi muốn dựa trên hành vi quan sát được, hơn là các cơ chế bên trong của nó.

Nền tảng Cộng tác và Quản lý Phản hồi

Đây là một câu hỏi tiếp theo hoàn hảo: "Bạn có khuyến nghị nào về nền tảng cộng tác không? Khi bạn đang trong vòng đời phát triển phần mềm, có nền tảng nào bạn sử dụng để các tác nhân, kỹ sư, nhà phát triển đều cộng tác trong bất kỳ công việc nào không? Vậy đó không chỉ là về các loại công cụ bạn sử dụng cho các loại công cụ."

Trong thế giới này, mọi thứ phần lớn chỉ là các tệp Markdown trong kho lưu trữ và GitHub, đó là một dạng hub and spoke chính. Vì vậy, bạn đang cộng tác trên một tài liệu giống như bạn mở Google Docs, bạn viết gì đó, bạn yêu cầu phản hồi, mọi người bình luận, bạn áp dụng các đề xuất — những thứ tương tự. Đây giống như một môi trường clean room nhỏ chỉ dành cho tác phẩm này mà bạn đang tạo ra; một PR (pull request) có mục đích tương tự. Vì vậy, chúng tôi coi đó là một broadcast domain lớn kiểu hub and spoke nơi tất cả các tác nhân và con người cộng tác với nhau.

Và bởi vì chúng tôi tối ưu hóa cho throughput (thông lượng), chúng tôi không chặn bất kỳ đóng góp nào vào đó; mọi người có thể xem xét hoặc không, các tác nhân có thể xem xét hoặc không. Tác nhân triển khai có thể xác nhận, trì hoãn hoặc từ chối bất kỳ phản hồi nào mà nó nhận được, thực sự cho phép mỗi người tham gia vào việc sản xuất diff đưa ra phán đoán riêng của mình về ý nghĩa của việc gửi, nhận, phản hồi phản hồi. Điều này có một đặc tính tốt là không đóng khung mô hình ở nhiều nơi. Chúng tôi muốn chúng sử dụng khả năng suy luận tốt của mình. Vì vậy, việc quá cứng nhắc về việc "mọi phản hồi phải được giải quyết" có thể dẫn đến catastrophic failure mode (chế độ lỗi thảm khốc) khi tác nhân lập trình của bạn bị "bắt nạt" bởi những người đánh giá cũ kỹ, trong khi thực sự chúng tôi muốn thiên về việc mã được chấp nhận, không cần phải hoàn hảo, không bị chìm trong chi tiết vụn vặt và những thứ tương tự.

Bắt đầu với Tác nhân Lập trình: Nâng cao Độ tin cậy và Tự động hóa

"Mọi người nên bắt đầu sử dụng các tác nhân lập trình như thế nào? Những người đã quen với việc viết mã thủ công nhiều, họ nên bắt đầu chuyển đổi như thế nào? Họ nên giao phó những gì? Làm thế nào để họ vượt qua rào cản 'tôi vẫn kiểm tra mọi PR và sao chép/dán từ Codex'? Một kỹ sư trung bình nên bắt đầu sử dụng các công cụ này như thế nào?"

Tôi nghĩ có hai cách để tiếp cận vấn đề này. Một là bắt đầu sử dụng các tác nhân lập trình để nâng cao sự tự tin của bạn vào chính mã đã viết hôm nay. Tôi nghĩ tất cả chúng ta sẽ đồng ý rằng nhiều test (kiểm thử) hơn có lẽ là một điều tốt để khẳng định rằng các chương trình của chúng ta được chỉ định rõ ràng và hoạt động chính xác khi người dùng tương tác với chúng. Và các tác nhân rất giỏi trong việc xem xét mã hiện có với một số ngữ cảnh về cách nó được sử dụng và viết các test để khẳng định hành vi đó. Vì vậy, việc sử dụng điều này để cải thiện sự tự tin của bạn vào chất lượng mã cũng sẽ tăng khả năng của tác nhân trong việc điều hướng nó thành công, nghĩa là bạn không phải lo lắng quá nhiều về việc review (đánh giá) chi tiết đầu ra của tác nhân.

Cách khác để suy nghĩ về điều này là nhìn vào cách bạn đang dành thời gian của mình. Bạn có đang nhìn chằm chằm vào trình soạn thảo để viết mã không? Bạn có đang chờ test chạy không? Bạn có đang chờ phản hồi review của con người không? CI (Continuous Integration) có chậm không và bạn đang phải chờ đợi? Có lẽ bạn có rất nhiều flaky test (kiểm thử không ổn định). Hãy sử dụng các tác nhân để tự động hóa dần dần những phần mà bạn đang dành thời gian.

Cuối cùng, những phần có đòn bẩy cao trong công việc của chúng ta là định nghĩa công việc cần làm, ưu tiên và lên lịch công việc đó, sau đó trao quyền hiệu quả cho các thành viên trong nhóm của chúng ta để thực hiện công việc đó. Và càng ngày chúng ta càng có thể giao phó và chuyển sang vai trò sequencing (tuần tự hóa) và orchestration (kiểu điều phối), ngay cả khi bạn chỉ nghĩ về việc quản lý các nhóm của mình. Càng song song và càng sâu sắc các lần thực thi cá nhân của những nhiệm vụ được giao đó, chúng ta càng có thể làm được. Nếu tôi đặt các primitives vào đúng vị trí giúp việc khởi tạo các cách phản hồi sự kiện từ hàng đợi trở nên cực kỳ dễ dàng, thì tôi không thực sự cần phải "lăn vào bụi rậm" với mỗi kỹ sư để đảm bảo họ triển khai một consumer đúng cách. Và những kỹ thuật xây dựng kiểu building block tương tự này áp dụng rất tốt cho các tác nhân và rất phù hợp để xếp chồng lên nhau.

Quản lý Tác nhân khi đang di chuyển và Khả năng Mở rộng cho Codebase Lớn

"Một câu hỏi thú vị: bạn làm việc với các tác nhân trong ô tô của mình như thế nào?"

Tôi chưa sử dụng chế độ giọng nói mới ra mắt trong CarPlay gần đây, chưa sẵn sàng cho điều đó. Nhưng thông thường, tôi sẽ khởi động một tác vụ ngay trước khi rời văn phòng, kết nối máy tính xách tay với điện thoại, buộc nó vào ghế sau và để nó chạy trong 30 phút đi về nhà. Hầu hết thời gian, với các skill (kỹ năng) mà chúng tôi gọi, chúng sẽ nói với tác nhân: "Bạn đang thực hiện một tác vụ. Bạn cứ tiếp tục cho đến khi các test có màu xanh lá cây." Tôi không phải với tay ra phía sau để nhắc nó tiếp tục công việc. Và về cơ bản, tôi có thể tận dụng tối đa ngày của mình với việc tiêu thụ mã thông báo.

Giấc mơ ở đây là tôi thực sự có 50 tác nhân chạy 24/7 và tôi không phải tương tác với chúng chút nào. Cách để làm điều đó là định nghĩa công việc thật tốt, tìm cách để nó tự động được lên lịch và loại bỏ bản thân khỏi việc phải nhấn nút. Mỗi khi tôi phải gõ "tiếp tục" cho tác nhân, đó giống như một lỗi của harness trong việc không cung cấp đủ ngữ cảnh về ý nghĩa của việc hoàn thành. Một phát biểu hay ở cuối: "Mỗi khi bạn phải tương tác với tác nhân là một thất bại."

"Được rồi, câu hỏi tiếp theo mở rộng điều này: khi knowledge map (bản đồ kiến thức) hoặc codebase của bạn mở rộng, bạn có những bước thực tế nào để cho phép progressive disclosure (tiết lộ dần dần)? Tức là, khi bạn có một codebase lớn hơn và nhiều người hơn, làm thế nào để bạn mở rộng các tác nhân của mình để hoạt động tốt hơn với điều này?"

Khi tôi bắt đầu dự án này, tôi đã làm việc trên một repository trống, cụ thể là một repository "tạo ứng dụng Electron". Đó là một gói duy nhất, tất cả những thứ tương tự, và cuối cùng thì mọi thứ trở nên lộn xộn vì không có package privacy nào cho phép tôi thực thi các invariants xung quanh việc API nào là công khai và API nào không. Vì vậy, chúng tôi không có các hook cụ thể trong hệ thống tệp để xác định các domain nào tách biệt với các domain khác. Cuối cùng, chúng tôi đã chuyển sang một kiến trúc nặng nề như một tổ chức 10.000 kỹ sư, với 750 gói trong PNPM workspace, được cô lập theo domain logic (lôgic nghiệp vụ) hoặc tầng của stack, các gói util nhỏ riêng lẻ gói gọn chức năng tái sử dụng mà chúng tôi đã liên kết để sử dụng và có thể tận dụng.

Và tôi thực sự nghĩ rằng trong thế giới này, ngay cả khi bạn không thực sự có microservices, việc cấu trúc các repository của bạn theo cách mà bạn thực sự có thể giới hạn directory subtree mà bạn đang xem xét để thực hiện hầu hết các thay đổi sẽ giúp ích. Và mã trong hệ thống tệp cũng là văn bản, có nghĩa là nó thực sự là các lời nhắc mà bạn đang cung cấp cho tác nhân lập trình của mình. Vì vậy, việc làm cho mã càng giống nhau càng tốt sẽ giúp cho tác nhân của bạn phát triển rất nhiều ngữ cảnh có thể chuyển giao, bất kể nó đang tìm kiếm ở đâu trong repository. Ví dụ, bạn nên có một cách để thực hiện bounded concurrency helper, một cách để xây dựng một lệnh side effect full có thể quan sát và được instrument (đo lường), hoặc bạn có một ngôn ngữ lập trình, một cách viết CI script, một cách thêm các quy tắc lint bổ sung — những thứ như vậy. Bởi vì điều đó có nghĩa là các mã thông báo bạn muốn mô hình tạo ra sẽ dễ dự đoán hơn và được dự đoán nhất quán hơn bất kể nó tìm kiếm ở đâu.

Vì vậy, tôi khuyên bạn nên tìm cách cấu trúc mã sao cho nó cục bộ với một subtree trong repository cho hầu hết các cách bạn tương tác với hệ thống đó, sau đó tìm cách sử dụng các tác nhân này để di chuyển hoàn toàn codebase để nó trở nên đồng nhất. Hãy trao quyền cho một người nào đó trong nhóm của bạn trở thành "người độc tài" để nói: "Đây là cách phải làm." Hoặc bạn sẽ cùng nhau tìm ra và ghi lại điều đó, phát triển mã để nó phản ánh thực tế đó.

Nâng cao Hiệu quả Code Review với Tác nhân

"Chúng tôi có một vài câu hỏi về code review. Vậy bạn tiếp cận code review như thế nào khi bạn có tốc độ cao như vậy? Bạn có bỏ qua việc đọc mã không? Bạn có chỉ tin tưởng vào độ bao phủ test không? Làm thế nào để bạn viết test tốt? Làm thế nào để bạn giảm bớt nỗi lo lắng phải kiểm tra thủ công mọi thứ trước khi merge (hợp nhất) PR?"

Cũng theo ý tưởng tương tự, bạn phải nhìn vào nơi bạn đang dành thời gian và tìm cách dành ít thời gian hơn. Khi chúng tôi bắt đầu, điều đầu tiên cần làm là tìm cách để tác nhân tạo ra mã mà chúng tôi sẽ chấp nhận một cách đáng tin cậy. Một thách thức lớn mà chúng tôi gặp phải là với mỗi kỹ sư tạo ra ba đến năm PR mỗi ngày, ngay cả trong một nhóm ba người, merge conflicts (xung đột hợp nhất) là một nỗi khổ kinh hoàng. Bởi vì những PR này thường khá lớn và chúng tôi làm việc trên cùng một phần của codebase.

Vì vậy, đó là lúc chúng tôi chuyển sang các hướng: một là cấu trúc mã thành tree nhiều hơn một chút để giảm thiểu các merge conflict, nhưng cũng giảm thiểu thời gian PR tồn tại trên toàn bộ mã. Điều này giúp giảm khả năng xảy ra merge conflict. Lý do các PR tồn tại quá lâu là vì chúng tôi cần code review và con người chính là yếu tố gây tắc nghẽn trong kịch bản này. Để tự động hóa phần đó, về cơ bản tôi đã yêu cầu mỗi kỹ sư trong nhóm dành một ngày mỗi tuần mà công việc của chúng tôi là thu thập mọi vấn đề nhỏ mà chúng tôi đã quan sát trong tuần khiến PR khó merge, và tìm cách loại bỏ hoàn toàn chúng ngay từ đầu.

Đây là nơi chúng tôi bắt đầu đóng vòng lặp giữa phản hồi mà con người đưa ra về PR – điều này cho thấy một số lỗi ngữ cảnh thay mặt cho tác nhân – đưa điều đó vào repository, và sau đó tìm cách tự động prompt và kiểm tra tác nhân để nó tự phục hồi khi tạo ra hành vi xấu. Và đây là cách bạn chuyển từ thời gian con người dành cho việc phản hồi đồng bộ dưới dạng bình luận code review sang documentation (tài liệu) trong repository để tự động phục vụ documentation này, hoặc thông qua một test thất bại hoặc một tác nhân viewer được chuẩn bị sẵn sàng để review mã như đã viết trong ngữ cảnh của các tài liệu này. Nhưng tất cả điều đó xảy ra bằng cách đặt các tài liệu đó vào một nơi duy nhất mà tất cả các quy trình này có thể gắn vào.

Tối ưu hóa quy trình đánh giá mã bằng Tác nhân AI

Chúng tôi đã yêu cầu mọi người phân loại các loại phản hồi đánh giá mà họ đưa ra theo hình mẫu mà họ đang hoạt động: kiến trúc sư giao diện người dùng, kỹ sư độ tin cậy, kỹ sư khả năng mở rộng, v.v. Và sau đó, về cơ bản, đối với mỗi hình mẫu đó, chúng tôi đã triển khai một tác nhân đánh giá được kích hoạt trên mỗi lần push mã. Tác nhân này sẽ hỏi: "Mã này có tốt không? Có vấn đề P2 hoặc cao hơn nào có thể ngăn cản việc hợp nhất PR này dựa trên tài liệu mô tả tiêu chuẩn chất lượng không?" Và với điều đó, cùng với việc liên tục bổ sung vào các tệp này, chúng tôi bắt đầu thấy nhiều việc giảm bớt.

Quản lý và tối ưu hóa sử dụng mã thông báo

Mọi người có câu hỏi về hàng tỷ mã thông báo của bạn. Bạn nghĩ chúng được phân chia như thế nào? Cụ thể, bao nhiêu phần trăm được dùng cho việc đánh giá mã? Phần lớn việc sử dụng đó đến từ đâu? Và một câu hỏi tiếp theo cho những người mới bắt đầu, ví dụ họ đã đăng ký gói chuyên nghiệp 200 đô la, phải không? Nếu bạn phải cắt giảm việc sử dụng của mình đi một phần năm, mọi người nên tối đa hóa hiệu quả như thế nào? Bạn biết đấy, bạn không muốn chỉ sao chép hàng triệu dòng mã cứ sau sáu giờ. Không, hãy sử dụng lời nhắc, lưu lời nhắc vào bộ nhớ đệm (prompt cash). Nhưng chúng ta nên nghĩ về điều đó như thế nào? Vâng, tôi nghĩ rằng có lẽ nó được chia thành ba phần bằng nhau giữa lập kế hoạch, sắp xếp ticket, tài liệu, triển khai và những thứ chạy trong CI.

Chế độ kế hoạch và giá trị của nó

Bạn có sử dụng plan mode không? Chúng tôi đã sử dụng exact plans, đây là một phiên bản ban đầu mà chúng tôi đã phát hành, giống như một kỹ năng nguyên mẫu (proto skill) hướng dẫn cách cấu trúc một kế hoạch với các mốc quan trọng và tiêu chí chấp nhận. Tôi chưa thực sự sử dụng plan mode trong Harness. Kỳ vọng của tôi là tôi có thể thả một ticket vào và tác nhân sẽ hoàn thành công việc mà không cần phải thông qua một kế hoạch, bởi vì hầu hết thời gian tôi cũng sẽ không đọc nó. Do đó, tôi thấy rằng nếu bạn sử dụng một kế hoạch và chấp thuận nó mà không đọc, bạn thực sự đang mã hóa một loạt các hướng dẫn mà bạn không nhất thiết muốn làm theo. Vì vậy, nếu bạn định sử dụng các kế hoạch, khuyến nghị của tôi là đưa chúng lên dưới dạng các PR riêng biệt chỉ chứa kế hoạch, trong đó bạn thực sự có người kiểm tra từng dòng và yêu cầu sự chấp thuận của con người trước khi chúng được hợp nhất và kích hoạt, bởi vì bạn có khả năng lãng phí thời gian vào một quy trình triển khai với những hướng dẫn không tốt. Vì vậy, bạn muốn giảm thiểu thời gian xảy ra điều đó. Nhưng tôi nghĩ rằng việc sử dụng mã thông báo trong CI là một phần cần thiết ở đây, bởi vì viết mã không còn là phần khó. Việc mã được chấp nhận và thúc đẩy mã cũng như sản phẩm tiến lên mới là điều cần thiết để mã đã viết trở nên có giá trị. Và bạn biết đấy, giống như câu châm ngôn rằng các kỹ sư cấp cao đưa ra các đánh giá mã tốt, chúng tôi kỳ vọng các kỹ sư cấp cao của chúng tôi, với tư cách là tác nhân, cũng làm điều tương tự.

LLM như một trình biên dịch mờ

Có người hỏi, "Mã có phải là một artifact xây dựng dùng một lần không?" Vâng. Tôi nghĩ chúng ta đã đề cập đến điều này với Symphony, đây là một orchestrator tác nhân mà chúng tôi đã phát hành ý tưởng rằng, bạn biết đấy, chúng ta có thể xuất bản một thư viện thực sự là một đặc tả (spec) được định nghĩa rất tốt, và mã là một artifact được biên dịch từ đó. Và tôi nghĩ rằng việc sử dụng LLM như một trình biên dịch mờ (fuzzy compiler) là một mô hình tư duy thú vị, phải không? Giống như tất cả ngữ cảnh mà chúng ta đưa vào cơ sở mã cho kỹ thuật Harness về cơ bản giống như các ràng buộc và các lượt tối ưu hóa để xác định mã nào là chấp nhận được để xây dựng ngay từ đầu. Và điều này khá tương tự với các lượt phân tích tĩnhtối ưu hóa mà một LLM sẽ thực hiện trong quá trình biên dịch mã Rust. Và việc thay thế mô hình này bằng mô hình khác giống như việc thay đổi phần backend sinh mã của bạn từ LLM sang Cranelift trong trình biên dịch Rust. Và bạn sẽ mong đợi rằng tất cả các quy tắc về mã Rust chấp nhận được sẽ tạo ra mã máy hợp lệ, đáng tin cậy ở phía sau, ngay cả khi quá trình sinh mã khác nhau và bạn nhận được các lệnh x86 khác nhau. Vì vậy, cùng một tư duy áp dụng cho việc LLM thay thế các mô hình khác nhau. Chúng tôi muốn cấu trúc xung quanh mã về cơ bản giới hạn cách nó được viết thành những thứ mà chúng tôi có thể chấp nhận.

Tầm nhìn tương lai của Kỹ thuật phần mềm với Tác nhân AI

Và ở cấp độ cao, bạn có thể cho chúng tôi một hình dung về tương lai mà bạn đang xây dựng cho ngữ cảnh này không? Bất kể mọi người thực hiện kỹ thuật như thế nào — kỹ thuật Harness, kỹ thuật ngữ cảnh — tương lai sẽ trông ra sao? Tương lai mà tôi muốn xây dựng ở đây là nơi tôi có thể lấy một ngân sách mã thông báo cho một quý, nửa năm, hoặc một năm làm việc, lấy thông tin đầu vào từ con người để xếp hạng những gì quan trọng nhất — các số liệu thành công, các số liệu độ tin cậy — giao cho máy móc, và để chúng liên tục làm việc nhằm thúc đẩy sản phẩm của tôi tiến lên mà không cần tôi trực tiếp can thiệp.

Mở rộng vai trò của Tác nhân AI ngoài việc viết mã

Khi chúng tôi trải qua từ các giai đoạn tạo mẫu rất sớm đến alpha nội bộ, beta nội bộ và alpha bên ngoài, tôi cảm thấy rằng các phần mới của quy trình kỹ thuật phần mềm đã bắt đầu từ con số 0, và chúng tôi phải xây dựng năng lực, giống như những biểu đồ tính cách hình ngũ giác, phải không? Hoặc như, tôi xuất sắc ở khía cạnh này, có thể tôi yếu ở khía cạnh khác. Và, bạn biết đấy, khi chúng ta triển khai phần mềm lần đầu tiên, khả năng của các tác nhân trong việc thực hiện QA smoke testing trên các artifact đã xây dựng của chúng tôi trước khi chúng được đưa vào phân phối còn yếu. Chúng tôi chưa đầu tư thời gian vào việc này. Không có tài liệu, không có công cụ mà các tác nhân có thể sử dụng, chẳng hạn như tải xuống artifact đã xây dựng, khởi chạy nó và kiểm tra để đảm bảo rằng các hành trình người dùng quan trọng nhất của chúng tôi đã được xác thực và kiểm tra tốt. Vì vậy, bởi vì tôi không muốn phải trực tiếp chạm vào máy tính, chúng tôi cần tìm cách để các tác nhân tự xây dựng công cụ để làm phần việc đó. Và có cả một vũ trụ kỹ thuật phần mềm bên ngoài việc viết mã, phải không? Chẳng hạn, tôi đang phân loại phản hồi người dùng, tôi đang phân loại các trang, tôi đang đảm bảo rằng chúng tôi không có bất kỳ PII nào bị rò rỉ trong nhật ký và quá trình sản xuất. Tôi đang đảm bảo rằng tâm trạng trên Twitter là tốt và mọi người đang thích phần mềm của tôi. Nhân viên vận hành người dùng của chúng tôi được hỗ trợ bằng các sách hướng dẫn (run books) được viết tốt, cho phép họ phân loại và giảm thiểu các vấn đề người dùng có khối lượng lớn, sau đó chuyển điều đó vào chính mã nguồn để chúng không xảy ra ngay từ đầu. Và khi tôi không còn phải tạo mã nữa, tâm trí tôi có thể chuyển sang các hoạt động cấp cao hơn hoặc mơ hồ hơn này, nhưng các tác nhân cũng đủ tốt để làm những điều này. Và việc tìm ra cách ghi lại các quy trình và các tiêu chí chấp nhận trở thành một phần của công việc metaprogramming.

Kết luận

Tôi nghĩ đó là một cách tuyệt vời để kết thúc với một tương lai đầy hứa hẹn. Mọi người hãy dành một tràng pháo tay cho Ryan! Cảm ơn mọi người.

Góp ý / Báo lỗiPhát hiện sai sót hoặc có ý tưởng cải thiện?