Thiết kế môi trường thực thi có thể lập trình cho việc điều phối tác nhân

@realmcore_
TIẾNG ANH21 giờ trước · 03 thg 7, 2026
283K
260
45
10
456

TL;DR

Onyx giới thiệu một môi trường thực thi có thể lập trình cho các AI agent, cho phép các nhà phát triển xây dựng các hệ thống mang tính xác định bằng cách sử dụng TypeScript, trạng thái bền vững và xử lý lỗi có cấu trúc.

Bài viết này giới thiệu về Onyx, VM dành cho việc điều phối tác tử có thể lập trình. Và mở rộng ra, đó là một runtime biến việc điều phối thành kỹ thuật phần mềm. Đến cuối bài viết này, bạn sẽ hiểu được các ràng buộc và quyết định thiết kế đã được đưa ra để xây dựng VM, cũng như cách tạo các chương trình của riêng bạn và kiến trúc hệ thống tác tử của mình.

Giới thiệu

Các tác tử (agent) vốn dĩ là không xác định (non-deterministic). Đó là toàn bộ ý nghĩa của chúng. Nếu bạn muốn tính xác định, bạn sẽ viết phần mềm.

Nhưng ở một khía cạnh nào đó, tất cả những người sử dụng tác tử đều muốn đẩy chúng đi xa hơn. Chúng ta đã học được rằng việc chia nhỏ quá trình thực thi thành các bước có cấu trúc sẽ giúp cải thiện hiệu suất: Lên kế hoạch, Thực hiện, Đánh giá, Đảm bảo chất lượng, v.v. Sau đó, chúng ta dường như đã đồng ý viết các script, công cụ và kỹ năng để định hướng từng tác tử, chia sẻ ngữ cảnh giữa chúng và đặt ra các rào chắn (guardrail) cho chúng. Sau đó, chúng ta ghép nối các script này lại với nhau bằng cách chuyển văn bản qua lại giữa các tác tử, và vì chúng ta chỉ chuyển văn bản xung quanh nên nó có vẻ hoạt động.

Nếu bạn dành đủ thời gian cho vấn đề này và đặc biệt thông minh, bạn sẽ tìm ra cách để có được những đảm bảo từ hệ thống của mình để có thể thực thi có điều kiện dựa trên một trạng thái nhất định. Và bạn có thể sẽ lưu trữ trạng thái đó trong một tệp đánh dấu có thể phân tích cú pháp hoặc một tập hợp các tệp đánh dấu để định hướng các script bash của mình. Bạn thậm chí có thể đã xây dựng một CLI tùy chỉnh để các tác tử của mình sử dụng.

Là các kỹ sư, điều này thật quen thuộc, chúng ta sử dụng script trong khi thực hiện kỹ thuật phần mềm. Tuy nhiên, phần mềm hiện đại không được xây dựng bằng cách chuỗi các script bash và công cụ CLI. Thay vào đó, chúng ta có các ngôn ngữ lập trình, runtime và chuỗi công cụ để giúp chúng ta kỹ thuật hóa các hệ thống của mình. Chúng ta viết phần mềm bằng các ngôn ngữ lập trình vì chúng đi kèm với một thư viện chuẩn, ngữ nghĩa rõ ràng và một mô hình thực thi mà chúng ta có thể dựa vào. Chúng có hệ sinh thái phong phú với các chuỗi công cụ cho mọi nhu cầu của chúng ta.

Những đảm bảo mà chúng mang lại cho chúng ta về hệ thống cho phép chúng ta suy luận ở các mức độ trừu tượng cao hơn.

Nhưng không có sự tương đương nào cho việc kỹ thuật hóa các hệ thống tác tử. Để xây dựng các hệ thống, việc điều phối tác tử cần phải có thể lập trình được theo cùng một cách chính xác như phần mềm hiện đại.

Hôm nay, chúng tôi giới thiệu đặc tả cho PROGRAMS (*.program.ts), và Onyx, VM của chúng tôi được xây dựng để điều phối tác tử xác định. Bài viết này khám phá lịch sử của việc điều phối tác tử, ngữ nghĩa tĩnh và thời gian chạy của một VM có thể chạy một chương trình, và ý nghĩa của nó đối với hướng đi của lĩnh vực này.

Nghe có vẻ tốn kém, nhưng thực ra không phải vậy. Tôi sẽ giải thích điều này sau trong bài viết.

Đối với những ai tò mò, đây là Autoresearch của Andrej Karpathy trông như thế nào dưới dạng một chương trình:

akira - inline image

Các vấn đề chưa được giải quyết trong Điều phối Tác tử

Để hiểu một runtime cho việc điều phối tác tử nên bao gồm những gì, chúng ta cần hiểu những hạn chế của các tác tử.

Một tác tử LLM có thể được coi như một trình tạo luồng JSON, được đưa vào một trình phân tích cú pháp, sau đó phân phối các lệnh gọi công cụ đến một môi trường trong một vòng lặp.

Mọi lệnh gọi công cụ đều có cùng một hình dạng lược đồ bên ngoài, nhưng nội dung của luồng đầu ra này là không xác định.

Sự kết hợp giữa tính xác định và tính không xác định là điều đã làm cho các tác tử trở nên có giá trị. Chúng đủ linh hoạt để chuỗi các chuỗi hành động theo những cách độc đáo, nhưng đủ xác định để tương tác với máy tính thông qua các lệnh gọi công cụ.

Khả năng kết hợp gần như là miễn phí nếu bạn sẵn sàng từ bỏ yêu cầu rằng nội dung của luồng đó phải được định kiểu. Các mô hình đủ tốt để chuyển văn bản vào và ra trong các giới hạn mà chúng ta cung cấp cho chúng: lời nhắc, tin nhắn và lệnh gọi công cụ.

Điều này phơi bày một giao diện rất có thể kết hợp: văn bản

Văn bản là một giao diện phổ quát. Mọi thứ trên máy tính đều có thể được tuần tự hóa thành văn bản, ngay cả khi nó chỉ là mã máy. Nếu bạn có thể có một LLM đầu vào và đầu ra văn bản thông qua giao diện phổ quát này, bạn sẽ có được khả năng kết hợp trên các luồng văn bản.

Điều này có nghĩa là độ tin cậy của hành vi tác tử của bạn liên quan trực tiếp đến tính nhất quán của đầu ra từ mô hình. Sự biến thiên đầu ra cao có nghĩa là hành vi tác tử thất thường hơn.

