Cấu trúc

Astragentic không phải một runtime, cũng không phải một method. Nó là lớp nằm giữa hai thứ đó: bên dưới là Claude Code, Codex hoặc OpenCode đang chạy model, bên trên là repo thật của bạn, còn method thì tôi thuê ngoài từ mattpocock-skills. Phần Astragentic tự viết là phần điều phối, và chỉ phần đó.

Tôi chia làm bốn lớp vì mỗi lớp trả lời một câu hỏi khác nhau, và câu hỏi đó quyết định ai sở hữu file nào. Lớp runtime trả lời “agent này chạy bằng gì”. Lớp harness trả lời “nó được phép làm gì”. Lớp coordination trả lời “các agent đang ở đâu”. Lớp cuối trả lời “dự án này thật ra là gì”, và đó là phần Astragentic không bao giờ được trả lời thay bạn.

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 Vai · Thomas · Shaper · Builder · Rin · QA · HARNESS Vai 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 Anh Em · repo · CONTEXT.md · ADR · DỰ ÁN CỦA ANH EM Dự Án Của Anh Em 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 ANH EM Legend Frontend Backend Database Security External
Explore ↗mở tab mới · giao diện tiếng Anh
Màu role trong hình

Bấm vào một ô để sang trang của nó.

Claude Code · Codex · OpenCode

Runtime

Ba runtime, và vai nào chạy trên runtime nào là một dòng trong .agents/orchestrator.md, file của bạn, upgrade không bao giờ đè lên. Claude Code là runtime gốc: cả năm vai đều chạy được ở đây. Codex và OpenCode là tuỳ chọn, và chúng có mặt vì lý do cụ thể chứ không phải để danh sách dài thêm.

Codex có mặt để làm nhân chứng. Cross-vendor arm cần một model của vendor khác đọc lại diff, nên nếu chỉ có một runtime thì arm đó không tồn tại. OpenCode là lựa chọn thứ ba cho vai Builder khi bạn cần.

Cái giá của việc đứng trên ba runtime là enforcement không đều nhau. hook-git-guard.py được đăng ký ở Claude Code qua .claude/settings.json và ở Codex qua .codex/hooks.json. Một Builder chạy OpenCode không có hook tương đương, và cả Claude lẫn Codex đều có thể chạy với hook tắt hoặc chưa được trust. Vì vậy luật thứ tự dọn dẹp phải nằm trong contract trước, trong hook sau. Hook là lớp thứ hai, không phải hàng rào.

Roles: 5 · Skills: 16 · Hooks: 4 · Ledger

Harness

Đây là thứ install.sh mang vào repo của bạn: năm vai, mười sáu skill, bốn hook, và ledger lỗi. Vai không chia theo chức danh mà chia theo tuổi thọ session, vì tuổi thọ session quyết định vai đó còn nhớ được gì. Thomas sống suốt session. Shaper sống đúng một session không đứt. Builder sống một ticket. Rin sống một vòng. QA sống một chuyến đi.

Mỗi vai có hai file, và chỗ đặt luật quan trọng hơn nội dung luật. .claude/agents/<role>.md là system prompt, chỉ mang bốn dòng. .agents/roles/<role>.md là contract đầy đủ, vào session qua tool Read nên nó nằm trong context như một tool result.

Tôi đo được điều này trong một session dài có compact đúng một lần: bốn dòng trong system prompt được tuân đúng cả session, còn mọi luật nằm ngoài nó đều bị vi phạm, và không vi phạm nào được phát hiện cho tới lúc chủ dự án hỏi. Tương quan là tuyệt đối. Đó không phải chuyện agent lơ đãng, đó là budget context hoạt động đúng như thiết kế. Vì vậy bốn dòng đó cố định ở bốn, và phần còn lại được nạp lại bằng hook chứ không bằng lời nhắc.

Tracker · herdr panes · git worktrees

Điều phối

Ba thứ giữ cho nhiều agent chạy cùng lúc mà không va nhau: tracker, pane của herdr, và git worktree. Điểm chung của cả ba là chúng nằm ngoài context của agent. Thứ gì chỉ tồn tại trong context của một session sẽ biến mất lúc session đó compact, và không ai biết nó đã biến mất.

Tracker giữ trạng thái công việc. Astragentic không ship tracker riêng; nó ship adapter cho GitHub Issues, Jira và Linear, nên bạn dùng tiếp board đang có. Trạng thái nằm ở đó nghĩa là câu “ticket nào đang sẵn sàng” là một truy vấn, không phải một trí nhớ.

herdr giữ pane. Mỗi Builder có một pane nhìn thấy được, và đây không phải chuyện thẩm mỹ: AST-018 đo được một lần dispatch chỉ được kể ra bằng chữ chứ chưa từng chạy, không có tín hiệu sống nào để phân biệt. Một pane là thứ đếm được.

