Lời biên tập: Cách sử dụng Agent mã hóa AI đang chuyển từ "con người viết Prompt thủ công, thúc đẩy nhiệm vụ từng vòng" sang "con người thiết kế vòng lặp, để hệ thống liên tục điều phối Agent". Loop Engineering (Kỹ thuật Vòng lặp) mà Addy Osmani đề cập, cốt lõi là xây dựng một quy trình công việc có thể tự động phát hiện nhiệm vụ, phân bổ nhiệm vụ, kiểm tra kết quả, ghi lại tiến độ và quyết định bước tiếp theo.
Vòng lặp này về cơ bản được tạo thành từ năm mô-đun: Automations (phát hiện và phân loại nhiệm vụ theo lịch trình), Worktrees (cô lập nhiều môi trường phát triển song song), Skills (lưu trữ kiến thức dự án và quy ước nhóm), Plugins/Connectors (kết nối với các công cụ thực tế như GitHub, Linear, Slack, cơ sở dữ liệu, v.v.), Sub-agents (tách biệt người thực thi và người kiểm tra), cộng thêm một lớp bộ nhớ bên ngoài, như tệp Markdown hoặc bảng Linear, để lưu trạng thái và tiến triển.
Bài viết nhắc nhở, ý nghĩa của Loop Engineering không chỉ là "để AI chạy nhiều vòng hơn", mà là đưa khả năng phán đoán của kỹ sư vào trước trong thiết kế hệ thống. Vòng lặp có thể khuếch đại đáng kể đòn bẩy công việc của nhà phát triển, nhưng sẽ không thay thế việc xác minh, hiểu và phán đoán. Rủi ro thực sự không nằm ở việc sử dụng vòng lặp, mà nằm ở việc sử dụng vòng lặp như một cái cớ để trốn tránh việc hiểu mã và hệ thống. Khả năng quan trọng để hợp tác với lập trình AI trong tương lai, có lẽ không còn chỉ là viết một Prompt tốt, mà là thiết kế quy trình công việc Agent đáng tin cậy, có thể xác minh và chạy bền vững.
Dưới đây là bài viết gốc:
Loop engineering (kỹ thuật vòng lặp) đang thay thế vai trò của bạn với tư cách là "người viết prompt cho trợ lý AI". Bạn sẽ thiết kế một hệ thống, để hệ thống này thay bạn prompt trợ lý AI. Ở đây, loop (vòng lặp) có thể hiểu là một mục tiêu đệ quy: bạn định nghĩa một mục đích, AI sẽ liên tục lặp lại cho đến khi nhiệm vụ hoàn thành. Nó về cơ bản được tạo thành từ năm thành phần, và cả Claude Code và Codex hiện đều đã có đủ năm thành phần này.
Tôi tin rằng, đây có thể là cách chúng ta hợp tác với các agent mã hóa trong tương lai. Tuy nhiên, tất cả vẫn đang ở giai đoạn đầu và tôi vẫn giữ thái độ hoài nghi. Bạn chắc chắn cần thận trọng với chi phí token, vì sự khác biệt chi phí giữa các chế độ sử dụng có thể rất lớn, đặc biệt tùy thuộc vào việc bạn "dư thừa token" hay "thiếu hụt token". Bạn cũng cần có cơ chế nào đó để đảm bảo chất lượng không bị giảm sút. Những lo ngại về "sản phẩm tào lao của AI" (slop) cũng hợp lý. Dù vậy, hãy cùng xem điều này thực sự là gì.
Gần đây, @steipete đã nói một câu: "Bạn không nên viết prompt cho agent mã hóa nữa. Bạn nên thiết kế một số vòng lặp, để những vòng lặp này prompt agent của bạn." Tương tự, @bcherny, người phụ trách Claude Code của Anthropic cũng nói: "Hiện tại tôi không còn prompt Claude nữa. Tôi có một loạt vòng lặp đang chạy, chúng sẽ prompt Claude và tự quyết định bước tiếp theo nên làm gì. Công việc của tôi là viết vòng lặp."
Vậy, điều này thực sự có nghĩa là gì?
Trong khoảng hai năm qua, cách cơ bản để bạn muốn agent mã hóa làm điều gì đó là viết một prompt tốt và cung cấp đủ ngữ cảnh. Bạn nhập một câu, đọc kết quả trả về, rồi nhập câu tiếp theo. Agent là một công cụ, và bạn luôn cầm công cụ này, thúc đẩy nó từng vòng một. Giai đoạn này ở một mức độ nào đó đã kết thúc, hoặc ít nhất một số người cho rằng nó sắp kết thúc.
Bây giờ, bạn xây dựng một hệ thống nhỏ: nó tự phát hiện công việc, phân bổ nhiệm vụ, kiểm tra kết quả, ghi lại tình trạng hoàn thành, rồi quyết định bước tiếp theo làm gì. Nghĩa là, bạn để hệ thống này điều khiển agent, thay vì bạn tự mình prompt nó từng chút một. Trước đây tôi đã viết về "họ hàng gần" của nó – agent harness engineering (kỹ thuật khung chạy agent), tức là xây dựng môi trường chạy cho một agent đơn lẻ; và factory model (mô hình nhà máy), tức là hệ thống xây dựng phần mềm. Loop engineering thì nằm ở một lớp trên harness. Nó giống harness, nhưng sẽ chạy theo bộ hẹn giờ, tạo ra trợ lý nhỏ và tự nuôi dưỡng chính mình.
Điều làm tôi ngạc nhiên là, bây giờ điều này không còn chỉ là vấn đề ở "cấp độ công cụ" nữa. Một năm trước, nếu bạn muốn một vòng lặp, bạn phải viết một đống script bash, rồi bảo trì đống script đó mãi mãi. Đó là thứ của riêng bạn, và chỉ thuộc về bạn. Bây giờ, các thành phần này đã được tích hợp trực tiếp vào sản phẩm. Các khả năng mà Steinberger liệt kê gần như có thể tương ứng từng cái một trong ứng dụng Codex, và cũng gần như tương tự có thể tương ứng trong Claude Code. Một khi bạn nhận ra hình dạng của chúng giống nhau, bạn sẽ không còn băn khoăn nên dùng công cụ nào nữa, mà sẽ đi thiết kế một vòng lặp: bất kể bạn đang ngồi trong công cụ nào, nó đều có thể tiếp tục vận hành.
Năm thành phần, và một số lưu ý
Một vòng lặp cần năm thứ, cộng thêm một nơi để ghi nhớ thông tin. Tôi sẽ liệt kê ra trước, rồi giải thích từng cái.
Thứ nhất, Automations (tự động hóa nhiệm vụ): Kích hoạt theo kế hoạch, tự động phát hiện và phân luồng.
Thứ hai, Worktrees (cây công việc): Để hai agent làm việc song song không can thiệp vào tệp của nhau.
Thứ ba, Skills (kỹ năng): Viết ra kiến thức dự án, tránh để agent mỗi lần phải đoán mò.
Thứ tư, Plugins and connectors (plugin và trình kết nối): Cho phép agent kết nối với các công cụ bạn đang sử dụng.
Thứ năm, Sub-agents (agent con): Một agent chịu trách nhiệm đề xuất giải pháp, một agent khác kiểm tra giải pháp.
Rồi đến thứ sáu: memory (bộ nhớ). Nó có thể là một tệp Markdown, hoặc một bảng Linear, hoặc bất kỳ thứ gì độc lập với một cuộc hội thoại đơn lẻ, có thể lưu "những việc đã hoàn thành" và "những việc tiếp theo". Nghe có vẻ đơn giản đến mức không giống một việc quan trọng, nhưng đây là cùng một kỹ thuật mà mọi agent chạy dài hạn đều dựa vào. Tôi cũng đã viết chi tiết trong long-running agents: mô hình sẽ quên giữa các lần chạy, vì vậy bộ nhớ phải được đặt trên đĩa, không phải trong ngữ cảnh. Agent sẽ quên, nhưng kho mã nguồn thì không.
Hiện tại, cả hai sản phẩm đều đã có đủ năm thành phần này.
Tên gọi của chúng ở một số chỗ khác nhau, nhưng bản chất khả năng là một. Dưới đây tôi giải thích từng cái, bởi thực sự, việc một vòng lặp cuối cùng chạy ổn định hay lén lút rò rỉ ở khắp nơi, chìa khóa đều nằm ở chi tiết.
Automations: Đây là nhịp tim của vòng lặp
Automations là thứ khiến vòng lặp thực sự trở thành vòng lặp, chứ không phải một nhiệm vụ một lần bạn đã từng chạy thủ công. Trong ứng dụng Codex, bạn có thể tạo một tác vụ tự động trong tab Automations, chọn dự án, prompt mà nó sẽ chạy, tần suất chạy, và việc nó chạy trong checkout cục bộ của bạn hay trong worktree nền. Những kết quả chạy phát hiện ra vấn đề sẽ đi vào Triage inbox (hộp thư phân loại), còn những kết quả không phát hiện vấn đề sẽ tự động lưu trữ, điểm này khá hay. OpenAI nội bộ cũng dùng nó để làm một số việc nhàm chán nhưng cần thiết, như phân loại issue hàng ngày, tóm tắt nguyên nhân thất bại CI, viết báo cáo commit, theo dõi lỗi do ai đó đưa vào tuần trước. Tác vụ tự động cũng có thể gọi skill, vì vậy bạn có thể giữ cho các nhiệm vụ lặp lại có thể bảo trì được: kích hoạt $skill-name, thay vì dán cả một bức tường văn bản hướng dẫn vào một tác vụ được lên lịch mà sau này không ai cập nhật.
Claude Code cũng đạt được hiệu quả tương tự, chỉ khác đường đi: nó thực hiện thông qua lập lịch và hooks. Bạn có thể dùng /loop để chạy một prompt hoặc lệnh theo khoảng thời gian cố định, cũng có thể lên lịch một cron job, và cũng có thể dùng hooks để kích hoạt lệnh shell tại một số điểm trong vòng đời của agent. Nếu bạn muốn nó tiếp tục chạy sau khi bạn đóng laptop, bạn cũng có thể đẩy toàn bộ thứ này lên GitHub Actions. Ý tưởng hoàn toàn giống nhau: bạn định nghĩa một nhiệm vụ tự chủ, cho nó một nhịp độ, để kết quả phát hiện đến với bạn, thay vì bạn phải đi kiểm tra khắp nơi.
Còn một cú pháp gốc trong phiên đáng để biết, nó gần hơn với cốt lõi thực sự được thảo luận trong bài viết này. /loop sẽ lặp lại chạy theo nhịp độ; /goal sẽ thực thi liên tục cho đến khi một điều kiện nào đó bạn viết ra thực sự đạt được. Sau mỗi vòng, sẽ có một mô hình nhỏ riêng biệt đánh giá xem nhiệm vụ đã hoàn thành chưa, vì vậy agent viết mã không phải là agent tự chấm điểm cho mình. Bạn có thể cho nó một điều kiện, chẳng hạn "tất cả bài kiểm tra trong test/auth đều pass, và lint sạch", rồi rời đi. Codex cũng có khả năng tương tự, cũng gọi là /goal. Nó sẽ làm việc xuyên suốt các vòng cho đến khi một điều kiện dừng có thể xác minh được đạt thành, và hỗ trợ tạm dừng, tiếp tục và xóa. Cùng một cú pháp gốc, cả hai công cụ đều có. Đây về cơ bản là mô hình lặp đi lặp lại trong bài viết này.
Vậy, Automations chịu trách nhiệm đưa công việc lên bề mặt. Phần còn lại của vòng lặp chịu trách nhiệm xử lý những công việc này.
Worktrees: Để song song không trở thành hỗn loạn
Một khi bạn chạy nhiều hơn một agent, xung đột tệp sẽ trở thành điểm thất bại. Hai agent đồng thời ghi vào cùng một tệp, về bản chất cũng phiền phức như hai kỹ sư sửa cùng một dòng mã mà không trao đổi. git worktree có thể giải quyết vấn đề này. Nó là một thư mục làm việc riêng biệt trên một nhánh độc lập, nhưng chia sẻ cùng một lịch sử kho mã nguồn, do đó sửa đổi của một agent về mặt vật lý không thể chạm vào checkout của agent kia.
Codex hỗ trợ worktree trực tiếp, vì vậy nhiều luồng có thể xử lý cùng một kho cùng lúc mà không va chạm nhau. Claude Code cũng có thể đạt được sự cô lập tương tự thông qua git worktree: bạn có thể dùng cờ --worktree để mở một phiên trong checkout độc lập, cũng có thể đặt isolation: worktree trên subagent, để mỗi trợ lý nhỏ nhận được một checkout hoàn toàn mới và được dọn dẹp tự động sau khi kết thúc. Tôi đã viết về khía cạnh con người của việc này trong the orchestration tax: worktrees có thể loại bỏ xung đột ở cấp độ cơ học, nhưng bạn vẫn là giới hạn trên. Thứ quyết định bạn có thể chạy bao nhiêu agent cùng lúc không phải là công cụ, mà là review bandwidth (băng thông xem xét) của bạn.
Skills: Để bạn không phải giải thích lại dự án mỗi lần
Skill là một cơ chế, để bạn không phải giải thích lại cùng một bộ ngữ cảnh dự án mỗi phiên như một con cá vàng. Cả hai công cụ sử dụng cùng định dạng: một thư mục, bên trong có một tệp SKILL.md, lưu hướng dẫn và siêu dữ liệu; ngoài ra có thể có tùy chọn script, tài liệu tham khảo và tệp tài nguyên. Codex sẽ chạy một skill khi bạn gọi nó bằng $ hoặc /skills, và cũng sẽ tự động chạy khi nhiệm vụ của bạn khớp với mô tả của skill đó. Đây cũng là lý do tại sao một mô tả ngắn gọn, đơn giản thường tốt hơn một mô tả thông minh, hoa mỹ. Cách làm của Claude Code cũng tương tự, tôi đã viết về mô hình này trong agent skills.
Skills cũng là nơi ý định không còn làm bạn hao tổn từng chút một. Tôi đã nói trong intent debt, agent khởi động lạnh mỗi khi bắt đầu phiên, chỉ cần ý định của bạn có khoảng trống, nó sẽ lấp đầy bằng những phỏng đoán đầy tự tin. Skill chính là viết ý định đó ra bên ngoài: quy ước dự án, các bước xây dựng, "chúng ta không làm điều đó vì lần đó đã xảy ra tai nạn", v.v., đều được viết một lần ở nơi mà agent sẽ đọc mỗi lần chạy. Không có skills, mỗi vòng lặp phải suy luận lại toàn bộ dự án của bạn từ đầu; có skills, nó giống như đang tăng trưởng lãi kép.
Cần phân biệt một điểm: skill là định dạng viết, plugin là cách phân phối. Khi bạn muốn chia sẻ một skill giữa nhiều kho mã nguồn, hoặc đóng gói một vài skill lại với nhau, bạn sẽ đóng gói chúng thành một plugin. Codex như vậy, Claude Code cũng vậy.
Plugins and connectors: Để vòng lặp tiếp xúc với công cụ thực của bạn
Một vòng lặp chỉ nhìn thấy hệ thống tệp là một vòng lặp rất nhỏ. Connectors được xây dựng dựa trên MCP, cho phép agent đọc trình theo dõi issue của bạn, truy vấn cơ sở dữ liệu, gọi API staging hoặc gửi tin nhắn trong Slack. Cả Codex và Claude Code đều hỗ trợ MCP, vì vậy connector bạn viết cho một bên thường cũng có thể sử dụng được ở bên kia. Plugins sẽ đóng gói connectors và skills lại với nhau, để đồng đội của bạn có thể cài đặt cấu hình đầy đủ một lần, thay vì xây dựng lại toàn bộ dựa trên trí nhớ.
Đây là sự khác biệt giữa "một agent nói với bạn 'đây là bản sửa lỗi'" và "một vòng lặp tự mở PR, liên kết ticket Linear và thông báo trên kênh khi CI pass". Connectors quan trọng vì chúng cho phép vòng lặp hành động trong môi trường thực của bạn, thay vì chỉ nói với bạn "nếu tôi có thể làm, tôi sẽ làm như vậy".
Sub-agents: Để người tạo ra xa khỏi người kiểm tra
Trong một vòng lặp, thiết kế cấu trúc hữu ích nhất, hơn xa việc tách biệt "người viết" và "người kiểm tra". Mô hình viết mã quá dễ dàng trở nên quá khoan dung khi tự chấm điểm bài tập của chính mình. Một agent khác mang theo hướng dẫn khác, đôi khi thậm chí sử dụng mô hình khác, có thể nắm bắt được những vấn đề mà agent đầu tiên đã tự thuyết phục bản thân bỏ qua.
Codex chỉ tạo subagents khi bạn yêu cầu, chúng sẽ chạy song song, sau đó hợp nhất kết quả thành một câu trả lời. Bạn có thể định nghĩa agents của riêng mình trong tệp TOML ở .codex/agents/: mỗi agent có tên, mô tả, hướng dẫn và tùy chọn mô hình và cường độ suy luận. Do đó, người kiểm tra an ninh của bạn có thể là một mô hình mạnh với cường độ suy luận cao, trong khi người thám hiểm của bạn có thể là một mô hình nhẹ, nhanh, chỉ đọc. Claude Code cũng thực hiện khả năng tương tự thông qua subagents và agent teams trong .claude/agents/, cho phép nhiều agent chuyển công việc giữa nhau. Sự phân công phổ biến nhất ở cả hai bên là: một agent thám hiểm, một agent triển khai, một agent xác minh theo quy chuẩn.
Tôi đã trình bày quan điểm này hai lần: một lần trong code agent orchestra, lần khác trong adversarial code review. Nó đặc biệt quan trọng trong vòng lặp, bởi vì vòng lặp chạy khi bạn không để mắt tới, vì vậy một verifier (người xác minh) mà bạn thực sự tin tưởng, là lý do duy nhất để bạn dám rời đi. Subagents thực sự tiêu thụ nhiều token hơn, vì mỗi agent phải thực hiện cuộc gọi mô hình và công cụ riêng, vì vậy bạn nên sử dụng chúng ở những nơi "đáng trả tiền cho ý kiến thứ hai". Điều này về cơ bản cũng là những gì /goal của Claude Code làm ở lớp dưới: một mô hình mới quyết định vòng lặp đã hoàn thành chưa, thay vì để mô hình đã hoàn thành công việc quyết định. Nghĩa là, nó áp dụng sự tách biệt "người tạo ra" và "người kiểm tra" vào chính điều kiện dừng.
Một vòng lặp trông như thế nào
Ghép những thứ này lại với nhau, một luồng đơn lẻ sẽ trở thành một bảng điều khiển nhỏ. Dưới đây là một cấu trúc tôi thường sử dụng.
Mỗi sáng, một automation chạy trên kho mã nguồn. Prompt của nó sẽ gọi một skill triage, đọc các lần thất bại CI ngày hôm trước, các issues đang mở, các commits gần đây và ghi phát hiện vào một tệp Markdown hoặc bảng Linear. Đối với mỗi vấn đề đáng xử lý, luồng sẽ mở một worktree cô lập, cử một sub-agent soạn thảo phương án sửa lỗi, rồi cử sub-agent thứ hai xem xét phương án này dựa trên project skills và các bài kiểm tra hiện có.
Connectors cho phép vòng lặp này tự mở PR và cập nhật ticket. Bất cứ thứ gì vòng lặp không xử lý được sẽ đi vào triage inbox, giao cho tôi xử lý. Tệp trạng thái là xương sống của toàn bộ hệ thống: nó ghi nhớ những gì đã thử, những gì đã pass, những gì vẫn chưa hoàn thành. Do đó, lần chạy vào sáng hôm sau sẽ tiếp tục từ nơi hôm nay dừng lại.
Hãy chú ý bạn thực sự đã làm gì. Bạn chỉ thiết kế một lần. Những bước đó không phải do bạn tự mình prompt từng cái một. Đây là phiên bản hiện thực của câu nói đó của Steinberger. Và cùng một vòng lặp có thể chạy trên Codex, cũng có thể chạy trên Claude Code, vì các thành phần bản thân chúng là cùng một bộ.
Vòng lặp vẫn sẽ không thay bạn làm gì
Vòng lặp thay đổi cách làm việc, nhưng không xóa bạn khỏi công việc. Trên thực tế, khi vòng lặp trở nên mạnh hơn, ba vấn đề sẽ trở nên gay gắt hơn, chứ không dễ dàng hơn.
Xác minh vẫn phụ thuộc vào bạn. Một vòng lặp chạy không giám sát cũng có thể đang mắc lỗi không giám sát. Lý do bạn tách verifier sub-agent và maker ra là để câu nói "đã hoàn thành" của vòng lặp có ý nghĩa phần nào. Dù vậy, "hoàn thành" vẫn là một tuyên bố, không phải là bằng chứng. Tôi vẫn lặp lại cùng một câu trong code review in the age of AI: trách nhiệm của bạn là giao mã mà bạn xác nhận có hiệu lực.
Nếu bạn bỏ mặc, sự hiểu biết của chính bạn vẫn sẽ mục nát. Vòng lặp càng nhanh chóng giao mã mà bạn không tự viết, khoảng cách giữa những gì bạn thực sự hiểu và những gì thực sự tồn tại trong hệ thống càng lớn. Đây là comprehension debt (nợ hiểu biết). Nếu bạn không đọc những gì vòng lặp tạo ra, một vòng lặp trơn tru chỉ khiến món nợ này tăng trưởng nhanh hơn.
Và, đúng vậy, tư thế thoải mái nhất rất có thể cũng là tư thế nguy hiểm nhất. Khi vòng lặp có thể tự chạy, bạn rất dễ dừng việc hình thành phán đoán của riêng mình, chỉ chấp nhận bất cứ thứ gì nó trả về. Tôi gọi đây là cognitive surrender (đầu hàng nhận thức). Nếu bạn thiết kế vòng lặp với sự phán đoán, nó là liều thuốc giải; nếu bạn thiết kế vòng lặp chỉ để trốn tránh suy nghĩ, nó là chất xúc tác tăng tốc. Cùng một hành động, dẫn đến kết quả hoàn toàn trái ngược.
Xây dựng vòng lặp, nhưng vẫn làm kỹ sư
Tôi cho rằng, điều này báo trước sự tiến hóa trong công việc tương lai của chúng ta. Dù vậy, nếu tôi không tự mình xem xét mã, hoặc hoàn toàn phụ thuộc vào vòng lặp tự động để sửa mã, chất lượng sản phẩm của tôi sẽ bị tổn hại. Tôi rất có thể rơi vào một vòng xoáy đi xuống: liên tục tự đào sâu vào hố.
Vì vậy, bạn tất nhiên có thể xây dựng vòng lặp của riêng mình, nhưng đừng quên, việc trực tiếp prompt agent của bạn vẫn hiệu quả. Điểm mấu chốt là tìm ra sự cân bằng phù hợp.
Kết quả của vòng lặp cũng sẽ khác nhau tùy người. Hai người có thể xây dựng cùng một vòng lặp hoàn toàn giống nhau, nhưng lại nhận được kết quả hoàn toàn trái ngược. Một người dùng nó để tăng tốc trên công việc mình hiểu sâu sắc; người kia dùng nó để trốn tránh việc hiểu chính công việc đó. Vòng lặp không biết sự khác biệt giữa hai điều này. Bạn biết.
Đây là lý do tại sao loop design (thiết kế vòng lặp) khó hơn prompt engineering (kỹ thuật prompt), chứ không dễ hơn. Ý của Cherny không phải là công việc trở nên dễ dàng hơn, mà là điểm đòn bẩy đã dịch chuyển.
Hãy xây dựng vòng lặp. Nhưng hãy xây dựng nó như một người vẫn có ý định làm kỹ sư, chứ không phải như một người chỉ chịu trách nhiệm nhấn nút "bắt đầu".






