Cách tiếp cận

Astragentic hướng tới autonomous coding: một team AI agent tự vận hành phần thi công, còn con người giữ định hướng và quyết định.

Mỗi team có một cách làm việc riêng, và không quy trình nào nhập khẩu nguyên vẹn được. Vì vậy Astragentic là một scaffold: bộ khung đã giải quyết sẵn những phần khó, còn mọi thành phần trong đó đều mở để bạn tuỳ biến.

Sáu phần dưới đây là sáu quyết định thiết kế lớn nhất của bộ khung: cơ chế, bằng chứng đo được, và đánh đổi. Đây là lựa chọn của tôi trên dự án của tôi, không phải khuôn mẫu bắt buộc.

Mô hình orchestrator agent: bạn định hướng, Thomas điều phối

Coding agent hôm nay đã đủ sức đảm nhận phần thi công: nhận việc, viết code, chạy test, trả kết quả.

Việc còn lại của bạn không phải viết code. Nó là hai thứ khác, và chúng ăn hết thời gian: trả lời câu hỏi agent đặt ra trong lúc làm, và review chất lượng kết quả trả về.

Cả hai có chung một điểm nghẽn. Câu hỏi kỹ thuật của agent thường vượt quá chuyên môn của người điều hành. Cách xử lý phổ biến là mang câu hỏi sang một AI khác rồi chuyển câu trả lời về. Khi đó con người chỉ còn là khâu trung chuyển, và quyết định trên thực tế đã do AI đưa ra.

Astragentic bỏ khâu trung chuyển đó bằng hai cơ chế.

Thomas, người đại diện của team

Thomas nắm ngữ cảnh dự án và đứng giữa bạn với các agent:

  • Đọc artifact các agent trả về, thay vì đẩy nguyên log sang cho bạn.
  • Đánh giá phương án và tech stack được đề xuất.
  • Trả lời câu hỏi kỹ thuật ngay tại chỗ.
  • Chuyển lên bạn những gì thuộc thẩm quyền của bạn: hướng sản phẩm, trải nghiệm người dùng, thứ tự ưu tiên.

Bạn làm việc như khách hàng của một đơn vị phát triển: đặt yêu cầu, theo dõi tiến độ, và can thiệp khi thấy team đi lệch.

Một team vận hành công khai

Mỗi agent là một session có tên, có pane riêng trong herdr, và lịch sử làm việc ở lại trong session đó. Bạn quan sát được từng agent làm gì. Thomas truy vết được khi có sự cố. Cách các agent phối hợp trở thành dữ liệu để bạn cải tiến chính bộ khung.

Subagent và agent team bên trong một runtime chạy ẩn trong tiến trình cha. Không có gì để nhìn.

Đánh đổi. Thêm một bộ công cụ phải cài, hiểu và nâng cấp, và mỗi bản nâng cấp là một sự kiện dự án phải hấp thụ. Tới nay tôi mới chứng minh được từng công cụ chạy đúng; cả vòng từ dispatch tới merge với đủ gate trên việc thật vẫn đang được đo.

Bốn Lớp, Một Bộ Khung An architecture diagram generated by Archify. Claude Code · runtime · RUNTIME Claude Code runtime Codex · runtime · RUNTIME Codex runtime OpenCode · runtime · RUNTIME OpenCode runtime Role · Thomas · Shaper · Builder · Rin · QA · HARNESS Role Thomas · Shaper · Builder · Rin · QA Skill · 16 skill đóng gói · HARNESS Skill 16 skill đóng gói Bộ Nhớ / Ledger · cái thật sự đã xảy ra · HARNESS Bộ Nhớ / Ledger cái thật sự đã xảy ra Hook · 4 hook vòng đời · HARNESS Hook 4 hook vòng đời Tracker · GitHub · Jira · Linear · COORDINATION Tracker GitHub · Jira · Linear herdr · mỗi agent một pane · COORDINATION herdr mỗi agent một pane git worktree · mỗi ticket một checkout · COORDINATION git worktree mỗi ticket một checkout Dự Án Của Bạn · repo · CONTEXT.md · ADR · DỰ ÁN CỦA BẠN Dự Án Của Bạn repo · CONTEXT.md · ADR Thomas hỏi frontier Builder claim worktree chặn lệnh nguy hiểm RUNTIME HARNESS COORDINATION DỰ ÁN CỦA BẠN Legend Frontend Backend Database Security External