git worktree giữ ranh giới ghi. Mỗi ticket một checkout, và Builder là người ghi duy nhất trong đó. AST-016 đo được điều ngược lại: nhiều agent chung một checkout thì HEAD của người này bị người kia kéo đi, và kể cả một reviewer chỉ đọc cũng git switch được checkout của người khác.

Cái giá là ba dependency ngoài: một tracker phải cấu hình, một herdr phải cài, và disk cho mỗi worktree.

repo · CONTEXT.md · ADR

Project của bạn

Lớp dưới cùng là repo của bạn, và luật ở đây là Astragentic không biết gì về nó ngoài những thứ chính bạn khai. docs/agents/issue-tracker.md nói dùng tracker nào. .agents/orchestrator.md nói vai nào chạy runtime nào, model nào. CONTEXT.md giữ từ vựng miền, và ADR giữ những quyết định đã chốt. Không file nào trong số đó bị release ghi đè.

Ranh giới này tôi học được ở chỗ đắt nhất là lúc dọn worktree. Harness biết đúng một thứ mà mọi worktree đều cấp phát: tiến trình có cwd nằm trong đó. Mọi thứ còn lại thuộc về project: database, port đã đăng ký, container, broker, lease trên cluster dùng chung. Harness không thể gọi tên bất kỳ thứ nào trong số đó mà không gọi tên stack của đúng một dự án.

Suốt bốn release nó đã làm đúng chuyện đó: một compose label và một tiến trình broker được hardcode ở năm chỗ gọi khác nhau. Một project chạy stack khác đọc thấy dòng chữ “đã có cleanup” rồi không giải phóng gì cả. Đo được ở downstream trong một đêm: 43 tiến trình mồ côi, 3.405 database thừa chiếm 25 GB, load average 123, một Builder bị hệ điều hành giết.

Nên bây giờ project tự khai bước dọn riêng thành một plug chạy được ở .astraler/project/cleanup-worktree.sh, và release-worktree-resources.sh gọi nó sau khi đã reap tiến trình. Một project không cấp phát gì ngoài git thì vẫn phải viết một file nói đúng điều đó, vì một no-op im lặng không phân biệt được với một lần giải phóng thành công.

Năm phần tôi sẽ giữ lại

Ledger lỗi chỉ thêm, không sửa

Mỗi lần có thứ hỏng, tôi ghi một dòng vào một file chỉ thêm, mỗi dòng một mã AST-<n> không bao giờ được đánh số lại hay xoá đi. Hiện có 136 dòng, và 71 trong số đó đã buộc vào một file đang bắt ai đó làm khác đi hôm nay. Phần còn lại vẫn nằm nguyên trong bảng chứ không bị lọc đi.

Cross-vendor arm chốt trên đúng SHA

Sau khi Claude viết xong, một model của vendor khác đọc lại diff và để lại receipt buộc vào đúng SHA nó đã đọc. Lý do không phải là đa dạng cho vui: một lần review cùng vendor đã cho lọt một defect đem secret sống và PII vào file được track, và chính vòng cross-vendor bắt được nó ở mức P1.

Tracker là substrate giữ trạng thái

Trạng thái công việc sống trên tracker của chính dự án, không nằm trong một file plan trong branch. Khác biệt kiểm chứng được: một file plan không trả lời được câu “ticket nào đang sẵn sàng ngay bây giờ”, còn một truy vấn trên blocking edge và assignee thì trả lời được.

Claim chạy trước khi tạo worktree

Thứ tự là ghi assignee lên tracker, đọc lại, rồi mới git worktree add -b. Nhờ vậy hai session nhìn thấy nhau trên chính tracker thay vì phát hiện va chạm sau khi cả hai đã viết code, và không cần lock file hay dispatcher trung tâm nào.

Review chạy đúng một vòng

Mỗi ticket đi qua ba tầng đúng một lượt: code-review trên hai trục Standards và Spec, rồi simplify pass, rồi cross-vendor arm. Hệ trước đó đo được 5 tới 14 vòng review cho một ticket, phần lớn vòng sau dùng để dọn thứ vòng trước để lại. Tôi bỏ vòng lặp và giữ nguyên độ nặng.

  • Ledger

    Mỗi luật trong harness đến từ một lần hỏng đo được, và dòng ledger tương ứng vẫn đọc lại được.

    71 / 136bài học đo được đã thành luật trong harnessMở ledger →

  • Cánh tay cross-vendor

    Claude build, Codex đọc lại, receipt buộc vào đúng SHA đã đọc.

    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
    Explore ↗mở tab mới · giao diện tiếng Anh
    Màu role trong hình
  • Tracker là nền, không phải báo cáo

    Trạng thái nằm trên board. Một session chết đi không mang theo thứ gì.

  • Claim trước worktree

    Assignee được ghi rồi đọc lại trước khi có branch, nên hai Builder không thể cùng nhận một ticket.

  • Review một vòng

    Standards và Spec chạy đúng một lượt trên cả increment, rồi dừng. Không có vòng thứ hai để trốn vào.