Một khi bạn có một giao diện để kết hợp các phần lại với nhau, ràng buộc tiếp theo bạn quan tâm là khả năng điều khiển (steerability)** :

bạn muốn tác tử làm gì và làm thế nào để bạn nhất quán khiến nó làm điều bạn muốn

Chúng ta điều khiển các tác tử bằng cách dịch chuyển phân phối mà nó lấy mẫu, nói cách khác, là prompting.

Vào năm 2022, ReAct ra đời và về cơ bản đã đi tiên phong trong khả năng điều khiển của tác tử. Trên thực tế, chúng ta có thể nói rằng nó đã tạo ra các tác tử như chúng ta biết. Việc suy nghĩ và lý luận về đầu ra của một công cụ trước khi thực hiện bước tiếp theo là điều giữ cho vòng lặp mạch lạc.

akira - inline image

Chúng ta vẫn cần các tác tử thông minh hơn. Việc sử dụng tính toán mở rộng thời gian thử nghiệm (test time compute scaling), được sản xuất hóa bởi dòng mô hình O-series của @OpenAI, đã cho các phòng thí nghiệm mô hình khả năng tích hợp hành vi tác tử tốt hơn [[11]](http://localhost:5173/blog/onyx#ref-11). Việc xuất ra nhiều token hơn trước khi gọi một công cụ cho phép mô hình thoát khỏi phân phối đầu ra mà nó có thể bị mắc kẹt nếu bị giới hạn về độ dài đầu ra suy luận. Bạn có thể chọn cách huấn luyện mô hình di chuyển qua bối cảnh phân phối đầu ra của nó, và do đó có quyền tự do huấn luyện các hành vi tác tử rõ ràng hơn trong các nhiệm vụ bạn quan tâm.

Khi độ dài ngữ cảnh tăng lên không giới hạn, việc điều khiển tác tử trở nên khó khăn và khả năng hoàn thành nhiệm vụ trở nên ít hơn. Ngay cả với một mô hình suy luận, không có gì đảm bảo về sự phục hồi, và tác tử sẽ chết ngay tại đó. Tác tử có thể đạt đến giới hạn ngữ cảnh, tuyên bố hoàn thành sớm, bị mắc kẹt trong một vòng lặp, v.v.

Kéo các Đảm bảo ra khỏi một Hệ thống Không xác định

Các giải pháp cho vấn đề này rất đa dạng, nhưng có một giải pháp nổi bật: Vòng lặp Ralph, được tạo bởi @GeoffreyHuntley. [[3]](http://localhost:5173/blog/onyx#ref-3

Ông ấy đưa ra ý tưởng rằng bạn có thể giới hạn việc thực thi tác tử, và sau đó sử dụng các giới hạn đó để suy luận về việc hoàn thành nhiệm vụ. Điều này cho phép Vòng lặp Ralph làm một điều kỳ diệu: nó cung cấp một thứ mà bạn có thể dựa vào trong một hệ thống không xác định.

Một tia sáng của tính xác định.

Tốt hơn là đảm bảo thất bại và từ từ tiến dần đến một thứ gì đó đúng đắn, hơn là kéo cần máy đánh bạc thêm một lần nữa. Ranh giới được xác định này cung cấp cho bạn một thứ cụ thể để suy luận và một khi bạn có thể suy luận về ranh giới của một thứ gì đó, bạn có thể tạo ra một hệ thống từ nó.

Chiến đấu với giới hạn của độ dài ngữ cảnh

Tuy nhiên, có một vấn đề, một tác tử mới mất đi sự mạch lạc giữa các lần chạy, nhưng một tác tử duy nhất sẽ hết ngữ cảnh nếu có đủ thời gian.

Hãy đến với RLM bởi @lateinteraction @a1zhang. RLM đã cho chúng ta một khái niệm về cách tương tác với ngữ cảnh dài (ví dụ: một lần chạy tác tử) một cách có cấu trúc [[4]](http://localhost:5173/blog/onyx#ref-4). RLM được lấy cảm hứng từ CodeAct, một bài báo năm 2024 đã chứng minh việc sử dụng mã để điều phối các hoạt động [[5]](http://localhost:5173/blog/onyx#ref-5). Tác tử viết các script điều phối các hoạt động bên trong một REPL để sau đó lấy đầu ra. RLM hoạt động theo cùng một cách với điểm bổ sung là nó sử dụng các biến để lưu trữ ngữ cảnh và thực hiện các thao tác trên ngữ cảnh đó. Nó cũng cho phép các lệnh gọi LLM đệ quy trong REPL. Bạn có thể mất một số khả năng phản ứng mà các vòng lặp khác có, nhưng bạn có được khả năng làm việc với ngữ cảnh một cách lập trình. Điều quan trọng ở đây là các script trong REPL là tạm thời (ephemeral). Bạn có một runtime viết script và quản lý ngữ cảnh, nhưng không có khả năng tái sử dụng hoặc kết hợp. Chỉ cần viết script, chạy nó và nó biến mất. Về mặt xây dựng hệ thống, điều này hoàn toàn tệ hơn so với việc chỉ chuỗi các tác tử và tệp đánh dấu với các script bash vì bạn mất đi tính bền vững và thực thi có giới hạn.

Từ các vòng lặp riêng lẻ đến việc mở rộng quy mô điều phối

Deep research của OpenAI[[6]](http://localhost:5173/blog/onyx#ref-6) là một trong những ví dụ sớm nhất về một quy trình làm việc xác định có hình dạng hoặc lược đồ thực thi chung với sự biến thiên nhỏ trên cơ sở từng lần chạy. Cách nó hoạt động là lập kế hoạch cho một loạt các truy vấn, chạy chúng trên web, xem xét kết quả và lập kế hoạch cho loạt truy vấn tiếp theo. Mỗi loạt truy vấn thăm dò sâu hơn vào không gian vấn đề.

akira - inline image

Cursor đã đưa ý tưởng về tính xác định đi xa hơn nhiều khi @wilsonzlin trình diễn một bộ khai thác (harness) điều phối các tác tử để xây dựng một trình duyệt. Anh ấy đã xây dựng một bộ khai thác tùy chỉnh để điều phối một lượng lớn công việc bằng cách sử dụng các tác tử lập kế hoạch song song và các tác tử nhiệm vụ [[7]](http://localhost:5173/blog/onyx#ref-7). Điều có liên quan ở đây là mối quan hệ giữa mỗi phần của bộ khai thác là cố định. Có các bộ lập kế hoạch, khám phá trạng thái hệ thống hiện tại và tạo ra các nhiệm vụ, và có các bộ thực thi, nhận nhiệm vụ và thực hiện chúng song song. Có các rào chắn cố định giữa các tác tử và các kênh cố định để truyền đạt thông tin. Để phối hợp tốt, bạn cần có các đảm bảo về giao diện.

Sử dụng các điều kiện kết thúc để thực thi có giới hạn

Vào tháng 5, Codex đã giới thiệu ý tưởng về một mục tiêu (goal) sử dụng một vòng lặp xác minh để leo đồi (hillclimb) chống lại một số trạng thái kết thúc mong muốn cho đến khi một nhiệm vụ hoàn thành. Bạn có thể coi đây là một phiên bản sẵn sàng sản xuất của vòng lặp Ralph, được tích hợp vào codex. Nó cho phép bạn chỉ định một mục tiêu và có một vòng lặp tự động thực thi và xem xét, được tích hợp sẵn.

akira - inline image

Autoresearch của Karpathy[[9]](http://localhost:5173/blog/onyx#ref-9) tương tự như /goal của Codex và vòng lặp Ralph. Nó kết hợp điều kiện kết thúc có thể xác minh của goal với giới hạn thực thi của vòng lặp Ralph qua các lần lặp, cho phép nó liên tục hướng tới một mục tiêu. Nó tiến bộ bằng cách tìm kiếm không gian ý tưởng, cải thiện lặp đi lặp lại theo thời gian.

akira - inline image

Cho đến thời điểm này, tất cả các giải pháp ngoại hóa việc điều phối bên ngoài tác tử đều cố định về hình dạng đồ thị thực thi của chúng. Chúng chạy bằng cách sử dụng một mẫu viết tay và có một loại lược đồ cho các hình dạng được phép mà chúng có thể hoạt động. Chúng không thích ứng theo từng nhiệm vụ hoặc chúng không có các đảm bảo mạnh mẽ về hình dạng đồ thị thực thi nói chung.

Làm cho việc điều phối trở nên linh hoạt

Vào tháng 3 năm nay, chúng tôi đã giới thiệu Slate, tác tử viết mã đầu tiên sử dụng mã để điều phối tác tử phụ trực tiếp theo phong cách RLM. Nó vẫn là tác tử viết mã được sử dụng nhiều duy nhất sử dụng mã để điều phối tác tử trực tiếp. Trong Slate, các luồng có thể được sinh ra, tạm dừng, tiếp tục và điều khiển trong thời gian thực. Tác tử chính hiểu sâu sắc cách điều phối tất cả các tác tử phụ đang chạy để bạn không cần phải làm vậy. Tuy nhiên, tương tự như RLM, chúng tôi vẫn phải đối mặt với thách thức về việc chia sẻ trạng thái giữa các tác tử phụ và việc viết script tạm thời, điều không phải là thứ bạn gặp phải khi sử dụng script bash và tệp đánh dấu.

Ngay cả như vậy, nếu mô hình là người thực hiện việc điều phối, làm thế nào để bạn điều khiển nó? Bạn có bảo nó viết mã điều phối của nó theo một cách cụ thể không? Bạn làm gì?

Giải pháp ban đầu của chúng tôi (như một bản vá trước khi phát hành runtime Onyx) được gọi là kỹ năng điều phối (orchestration skills) [[13]](http://localhost:5173/blog/onyx#ref-13). Ý tưởng rất đơn giản, cho phép người dùng cung cấp một kỹ năng để định hướng cách tác tử tiếp cận việc điều phối của nó. Chỉ vậy thôi. Nó hoạt động ổn, nhưng có rất nhiều vấn đề.

Cụ thể, một kỹ năng không phải là một hợp đồng hành vi ràng buộc. Bạn không thể có được một sự đảm bảo từ văn bản.

Điều này có nghĩa là bộ điều phối không phải tuân theo mẫu thực thi mong muốn vì không có cách thực sự để thực thi nó. Một trong những lợi ích lớn nhất của runtime Onyx là chúng tôi đã giải quyết được vấn đề này.

Không có hệ thống nào được đề cập có các hợp đồng hành vi ràng buộc.

Vậy thì, điều gì sẽ xảy ra nếu tác tử có thể viết mã điều phối của nó thành một script cho mỗi nhiệm vụ để đồ thị thực thi được cố định? Đây là những gì quy trình làm việc động của Claude là.[[10]]([http://localhost:5173/blog/onyx#ref-10)[[12]](http://localhost:5173/blog/onyx#ref-12](http://localhost:5173/blog/onyx#ref-10)[[12]](http://localhost:5173/blog/onyx#ref-12) Theo cùng một phong cách như RLM và Slate, bằng cách viết mã để điều phối các tác tử phụ, quy trình làm việc động cho phép Claude viết và lưu các hình dạng quy trình làm việc. Điều này kết hợp với /loop để có thể lặp lại các mẫu cụ thể. Nó cung cấp một hợp đồng khai báo cho hành vi của một tập hợp các tác tử. Nó vẫn không giống như viết phần mềm vì nó thiếu những thứ như thành phần chức năng, nhưng bạn có được tính bền vững và một sự đảm bảo mạnh mẽ về cách nhiệm vụ sẽ được thực thi. Chúng là các script quy trình làm việc được viết một cách linh hoạt cho một nhiệm vụ nhất định một cách đặc biệt.[[12]](http://localhost:5173/blog/onyx#ref-12) Và vì chúng được lưu trữ trên đĩa nên chúng có một lợi ích bổ sung: chúng có thể được chạy lại và bọc bằng keo điều phối như /loop.

akira - inline image

Nếu bạn để ý, tất cả các giải pháp trên đều hướng đến cùng một thứ: một cách xác định để kiểm soát cách các tác tử thực thi theo thời gian.

Đây là một câu chuyện mà chúng ta đã chứng kiến diễn ra trong lĩnh vực kỹ thuật phần mềm. Chúng ta bắt đầu bằng cách ghép nối các hệ thống khác nhau và các công việc viết script, và sau đó các ngôn ngữ của chúng ta trở nên linh hoạt và mạnh mẽ hơn. Chúng ta ngày càng có nhiều đòn bẩy hơn trong quy trình kỹ thuật với các hệ sinh thái mạnh mẽ hơn cho phép chúng ta xây dựng các hệ thống đáng tin cậy hơn ở các mức độ trừu tượng cao hơn.

Ngay bây giờ, các tác tử đang đi trên cùng một quỹ đạo, và hôm nay chúng tôi đang phát hành bước tiếp theo trên quỹ đạo đó để cho phép bạn kỹ thuật hóa các hệ thống chạy các tác tử của mình. Các ngôn ngữ lập trình thường sử dụng trình thông dịch hoặc VM để lên lịch tài nguyên một cách tự động. Đây là điều mang lại cho bạn đòn bẩy với tư cách là một kỹ sư sử dụng ngôn ngữ đó.

Nếu một VM có ý nghĩa đối với việc điều phối tác tử, bạn sẽ cần một vài thứ:

  1. Quản lý trạng thái bền vững: chúng ta có thể định nghĩa trạng thái, tham chiếu nó bằng tên, duy trì nó và thao tác nó một cách lập trình.
  1. Đảm bảo về kiểu dữ liệu. Chúng ta nên tôn trọng các hình dạng đầu vào và đầu ra đã xác định và tuân theo chúng, đồng thời có thể dựa vào chúng.
  1. Các nguyên thủy luồng điều khiển, tốt nhất là những nguyên thủy nổi tiếng mà một LLM sẽ hiểu.
  1. Cấu trúc rõ ràng để xử lý lỗi (ví dụ: try-catch).
  1. Quản lý tài nguyên: các kiểm soát xác định đối với các tài nguyên như tính song song của tác tử, chi phí, mô hình nào đang chạy, v.v.
  1. Cô lập thực thi: Một tác tử hoặc chương trình đang chạy phải được cô lập khỏi một tác tử khác trừ khi trạng thái được chia sẻ một cách rõ ràng.
  1. Kiểm soát vòng đời: một chương trình tác tử trông như thế nào và ngữ nghĩa để chạy, hủy bỏ và điều khiển. Nếu không có điều này, bạn không có con đường rõ ràng để dọn dẹp và không thể kiểm soát việc quản lý vòng đời.
  1. Khả năng kết hợp: Các chương trình nên kết hợp với nhau và có thể được gọi với các kiểu đầu vào và đầu ra đã xác định.
  1. Khả năng hiển thị: Chúng ta nên biết cái gì đã chạy, khi nào và có thể truy ngược lại một lỗi thực thi trong mã nguồn.
  1. Độ bền: Chúng ta nên có một mô hình rõ ràng về cách chúng ta có thể phục hồi sau sự cố và tiếp tục.

Mỗi một vấn đề trong số này đều là vấn đề đã được giải quyết bởi các ngôn ngữ lập trình từ nhiều thập kỷ trước. Việc điều phối tác tử chỉ đang gặp lại tất cả chúng lần đầu tiên.

Để thực sự có thể viết phần mềm cho việc này, một chương trình "program.ts" phải được tác giả trong một runtime hỗ trợ tất cả những điều trên, để chúng ta có thể suy luận về những gì sẽ xảy ra khi một chương trình không hoạt động và kỹ thuật hóa xung quanh sự cố.

Đây là lý do tại sao chúng tôi xây dựng Onyx. Đó là một VM điều phối tác tử được thiết kế chính xác để hỗ trợ cả các chương trình kết hợp bền vững và một lớp viết script được thông dịch. Đây là cách nó hoạt động và những gì một runtime tương thích "program.ts" cần hỗ trợ.

Thiết kế runtime

Khi chúng ta thiết kế một ngôn ngữ và một runtime cho ngôn ngữ đó, chúng ta cần suy nghĩ về các ràng buộc mà chúng ta muốn có thể suy luận và những gì chúng ta quan tâm đến việc dễ dàng diễn đạt. Sau đó, chúng ta có thể chia ngữ nghĩa kết quả thành hai loại: ngữ nghĩa tĩnh và ngữ nghĩa thời gian chạy.

Ngữ nghĩa tĩnh là tất cả những thứ có thể được suy ra về một chương trình chỉ bằng cách nhìn vào nó. Những thứ mà một trình biên dịch hoặc trình kiểm tra kiểu biết về một chương trình nhất định.

Ngữ nghĩa thời gian chạy xác định mã thực sự có nghĩa là gì và chương trình thực sự chạy như thế nào. Điều này bao gồm các cơ chế phân bổ tài nguyên và lập lịch cơ bản.

Mục tiêu của chúng tôi với một runtime cho các tác tử là biến luồng điều khiển điều phối thành mã và chúng tôi muốn làm cho trạng thái thực thi trở nên bền vững và được định kiểu để chúng tôi có thể sử dụng nó một cách đáng tin cậy để điều khiển việc điều phối.

Một vài yêu cầu của VM

Có 3 điều cụ thể về VM mà chúng tôi quan tâm ngoài việc thực thi TypeScript thông thường.

  1. Là một runtime điều phối tác tử, nó cần có khả năng điều phối các tác tử. Điều này có nghĩa là tạo ra chúng, theo dõi vòng đời của chúng, v.v. Chúng tôi muốn runtime có thể chạy chúng theo cách chặn hoặc không chặn và lên lịch cho chúng một cách chính xác.
  1. Chúng tôi muốn kiểm soát các hình dạng đầu ra của các tác tử và muốn thực thi hợp đồng đầu ra nghiêm ngặt.
  1. Chúng tôi muốn có quyền kiểm soát thời gian chạy đối với các tài nguyên bên ngoài như mô hình và chi phí.

Chạy Tác tử và Chương trình

Để chạy một tác tử, chúng tôi đã chọn hai động từ cơ bản: run và spawn. Run chạy một tác tử chặn ở nền trước. Spawn chạy một tác tử ở nền. Điều này phù hợp với sự hiểu biết phổ biến về spawn, như posix_spawn, giúp một mô hình dễ dàng hiểu các động từ mới của chúng tôi vì chúng về mặt khái niệm nằm trong dữ liệu huấn luyện. Spawn và run cho phép bạn gọi trực tiếp các tác tử và chương trình được đọc từ đĩa, trả về đủ thông tin cho một handle thực thi.

Run cũng hỗ trợ một vài thứ. Nó hỗ trợ các kiểu đầu ra được thực thi trực tiếp thông qua zod @colinhacks và hỗ trợ ghi đè mô hình trực tiếp, giúp dễ dàng viết và chạy các chương trình mà việc phân nhánh ra nhiều mô hình khác nhau cho các giải pháp khác nhau hoặc các bước khác nhau của một nhiệm vụ là hợp lý.

typescript
1function run<S extends z.ZodType>(
2 name: string,
3 options: ...
4): Promise<z.infer<S>>

Run cho phép bạn chuỗi trực tiếp các tác tử phụ nội tuyến.

typescript
1// chạy tác tử đơn giản
2const out = await run({ type: "read", prompt: () => "Reply with: ok" })
3// chạy có tên (string = child workflowId)
4const review = await run("reviewer", {
5 type: "general",
6 prompt: () => "Review the diff",
7})
8// đầu ra có cấu trúc (kết quả đã định kiểu)
9const Verdict = z.object({ risk: z.enum(["low", "high"]), why: z.string() })
10const v = await run({
11 type: "general",
12 prompt: () => "Assess risk",
13 output: Verdict,
14})

Spawn tương tự như run nhưng tạo một tác tử ở nền. Các tác tử phụ được spawn không được chờ đợi và luồng điều khiển chỉ tiếp tục. Spawn rất hữu ích để khởi động một số tác tử thực thi không chặn.

typescript
1// tác tử nền
2const h = await spawn("worker", { type: "general", prompt: "Long task" })

Tương tác với các tác tử đang chạy

Chúng tôi muốn có thể thực hiện hai loại thao tác trên các tác tử đang chạy: điều khiển (steering) và dừng (stopping).

Một tin nhắn điều khiển là một tin nhắn được gửi đến tác tử mà LLM sẽ nhận được trong khi nó đang chạy để đẩy nó theo một hướng. Điều này hữu ích để cập nhật ngữ cảnh nhiệm vụ của tác tử mà không cần phải phá hủy worker.

Việc hủy bỏ cũng rất quan trọng, chúng tôi muốn có thể chủ động phá hủy một tác tử phụ nếu nó không nên chạy.

Có thể chạy các thao tác này từ cả REPL trực tiếp và một chương trình được tác giả trước cho Slate khả năng điều phối mọi thứ trong thời gian thực. Nó có thể xác định linh hoạt hình dạng của việc điều phối tại thời gian chạy hoặc nó có thể tác giả và lặp lại trên phần mềm thực để thực hiện việc điều phối.

Slate có thể viết các chương trình vào các tệp \.program.ts. Một tệp chương trình có một vài thứ: tên của nó (đây là cách Slate biết nó là gì), một mô tả JSDoc và sau đó là phần thân chương trình thực tế*. Một khai báo chương trình trông như thế này:

typescript
1program(async (ctx) => {
2 // mô hình rẻ cho tìm kiếm — nó chỉ cần tìm tệp
3 const findings = await run("search", {
4 type: "read",
5 prompt: "Find all authentication-related files",
6 model: "codex/gpt-4.1-mini", // sử dụng khóa codex tích hợp của bạn
7 })
8})

Các chương trình tuân theo cùng một mô hình thực thi bất đồng bộ cho phép chúng tôi chạy một chương trình ở cả nền trước và nền, đồng thời tương tác với nó trong khi nó đang chạy.

typescript
1// tác tử nền
2const h = await spawn("worker", { type: "general", prompt: "Long task" })
3await h.notify("focus on the parser first") // tin nhắn điều khiển đến tác tử đang chạy
4const result = await h.result() // chờ hoàn thành sau// phân nhánh, sau đó thu thập
5const a = await spawn({ prompt: "task A" })
6const b = await spawn({ prompt: "task B" })
7const [ra, rb] = [await a.result(), await b.result()]// chạy nền một chương trình
8import Audit from "deep-audit"
9const ah = await spawn(Audit, { input: { pr: 42 } })
10const auditResult = await ah.result()

Đầu ra có cấu trúc và trạng thái

Đây là một hạn chế chính của mọi hệ thống khác cho đến nay. Trạng thái, trong tất cả các hệ thống khác, được ngoại hóa kém và không được cô lập an toàn. Nếu nó là một tệp trên hệ thống, bạn không thể đảm bảo không bị hỏng. Nếu bạn có thể, bạn vẫn không thể đảm bảo khả năng phân tích cú pháp. Bạn không thể đăng ký các thay đổi trạng thái để điều khiển các hoạt động và bạn không thể đảm bảo tuân thủ kiểu dữ liệu.

Hãy nhớ cách chúng ta muốn trạng thái bền vững cũng có cấu trúc và có thể được tham chiếu?

Trạng thái, trong Onyx, là khác biệt. Các không gian tên trạng thái được khai báo, đặt tên trực tiếp và duy trì theo thời gian. Điều này có nghĩa là một kho lưu trữ trạng thái có thể được sử dụng đi sử dụng lại nhiều lần, cho phép bạn xây dựng các hệ thống tác tử chạy lâu dài với dữ liệu thực.

Cả tác tử và mã đều đọc trạng thái, và tính xác định mà chúng tôi muốn từ một runtime xuất phát từ điều này. Các tác tử đọc trạng thái thông qua một công cụ chuyên dụng cho phép chúng luôn tương tác với nó một cách an toàn và có cấu trúc. Các tác tử và chương trình đều là những người tiêu dùng có thể được điều khiển để sửa đổi trạng thái, điều này cho phép runtime dựa vào đối tượng trạng thái để điều khiển việc điều phối.

Trạng thái và sự tuân thủ lược đồ, kiểm soát việc hoàn thành tác tử phụ. Do đó, trạng thái cung cấp một bề mặt thống nhất để điều khiển toàn bộ chương trình.

Các đối tượng trạng thái cũng có thể được truyền dưới dạng các biến thời gian chạy xuống các phiên con được chia sẻ với tác tử chính. Quyền truy cập tham chiếu này trong toàn bộ hệ thống phân cấp tác tử (đây là lần đầu tiên có) cho phép giao tiếp giữa các tác tử thông qua một kênh trạng thái được chia sẻ.

akira - inline image

Các vòng lặp chạy dài

Một số chương trình cần hoạt động giống như các hệ thống đang chạy. Lấy openclaw làm ví dụ. Bạn thực sự có thể biểu diễn openclaw dưới dạng một chương trình với các nguyên thủy phù hợp. Đối với điều này, chúng tôi sử dụng hai nguyên thủy: sleep và checkpoint.

Sleep làm những gì bạn mong đợi, nó ngủ.

Bây giờ, vấn đề là, giả sử bạn muốn một số quản lý tác vụ chạy dài ở nền. Một đồ thị thực thi được xác định trước có thể bị kẹt hoặc hỏng, và do đó, điều quan trọng là tác tử chính phải nhận thức được trạng thái của chương trình.

Để hỗ trợ điều này, chúng tôi giới thiệu nguyên thủy checkpoint.

Một checkpoint có thể là bất cứ thứ gì, nhưng lý do nó được đặt tên là checkpoint là vì nó thông báo cho tác tử chính bằng một đối tượng có hình dạng cố định. Điều này cho phép tác tử chính theo dõi những thứ như tiến độ nhiệm vụ và được thông báo trực tiếp về những thay đổi trong trạng thái chương trình. Đổi lại, tác tử chính sau đó có thể quản lý một chương trình đang chạy hiệu quả hơn.

Onyx hỗ trợ tạo một vòng lặp tác tử như Openclaw, tức là một tác tử bền bỉ với một nhịp tim (heartbeat).

Điều này thực sự rất thú vị, bạn có thể kết hợp các nguyên thủy (primitives) thành một loại agent hoàn toàn khác chỉ bằng cách sử dụng một vòng lặp while, một lệnh sleep và một checkpoint.

Openclaw có thể được biểu diễn đơn giản như một tệp chương trình!

typescript
1// Một chương trình để chạy một vòng lặp tự động nghiên cứu dài hạn
2for (let i = 0; i < maxExperiments; i++) {
3 const idea = await run("propose", { ... })
4 const result = await run("train", { ... })
5 checkpoint({ message: `thí nghiệm ${i}`, data: { idea, result } })
6 await sleep(30_000) // nghỉ giữa các thí nghiệm
7}
8
9// Một chương trình để chạy một agent kiểu openclaw liên tục
10while(true) {
11 const status = await run("status_check", { ...chèn mô hình rẻ ở đây... })if(status.pending_tasks) {checkpoint({ tasks: status.pending_tasks }) // trả về trạng thái quan trọng và đánh thức agent chính}
12 await sleep(30_000) // nghỉ giữa các thí nghiệm
13}

Sự kết hợp (Composition)

Với Onyx, Slate có thể viết một tệp *.program.ts cho bạn. Tệp này tồn tại lâu dài và có thể (và nên) được xử lý giống như mã nguồn thông thường. Nó có các kiểu dữ liệu (types) đi kèm ngay từ đầu, chạy trong một môi trường runtime đã được loại bỏ các biến toàn cục, và vì nó chỉ là TypeScript, nên mô hình kết hợp của nó chỉ đơn giản là import và gọi một chương trình khác.

Bởi vì nó chỉ là TypeScript, bạn có được các tính năng như song song hóa (Promise.all) và vòng lặp một cách miễn phí.

Đây là cách bạn import một chương trình và sử dụng nó trong một chương trình khác:

typescript
1import Audit from "deep-audit"program (() => {const ah = await spawn(Audit, { input: { pr: 42 } })
2 const auditResult = await ah.result()
3 const fixer = await run("fixer", ... đầu ra của audit) // cái này sẽ chạy và sửa đầu ra của chương trình audit.
4})

Ngữ nghĩa lỗi (Error semantics)

Lỗi, trong VM lý tưởng, được ném ra một cách rõ ràng (loudly). Chúng nên được ném ra khi có vấn đề về cú pháp runtime, lỗi agent, sự cố, v.v.

Cụ thể, chúng tôi định nghĩa các lỗi điều phối (orchestration errors) như sau:

  • Một agent bị chặn bởi một tác vụ
  • Một agent không hoàn thành được một tác vụ
  • Một agent đã hết số bước hoặc ngân sách cho một tác vụ
  • Một chương trình đã hết ngân sách cho một lần chạy
  • Mô hình điều phối không thể viết mã nguồn đúng cú pháp
  • Một sửa đổi trạng thái bất hợp pháp được thực hiện

Tất cả các trường hợp lỗi cụ thể này đều định nghĩa ngữ nghĩa runtime. Chúng nói rằng, "Bạn có thể mong đợi runtime này sẽ ném lỗi, bởi vì chúng tôi coi lỗi thực thi agent cũng giống như lỗi trong mã nguồn". Nó có vẻ hơi khó chịu lúc đầu, nhưng cơ chế báo lỗi rõ ràng này mang lại cho bạn một thứ gì đó đáp lại: một cách rõ ràng để chuẩn bị và lập trình xung quanh các lỗi. Vì vậy, trên thực tế, nó mang lại cho bạn nhiều quyền kiểm soát hơn, chứ không phải ít hơn.

typescript
1// lỗi được xử lý bằng try/catch — giống như bất kỳ chương trình TypeScript nào
2program(async (ctx) => {
3 try {
4 const result = await run("risky-refactor", {
5 type: "general",
6 prompt: "Tái cấu trúc module xác thực",
7 model: "claude-sonnet",
8 maxSteps: 20,
9 })
10 } catch (err) {
11 // agent đã thất bại — nhưng chúng ta biết chính xác lý do.
12 // trace có mọi lệnh gọi tool, mọi yêu cầu model,
13 // mọi ghi trạng thái đã dẫn đến đây.
14
15 // thử lại với một model khác
16 const result = await run("risky-refactor-retry", {
17 type: "general",
18 prompt: `Lần thử trước đã thất bại: ${err.message}. Hãy thử một cách tiếp cận khác.`,
19 model: "claude-opus",
20 maxSteps: 30,
21 })
22 }
23})

Lựa chọn model, thực thi ngân sách và BYOK

Việc lựa chọn model được tích hợp sẵn cho phép bạn kiểm soát chính xác hơn nữa. Kỹ năng /models cung cấp cho Slate toàn bộ quyền truy cập vào danh sách các model có sẵn, cho phép Slate tạo ra các chương trình với nhiều model khác nhau thực hiện các công việc khác nhau. Muốn Fable là người lập kế hoạch, nhưng GLM 5.2 thực hiện bên trong một harness xác định? Được thôi. Muốn phân tán một câu hỏi qua Gemini, GPT 5.5 và DeepSeek? Điều đó cũng hiệu quả.

Ngoài ra, runtime hỗ trợ hai loại ghi đè cấu hình cho các chương trình:

  • Các model toàn cục mặc định được sử dụng để thực thi agent
  • Ngân sách để chạy một chương trình

Bạn có thể trực tiếp đặt ngân sách chạy để giới hạn chi tiêu cho một vòng lặp nhất định.

Ngoài ra, runtime hỗ trợ sử dụng các đăng ký OpenAI và Github Copilot hiện có của bạn.

typescript
1program(async (ctx) => {
2 // model rẻ cho tìm kiếm — nó chỉ cần tìm tệp
3 const findings = await run("search", {
4 type: "read",
5 prompt: "Tìm tất cả các tệp liên quan đến xác thực",
6 model: "codex/gpt-4.1-mini", // sử dụng khóa codex tích hợp của bạn
7 })
8
9 // model suy luận cho phần khó — nó cần phải suy nghĩ
10 const plan = await run("architect", {
11 type: "general",
12 prompt: `Thiết kế một bản sửa lỗi dựa trên: ${findings.output}`,
13 model: "openai/o3", // Cuối cùng sẽ sử dụng tín dụng api
14 output: z.object({
15 approach: z.string(),
16 files: z.array(z.string()),
17 risk: z.enum(["low", "medium", "high"]),
18 }),
19 })
20
21 // model tầm trung cho việc triển khai — nó chỉ cần chỉnh sửa
22 const handles = await Promise.all(
23 plan.files.map(f => spawn("fix-" + f, {
24 type: "general",
25 prompt: `Áp dụng bản sửa lỗi này cho ${f}: ${plan.approach}`,
26 model: "anthropic/claude-sonnet-5",
27 maxSteps: 15,
28 }))
29 )
30 await Promise.all(handles.map(h => h.result()))
31})

Định nghĩa bề mặt tác giả (authoring surface)

Có hai yếu tố chính trong việc thiết kế bề mặt tác giả cho các chương trình: mức độ dễ hiểu đối với một agent và mức độ dễ đọc đối với một con người. Chúng tôi đã chọn các động từ tương đối đơn giản, đọc giống như tiếng Anh, và quyết định rõ ràng rằng chúng tôi muốn mô hình hóa sự điều phối một cách thủ tục (procedurally) thay vì khai báo (declaratively).

Việc lựa chọn TypeScript làm ngôn ngữ cũng rất quan trọng. Có rất nhiều mã TypeScript thủ tục ngoài kia mà một model sẽ ngầm hiểu ngữ nghĩa của TypeScript, ngay cả khi không có quá trình hậu huấn luyện (post-training).

akira - inline image

Các mảnh ghép kỹ thuật trong nhà máy phần mềm của chúng tôi

Câu hỏi tiếp theo cần trả lời là: tất cả những điều này mang lại cho bạn điều gì?

Nó mang lại cho bạn khả năng viết phần mềm thực sự cho việc điều phối agent của bạn. Giờ đây bạn có thể tự thiết kế việc điều phối agent của mình từ đầu đến cuối.

Bạn có thể thiết kế nhà máy (factory).

Ví dụ, bạn có thể tạo một chương trình giám sát Github trong một vòng lặp, và một chương trình riêng biệt chạy một agent triển khai với một agent QA để xem xét. Cả hai đều là những mẫu hữu ích riêng lẻ mà bạn có thể gặp trong thực tế. Sau đó, bạn có thể kết hợp chúng lại để tạo ra một hệ thống lắng nghe các bình luận trên một PR, sinh ra một agent triển khai để giải quyết các bình luận đó, và sau đó sinh ra một agent QA để đảm bảo bản sửa lỗi là hợp lệ.

Sau đó, bạn có thể sử dụng chương trình này được kết nối với một hàng đợi tác vụ để ủy quyền và giám sát công việc trên cơ sở mã nguồn của bạn, và tự động phản hồi các bình luận PR.

Và bạn có thể làm tất cả điều đó bằng cách sử dụng các model mã nguồn mở nhanh. Bởi vì nó chỉ là mã nguồn, bạn không cần một LLM mạnh mẽ để suy nghĩ về sự điều phối sau khi nó được tạo ra lần đầu tiên.

Bây giờ đến phần thú vị, đã đến lúc chia sẻ một số chương trình chúng tôi đã sử dụng để tăng sản lượng một cách đáng kể.

Nghiên cứu sâu về cơ sở mã nguồn (Deep Codebase Research)

Chúng tôi sử dụng chương trình này để giúp xác định phạm vi của các tác vụ. Nó thực hiện nghiên cứu sâu về trạng thái của monorepo của chúng tôi và chuẩn bị một gói nghiên cứu để một agent triển khai tham khảo. Chúng tôi sử dụng nó mọi lúc. Nghe có vẻ tốn kém, nhưng thực ra không phải vậy. Bạn có thể chạy chương trình này trong Slate với DeepSeek V4 Flash và quá trình nghiên cứu rất kỹ lưỡng nhưng cực kỳ rẻ.

akira - inline image

Mục tiêu-Đánh giá-PR (Goal-Review-PR)

Đây là chương trình chúng tôi sử dụng để triển khai một tác vụ sau khi nghiên cứu hoàn tất. May mắn thay, vào thời điểm nghiên cứu đến được chương trình mục tiêu, hầu hết sự mơ hồ của tác vụ đã được giải quyết, do đó việc thực thi tác vụ thậm chí còn nhanh hơn. Việc tải trước nghiên cứu với một model OSS nhẹ giúp chúng tôi dễ dàng sử dụng một model đắt tiền như Opus cho những việc quan trọng: viết mã thực sự tốt và xác minh trạng thái của hệ thống. Bạn thậm chí có thể sửa đổi chương trình để sử dụng GPT 5.5 để đánh giá đối nghịch (adversarially review) công việc của Opus 4.8.

akira - inline image

Tự động nghiên cứu (Autoresearch) như một Chương trình

Autoresearch[[9]](http://localhost:5173/blog/onyx#ref-9) ban đầu hoàn toàn do LLM điều khiển. Hướng một agent vào prompt program.md và nó quyết định thử cái gì và làm thế nào để tiến triển.

Không có gì ngạc nhiên, Autoresearch thực chất chỉ là một chương trình.

Các chương trình agent cho phép bạn đảo ngược điều đó và đặt luồng điều khiển vào runtime. Chương trình sở hữu luồng điều khiển trong khi các agent thực hiện công việc có tác dụng phụ (chỉnh sửa mã nguồn, chạy git, SSH đến GPU từ xa, huấn luyện). Đối với chương trình autoresearch, quyết định giữ lại/hoàn nguyên là mã nguồn xác định:

typescript
1kept = status === "ok" && valBpb != null && valBpb < best

Trong trường hợp của chúng tôi, chương trình chạy một agent thiết lập để chuẩn bị một repo mới và xác minh rằng A100 từ xa có thể truy cập được. Nếu thiết lập thất bại, nó sẽ trả về sớm với một kết thúc sạch sẽ dựa trên một giá trị đã được định kiểu. Nếu không, nó sẽ bước vào vòng lặp thí nghiệm.

Mỗi thí nghiệm có một agent mới. Agent được cung cấp cấu hình tốt nhất hiện tại và lịch sử các ý tưởng và kết quả trước đó, để nó không lặp lại chính mình và có thể xây dựng dựa trên những gì đã được giữ lại. Nó đề xuất một thay đổi, chỉnh sửa train.py, commit, rsync đến máy từ xa, huấn luyện và phân loại kết quả.

Agent và chương trình chia sẻ trạng thái. Agent ghi dữ liệu vào trạng thái, và chương trình đánh giá trạng thái để điều khiển luồng. Dựa trên kết quả, một agent ghi chép (recorder agent) cập nhật results.tsv, và tùy chọn đặt lại lần chạy nếu chương trình quyết định loại bỏ thí nghiệm. Điều này làm cho HEAD của git luôn trỏ đến nhánh tốt nhất hiện tại của cây thí nghiệm.

Có hai điểm khác biệt cốt lõi đáng chú ý: 1) điều này chạy trong một chương trình nên chúng ta có thể sinh ra một agent mới cho mỗi thí nghiệm và 2) chúng ta có thể quyết định agent nên làm nhiệm vụ gì dựa trên trạng thái chương trình trực tiếp.

akira - inline image
akira - inline image

Và nó trông như thế này trong mã nguồn:

typescript
1// ---------- Chương trình ----------
2
3program(async (ctx) => {
4 const c = cfg(ctx.input)
5 const total = ctx.input?.maxExperiments ?? 20
6
7 const setup = await run("ar-setup", {
8 prompt: setupPrompt(c),
9 type: "general",
10 maxSteps: 40,
11 output: SetupResult,
12 })
13 if (!setup.ready) {
14 return { aborted: true, reason: `thiết lập thất bại: ${setup.note}`, setup }
15 }
16
17 let best = c.baselineValBpb
18 let bestCommit = setup.baselineCommit
19 const history = []
20
21 for (let i = 1; i <= total; i++) {
22 let exp
23 try {
24 exp = await run(`ar-exp-${i}`, {
25 prompt: experimentPrompt(c, i, total, best, historyText(history)),
26 type: "general",
27 maxSteps: 80,
28 output: ExperimentResult,
29 })
30 } catch (err) {
31 // Agent bị lỗi/bị chặn — coi như sự cố, khôi phục repo về trạng thái tốt nhất, tiếp tục.
32 exp = {
33 description: `lỗi agent thí nghiệm ${i}`,
34 commit: "error",
35 status: "crash",
36 valBpb: null,
37 peakVramMb: null,
38 numSteps: null,
39 exitCode: -1,
40 retries: 0,
41 note: String(err?.message ?? err).slice(0, 200),
42 }
43 }
44
45 const kept = exp.status === "ok" && exp.valBpb != null && exp.valBpb < best
46
47 await run(`ar-record-${i}`, {
48 prompt: recordPrompt(c, exp, kept, bestCommit),
49 type: "general",
50 maxSteps: 20,
51 output: RecordResult,
52 })
53
54 if (kept) {
55 best = exp.valBpb
56 bestCommit = exp.commit
57 }
58
59 history.push({
60 idx: i,
61 description: exp.description,
62 status: exp.status,
63 valBpb: exp.valBpb,
64 kept,
65 commit: exp.commit,
66 retries: exp.retries,
67 })
68
69 await checkpoint({
70 name: `experiment-${i}`,
71 message: `thí nghiệm ${i}/${total}: ${exp.status}${kept ? " ĐÃ GIỮ" : ""} val_bpb=${exp.valBpb ?? "n/a"} (tốt nhất=${best})`,
72 data: { i, total, status: exp.status, valBpb: exp.valBpb, kept, best, bestCommit },
73 })
74 }
75
76 const kepts = history.filter((h) => h.kept)
77 return {
78 baselineValBpb: c.baselineValBpb,
79 bestValBpb: best,
80 bestCommit,
81 improvement: c.baselineValBpb - best,
82 experimentsRun: history.length,
83 kept: kepts.length,
84 crashes: history.filter((h) => h.status === "crash").length,
85 infraFails: history.filter((h) => h.status === "infra_fail").length,
86 localRepo: c.localRepo,
87 branch: c.branch,
88 history,
89 }
90})

Công việc tương lai

Yêu cầu VM duy nhất còn lại mà chúng tôi chưa định nghĩa là mô hình độ bền (durability model) cho các chương trình. Vẫn chưa rõ mô hình chính xác cho việc tiếp tục và xử lý vòng đời của một chương trình là gì, và mức độ kiểm soát nào nên được hiển thị trên runtime.

Ngoài ra, còn rất nhiều điều thú vị mà chúng tôi sẽ thêm vào để hỗ trợ các khối lượng công việc và hình dạng tác vụ khác nhau, để chúng tôi có thể viết phần mềm thực sự nhằm điều phối các agent tốt hơn. Chúng tôi chắc chắn rằng nhiều mẫu hình sẽ xuất hiện từ việc mọi người sử dụng các chương trình một cách sáng tạo theo cách riêng của họ.

Chúng tôi thực sự rất nóng lòng muốn thấy những gì bạn sẽ xây dựng.

  • Nhóm RL

Tài liệu tham khảo

  1. Yao et al., "ReAct: Synergizing Reasoning and Acting in Language Models," 2022
  2. Geoffrey Huntley, "The Ralph Loop"
  3. Geoffrey Huntley, "everything is a ralph loop," January 2026
  4. Zhang, Kraska, Khattab, "Recursive Language Models," December 2025
  5. Wang et al., "Executable Code Actions Elicit Better LLM Agents," ICML 2024
  6. OpenAI, "Introducing Deep Research," February 2025
  7. Cursor, "Scaling Agents," January 2026
  8. OpenAI, "Using Goals in Codex"
  9. Andrej Karpathy, "autoresearch"
  10. Anthropic, "Introducing Dynamic Workflows in Claude Code"
  11. OpenAI, "Learning to Reason with LLMs," September 2024
  12. Anthropic, "A harness for every task: dynamic workflows in Claude Code"
  13. Random Labs, "Skill Chaining"

Turn one viral article into a full content workflow

Collect the source, decode the pattern, create assets, draft the story, and distribute from one AI workspace.

Explore YouMind
Dành cho nhà sáng tạo

Biến Markdown của bạn thành bài viết 𝕏 gọn gàng

Khi bạn đăng bài viết dài của riêng mình, việc định dạng hình ảnh, bảng và khối mã cho 𝕏 rất mệt mỏi. YouMind biến cả bản nháp Markdown thành một bài viết 𝕏 gọn gàng, sẵn sàng để đăng.

Thử Markdown sang 𝕏

Thêm pattern để giải mã

Bài viết viral gần đây

Khám phá thêm bài viết viral