Vuốt ngang để xem hết sơ đồ

Xem sơ đồ đầy đủ ↗mở tab mới
Màu role trong hình

Issue tracker giữ trạng thái, không phải file markdown

Trạng thái công việc cần nằm ngoài context của agent, và bạn mở ra là đọc được. Issue tracker là nơi duy nhất thoả cả hai.

Cách làm phổ biến trước đó là để AI cắt việc thành file markdown rồi theo dõi bằng ô tick. Nó hỏng ở hai đầu: agent phải nhớ quay lại sửa, còn bạn phải mở file ra đọc.

File markdown Issue tracker
Cập nhật trạng thái Agent phải nhớ quay lại sửa ô tick Một trường status, đổi bằng một lệnh
Xem tiến độ Mở file, đọc vài trăm dòng Mở board, nhìn cột
Phụ thuộc giữa các việc Nằm trong câu chữ Một cạnh chặn (blocking edge), truy vấn được
Hai agent cùng nhận một việc Không có gì chặn Assignee đóng vai xí phần, ghi và đọc lại được
Máy thao tác Sửa văn bản tự do CLI và MCP chính thức
Duyệt hoặc yêu cầu sửa Nhắn ở một chỗ khác Comment ngay trên ticket
Nhiều người cùng góp ý Sửa chung một file, giẫm lên nhau Mỗi người một comment, có tên, có thứ tự
Agent hỏi lại Không có chỗ để hỏi Đặt câu hỏi ngay trong ticket, ai trả lời cũng được, rồi agent làm tiếp
Khi session đóng Trạng thái mất theo context Board vẫn còn nguyên

Hai dòng về comment là chỗ thay đổi cách làm việc rõ nhất. Agent không còn phải chờ đúng một người: nó đặt câu hỏi trên ticket, ai trong team trả lời được thì trả lời, rồi nó chạy tiếp. AI làm việc như một thành viên trong nhóm chứ không phải một công cụ bạn phải ngồi canh.

Một chi tiết dễ bỏ sót: danh sách việc làm được ngay, gọi là frontier, phải được ghi lại. Nếu nó chỉ được tính trong context của agent thì bạn mở board ra không thấy, và ticket đã hết blocker vẫn trông như đang bị chặn. Vì vậy contract mang cả hai nửa: tính xong thì ghi câu trả lời ngược lại lên tracker, và không đọc nhãn sẵn sàng như thể nó là trạng thái.

Đánh đổi. Astragentic thừa kế giới hạn của tracker bạn đang dùng. Không tracker nào có ô assignee thiết kế để chứa builder/<ticket-id>. GitHub Issues không có trường status thật, nên status nằm trong label và cột trên Project board chỉ là bản sao phải giữ đồng bộ. Và vì tracker giữ trạng thái chứ không phải bản ghi thụ động, nó lệch được với thực tế; reconcile-tracker đo tracker bằng git.

Truy Vấn Frontier A data-flow diagram generated by Archify. 01 / Field trên tracker 02 / Truy vấn 03 / Board 04 / Tiêu thụ Ticket Đang Mở · toàn bộ item tracker · 01 / Field trên tracker Ticket Đang Mở toàn bộ item tracker Cạnh Blocking · đồ thị blocked_by · 01 / Field trên tracker Cạnh Blocking đồ thị blocked_by Field Assignee · trống hoặc đang giữ · 01 / Field trên tracker Field Assignee trống hoặc đang giữ Frontier Query · hỏi cái gì đã sẵn sàng · 02 / Truy vấn · không nhớ lại Frontier Query hỏi cái gì đã sẵn sàng không nhớ lại Board Claimable · claim được, chưa ai claim · 03 / Board Board Claimable claim được, chưa ai claim Thomas · chạy lại sau merge/handback · 04 / Tiêu thụ Thomas chạy lại sau merge/handback Builder · claim rồi làm ticket · 04 / Tiêu thụ Builder claim rồi làm ticket Chủ site · nhìn vào board · 04 / Tiêu thụ Chủ site nhìn vào board mọi ticket đang mở đọc state blocker xong hết? đọc đồ thị assignee trống? đọc state kết quả đã ghi suy ra đầu session + ticket đóng polled xem lại độ sẵn sàng chỉ đọc claim, rồi dispatch ghi assignee issue phát sinh → ticket mới ghi Legend data store data flow

Vuốt ngang để xem hết sơ đồ

Xem sơ đồ đầy đủ ↗mở tab mới
Màu role trong hình

Subagent và agent team tốt trong một session; điều phối thì không nằm ở đó

Claude Code có subagent và agent team. Cả hai chạy tốt bên trong một session, và Astragentic vẫn dùng chúng: Builder spawn subagent cho việc đọc và báo cáo, còn Thomas dùng cả hai khi cần khảo sát hay lên plan.

Câu hỏi hay gặp là: đã có hai thứ đó thì cần gì thêm một bộ điều phối nữa.

Ranh giới nằm ở phạm vi. Subagent và agent team điều phối công việc bên trong một session. Thứ một team cần là điều phối qua nhiều session, và quan sát được từng session một. Với cách làm việc tôi muốn, nhìn thấy agent đang làm gì, sai ở đâu, lệch hướng lúc nào, một tiến trình chạy ẩn không đủ.

Khi đặt điều phối vào subagent, bốn điều dưới đây thiếu, và chúng thiếu theo cùng một kiểu: khi có lỗi, không có tín hiệu nào báo ra.

  • Checkout dùng chung. Subagent chạy trong cùng worktree với session cha, nên nhiều agent kéo HEAD của nhau đi. Tôi bắt được một reviewer chỉ đọc đã git switch checkout của người khác.
  • Context dùng chung. Một fork thừa kế nguyên context của cha, kèm cả những gì không ai định trao. Có lần fork thừa kế cả model của cha, nên việc đáng chạy bằng model rẻ lại chạy bằng model đắt nhất. Lần khác, một fork bên trong Builder gửi báo cáo kết thúc việc, gọi là handback, cho dispatcher dưới đúng tên Builder, và Builder không hề thấy. Và một fork ký marker simplify(increment): lên code do chính nó vừa commit, đúng form được phép.
  • Không có tracker giữ trạng thái. Trạng thái của subagent nằm trong context của session cha, mất đi khi session compact, và trong lúc tồn tại thì bạn không đọc được.
  • Không có pane để nhìn. Có lần một lượt dispatch chỉ được kể ra bằng chữ mà chưa từng được gọi. Một pane trong herdr là thứ đếm được; một subagent trong tiến trình thì không.

Và còn một điều nữa: subagent của Claude vẫn là Claude, nên không có lượt review chéo từ một hãng khác.

Vì vậy Astragentic để subagent làm đúng việc của nó, bên trong một session, với một luật: fork phải có isolation: "worktree" và không được nhắn cho dispatcher.

Đánh đổi. Bạn phải cài herdr và cấu hình một tracker, hai dependency mà subagent không cần. Mỗi Builder tốn một worktree trên disk và vài giây setup. Mỗi lần dispatch tốn một lượt ghi và một lượt đọc trên tracker. Quy trình dài hơn, nhiều tên hơn phải nhớ. Tôi chọn trả giá đó vì lỗi im lặng đắt hơn nhiều.

Mỗi Agent Có Pane Riêng An architecture diagram generated by Archify. Thomas · router thường trực · KHÔNG GIAN HERDR Thomas router thường trực ticket:TRA-139 · Builder · KHÔNG GIAN HERDR ticket:TRA-139 Builder ticket:TRA-142 · Builder · KHÔNG GIAN HERDR ticket:TRA-142 Builder spec:TRA-87 · Shaper · KHÔNG GIAN HERDR spec:TRA-87 Shaper qa:TRA-125 · QA · KHÔNG GIAN HERDR qa:TRA-125 QA rin:TRA-125 · Rin · KHÔNG GIAN HERDR rin:TRA-125 Rin dispatch dispatch dispatch dispatch-qa review KHÔNG GIAN HERDR Legend Frontend Backend Security External

Vuốt ngang để xem hết sơ đồ

Xem sơ đồ đầy đủ ↗mở tab mới
Màu role trong hình

Phương pháp phát triển đến từ mattpocock-skills

Astragentic không viết phương pháp riêng. Phần craft là mattpocock-skills: wayfinder, grill-with-docs, to-spec, to-tickets, implement, code-review. Astragentic bọc điều phối quanh đó.

Lý do nằm ở chỗ vòng lặp được đặt ở đâu.

  • Phương pháp này lặp ở đầu. grilling hỏi cho tới khi không còn câu hỏi mở, nên spec chốt xong mới viết code. Mọi review phía sau là một lượt có biên.
  • Cách làm thường gặp lặp ở cuối. Quyết định chưa chốt được đưa vào code, rồi mới chốt ở review. Đó là khâu tốn kém nhất, và số vòng review không có điểm dừng tự nhiên.

Khác biệt nằm ở chỗ dừng. Hỏi cho hết ở đầu thì có điểm dừng: hết câu hỏi mở là xong. Chốt ở review thì không, vì mỗi vòng lại sinh câu hỏi mới, và vòng sau chủ yếu dọn thứ vòng trước để lại.

Về Superpowers, câu hay được hỏi kèm: đó là một hệ tốt và team của tôi có dùng ở dự án khác. Nó gói phương pháp và điều phối vào chung một session, trạng thái nằm trong file plan trên branch, và không có gì tương đương to-tickets sinh ticket kèm blocking edge lên tracker. Chạy cả hai trong một repo là hai bộ điều phối cùng quản lý một trạng thái, nên Astragentic không kết hợp.

Đánh đổi. Đây là phụ thuộc thật. check-requirements.sh dừng cứng khi thiếu mattpocock-skills >= 1.2.3. Tên skill nằm thẳng trong các contract, nên đổi phương pháp là viết lại contract. Và Astragentic chỉ vá được đường nối, không vá được plugin: khi một defect nằm bên trong to-tickets, cách xử lý đúng là để contract tính tới nó thay vì fork một bản vá.

Review chéo: một AI của hãng khác đọc lại diff

Sau khi Claude viết xong và tự review, một model của hãng khác đọc lại diff. Ở đây là Codex của OpenAI.

Lượt đọc lại đó gọi là arm, và đây là review chéo chứ không phải tranh luận: hai model không cãi nhau để thuyết phục ai, mỗi bên đọc và kết luận độc lập, cả hai kết luận đều được giữ lại.

Cơ chế thì đơn giản: arm đọc cả repository, còn tác giả chỉ đọc ticket. Nên arm bắt được mâu thuẫn với chính tiêu chuẩn dự án đã khai, điều người viết code khó nhận ra vì đang làm theo yêu cầu của ticket.

  • Một defect lọt qua vòng cùng hãng: nó đem secret đang dùng thật và PII của người mua vào file được track. Lượt đọc của hãng khác bắt được và xếp P1.
  • Hai lăng kính bắt hai loại defect khác nhau, nên chúng chạy song song chứ không thay thế nhau.
  • Một ca trên diff lớn. 6.904 dòng thêm mới trên 31 file đi qua lượt đọc cùng hãng bỏ sót ba test rỗng. Lượt đọc phạm vi ticket trên diff nhỏ hơn bắt được một deadlock thật mà bản vá của lượt trước vừa tạo ra.

Đánh đổi. Ma sát lúc gọi. Cách quote và argv khác nhau giữa các runtime. codex exec đã có lần treo im lặng, nên cần timeout và một dispatcher theo dõi. Nguy hiểm nhất là phạm vi: nếu --base và HEAD resolve lệch nhau, companion so một branch với chính nó và trả về sạch trên không commit nào. Vì vậy mọi lượt đọc phải in ra dòng range trước khi verdict được tin.

Cánh Tay Chéo Vendor A sequence diagram generated by Archify. commit range <base>..HEAD adversarial-review --wait --base <ref> Chữ focus mang ý định của chủ ticket blocking / non-blocking Chỉ file output đáng tin, không bao giờ tin exit code arm(ticket): receipt Finding gộp theo class trước; commit rỗng, parent là cây mà gate đã đọc branch, SHA, marker Bắn cánh tay Phán quyết Receipt + handback Builder · worktree riêng · Sequence participant Builder worktree riêng Codex · review đối kháng · Sequence participant Codex review đối kháng Ticket Branch · HEAD · Sequence participant Ticket Branch HEAD Thomas · router thường trực · Sequence participant Thomas router thường trực Legend request return async trace default message

Vuốt ngang để xem hết sơ đồ

Xem sơ đồ đầy đủ ↗mở tab mới
Màu role trong hình

Bộ khung tự sửa chữa qua từng vòng làm việc

Một sự cố không được ghi lại sẽ quay lại. Đó không phải nhận xét về agent; đó là nhận xét về mọi hệ thống không có bộ nhớ sống lâu hơn phiên làm việc.

Với một team agent, chuyện này gắt hơn một team người ở đúng một điểm: session kết thúc là context mất. Một Builder vừa mắc lỗi và vừa hiểu ra vì sao nó sai sẽ không mang hiểu biết đó sang ticket sau, vì không có “nó” nào đi tiếp. Người thì ít nhất còn nhớ mang máng.

Cơ chế là một cuốn sổ, và một đường đi từ sổ vào contract.

Sổ. Mỗi sự cố là một dòng trong một file chỉ thêm, mang mã cố định — AST-136 hôm nay vẫn là AST-136 sau một trăm mục nữa. Không đánh số lại, không xoá, kể cả sau khi lỗi đã được sửa. Hiện có 136 mục.

Đường đi. Dòng nào rút ra được luật thì luật đó không nằm lại trong sổ. Nó được viết vào một file mà agent thật sự đọc: contract của một role, một skill, hoặc một hook. Sổ là bằng chứng; contract là chỗ bằng chứng có hiệu lực.

Vòng khép lại ở lúc merge, không phải cuối sprint và không phải khi ai đó nhớ ra. Commit merge mang một dòng Ledger: nói rõ cái gì vừa được ghi vào sổ. Ledger: none là hợp lệ; thiếu hẳn dòng đó thì không — “lượt này không học được gì” là một kết luận, còn không có dòng nào là một bước bị bỏ qua, và nhìn từ ngoài hai thứ giống hệt nhau nếu không bắt buộc khai báo.

Không có bước build, và không ai phải nạp lại. System prompt của mỗi role chỉ có vài dòng, và một trong số đó là lệnh đọc contract của chính nó. Session kế tiếp mở lên là đã mang luật mới. Một hook lo phần còn lại: sau khi session bị compact, contract được nạp lại, vì thứ nằm ngoài system prompt là thứ compaction tóm tắt đi trước tiên.

Một mục chỉ vào sổ khi nó đã xảy ra nhiều lần. AST-136 được ghi sau ba lần cùng một sai lầm đội ba lớp vỏ khác nhau: một lần escape sai khiến script báo STOP với nguyên nhân sai, một lần đọc 23 marker thành 193, một lần làm một marker có thật báo là chưa từng được ghi. Ba lần đó cách nhau nhiều release, và chỉ nhìn ra được vì cả ba đều nằm trong sổ.

Đánh đổi. Cuốn sổ dài ra và không bao giờ ngắn lại. Nó không phải thứ để đọc từ đầu tới cuối, mà là thứ để tra khi một luật trong contract khiến bạn thắc mắc vì sao lại có luật này. Và mỗi luật thêm vào contract là token phải trả ở mỗi session của role đó — nên một luật phải chứng minh được nó chặn một lỗi đã xảy ra, không phải một lỗi có thể xảy ra.