Chạy hai coding agent trong cùng một checkout, và bạn sẽ gặp ngay kiểu lỗi này trong vòng chưa đầy một giờ. Một agent chuyển branch trong khi agent kia đang sửa dở. Các thay đổi đã stage biến mất vào một commit mà chúng không thuộc về. Test pass trên một file mà agent kia mới viết lại dở dang. Đây không phải lỗi của model. Git working tree là trạng thái mutable dùng chung, và hai process cùng thay đổi trạng thái dùng chung mà không phối hợp thì sớm muộn cũng sẽ làm hỏng nó.
Cách khắc phục tiêu chuẩn thì ai cũng biết: cho mỗi agent một working tree riêng. Git worktree cho phép một repository phục vụ nhiều thư mục đã checkout cùng lúc, nên các branch song song không bao giờ chạm vào cùng một file trên đĩa. Nhiều team tự viết script thủ công cho việc này; hướng dẫn của chúng tôi về dùng git worktree với AI coding agent sẽ đi qua từng bước của thiết lập DIY đó.
Bài viết này nói về con đường còn lại: điều gì xảy ra khi việc cô lập, chuẩn bị thư mục, giới hạn concurrency và dọn dẹp đều do platform đảm nhiệm thay vì các shell script của bạn.
TL;DR
Sharkly chạy các AI agent song song mà không gặp merge conflict bằng cách cấp cho mỗi run của Task một thư mục cô lập riêng trên một Computer đã kết nối. Một service cục bộ trên Computer đó nhận từng run trong hàng đợi, chuẩn bị thư mục task (với công việc dựa trên repository thì mỗi run có một git worktree riêng), khởi động Runtime đã chọn, rồi stream tiến độ, trace event và kết quả về cho Task. Giới hạn concurrency trên Agent và trên Computer chặn số run chạy đồng thời, và không có gì tự merge: kết quả trả về Task, nơi con người review thay đổi và quyết định bước merge và release. Các agent không bao giờ dùng chung working tree, nên những Task song song không thể ghi đè thay đổi của nhau.
Kiểu lỗi mà Sharkly được sinh ra để ngăn chặn
Cần nói rõ chính xác điều gì sai khi các agent dùng chung một checkout, vì mỗi triệu chứng đều tương ứng với một phần của giải pháp.

Trạng thái branch là toàn cục trên từng working tree, nên khi agent A checkout branch của nó, file của agent B bị thay đổi ngay giữa lúc đang chạy. Index cũng là toàn cục, nên git add và git commit đan xen công việc từ các task khác nhau. Trạng thái untracked va chạm nhau: output build và các bản cài dependency từ run này làm nhiễu kết quả test của run khác. Và nợ dọn dẹp cứ chồng lên, vì mọi bản copy repository tạm bợ để né ba vấn đề đầu tiên đều nằm trên đĩa cho đến khi có người nhớ ra là nó tồn tại.
Một thư mục dùng chung chỉ có thể chạy an toàn một agent tại một thời điểm. Nếu bạn đang xoay xở với các tmux pane và sự kỷ luật, bài viết của chúng tôi về chạy nhiều Claude Code agent song song sẽ giải thích vì sao giới hạn đó lại đến nhanh như vậy.
Ngăn xếp thực thi: Agent, Computer, Runtime, Task
Sharkly không thay thế Claude Code, Codex hay các công cụ thực thi khác. Nó bổ sung lớp task dùng chung, Computer, context, điều khiển và review xung quanh những công cụ mà team bạn đã dùng. Vị trí ở lớp đó định hình cách thực thi song song vận hành, vì nhiệm vụ của Sharkly là điều phối các run, chứ không phải viết code.
Bốn vai trò chia nhau công việc, và mỗi vai trò có đúng một nhiệm vụ:
- Agent định nghĩa cách công việc nên được xử lý: instruction, Skills, repository và cài đặt run của nó. Agent không phải là host thực thi.
- Computer cung cấp host và tài nguyên cục bộ: máy local, server từ xa, container, hoặc cloud host được hỗ trợ. Bài viết cùng chủ đề về Computer trong Sharkly sẽ nói về cách kết nối chúng.
- Runtime thực hiện phiên agent thực tế. Đó là công cụ cụ thể được cài trên Computer đó, chẳng hạn Claude Code, Codex hoặc Gemini CLI.
- Task vẫn là bản ghi dùng chung cho cả team: mục tiêu, trạng thái, thảo luận, execution trace và kết quả.
Gắn kết chúng lại là một service cục bộ nhỏ chạy trên Computer. Nó đăng ký Computer, phát hiện các Runtime đã cài, nhận các run trong hàng đợi, chuẩn bị thư mục task cho từng run, khởi động Runtime và báo kết quả về. Nó chủ động khởi tạo kết nối tới server, nên một thiết lập điển hình không cần mở port inbound.
Chính sự tách biệt đó khiến việc chạy song song trở nên khả thi. Vì thư mục làm việc được service cục bộ chuẩn bị cho từng run, chứ không do Agent chọn, hai Agent được giao hai Task khác nhau có thể nhắm tới cùng một repository trên cùng một Computer mà không bao giờ thấy file của nhau. Để biết cách cấu hình Agent, xem bài Agent trong Sharkly.
Điều gì xảy ra khi một run bắt đầu
Giao một Task cho một Agent và đưa nó ra khỏi Backlog, Sharkly sẽ kiểm tra mức sẵn sàng thực thi, xếp hàng một run đủ điều kiện và dispatch nó tới Computer đã chọn. Từ đó, service cục bộ tiếp quản. Trước khi Runtime khởi động, nó có thể cần chờ dung lượng concurrency, chuẩn bị một thư mục tạm được cô lập hoặc chờ một thư mục specified rảnh, fetch các repository đã cấu hình, chiếu các biến môi trường được phép, và dựng lệnh gọi Runtime.
Chỉ khi đó Runtime mới khởi động. Run đi qua các trạng thái rõ ràng: Queued, Dispatched, Waiting for local directory, Running, và cuối cùng là Completed, Failed hoặc Canceled. Những trạng thái đó hiển thị trong execution log của Task, nên câu hỏi "sao vẫn chưa có gì xảy ra" có một câu trả lời có thể kiểm tra được thay vì phải đoán. Một run bị giữ ở Queued do giới hạn concurrency đã đầy trông khác với run bị giữ ở Waiting for local directory, và sự khác biệt đó cho bạn biết cần vặn nút nào.
Hãy để ý điều còn thiếu: không có lúc nào Agent quyết định chạy ở đâu. Agent mang theo instruction; hạ tầng mang lại sự cô lập.
Worktree cô lập: chế độ Temporary hoạt động thế nào
Agent hỗ trợ hai chế độ thư mục làm việc, và chế độ được thiết kế cho công việc song song là Temporary mode. Mỗi Task nhận một thư mục được cô lập, và với công việc dựa trên repository, service cục bộ có thể chuẩn bị một git worktree riêng cho từng run từ dữ liệu repository đã cache của nó.
Chỉ một câu đó đã chứa đựng toàn bộ câu chuyện ngăn ngừa xung đột. Một worktree cho mỗi run thư mục đã checkout riêng và trạng thái branch riêng, đồng thời chia sẻ các object repository bên dưới. Bốn kiểu lỗi ở trên biến mất một cách tự nhiên: không có branch pointer dùng chung, không có index dùng chung, không có build artifact dùng chung, và các thư mục mà platform có thể dọn dẹp sau này. Vì worktree được tạo từ dữ liệu đã cache thay vì clone mới, chi phí khởi động vẫn ở mức hợp lý, mặc dù một run vẫn có thể cần truy cập mạng để làm mới repository.
Tài liệu nói rất thẳng về thời điểm dùng cách này: Temporary mode được khuyến nghị cho các thay đổi code song song, và cho mọi tình huống mà nhiều Task có thể sửa cùng một codebase cùng lúc.
Một ranh giới cần nói rõ: cô lập ngăn được va chạm working-tree, chứ không ngăn được xung đột ngữ nghĩa. Nếu hai Task cùng viết lại một function, cả hai run đều hoàn thành sạch sẽ trong worktree của mình, và vẫn cần một người hòa giải phần chồng lấn ở bước review. Cách khắc phục là khoanh vùng Task để chúng không nhắm vào cùng một đoạn code trong cùng một buổi chiều: đây là quyết định về planning, không phải về hạ tầng.
Khi cô lập là lựa chọn sai: Specified mode
Chế độ thứ hai tồn tại vì việc tạo thư mục mới cho mỗi run không hề miễn phí. Ở Specified mode, Agent chạy trong một thư mục local tuyệt đối đã cấu hình từ pool của nó, tái sử dụng repository, dependency và cache đã có sẵn ở đó. Chế độ này chỉ khả dụng trên Computer local.
Sự đánh đổi này có một hệ quả cứng: một thư mục specified phục vụ một run tại một thời điểm, và khi mọi thư mục đã cấu hình đều bận, run tiếp theo phải chờ. Một Agent phải chạy nhiều Task đồng thời ở Specified mode cần nhiều thư mục trong pool của nó.
| Temporary mode | Specified mode | |
|---|---|---|
| Thư mục cho mỗi run | Thư mục cô lập mới, worktree cho công việc với repository | Một thư mục tuyệt đối đã cấu hình từ pool |
| An toàn khi chạy song song | Các run không thể chạm vào file của nhau | Mỗi thư mục phục vụ một run tại một thời điểm |
| Chi phí khởi động | Chuẩn bị thư mục mỗi run, từ dữ liệu repository đã cache | Tái sử dụng code, dependency và cache có sẵn |
| Phù hợp nhất cho | Các thay đổi code song song, hầu hết công việc với repository | Repo rất lớn, local state tốn kém, tooling gắn với một đường dẫn cụ thể |
| Khả dụng | Mọi Computer đã kết nối | Chỉ Computer local |
Cô lập đổi lấy sự an toàn bằng chi phí chuẩn bị; tái sử dụng đổi lấy tốc độ bằng chi phí tuần tự hóa. Sharkly buộc bạn chọn rõ ràng theo từng Agent, điều này tốt hơn nhiều so với việc phát hiện ra sự đánh đổi đó trong một working tree đã hỏng.
Giới hạn concurrency: song song nhưng có chặn trên
Song song không giới hạn tự nó đã là một kiểu lỗi. Mỗi run đồng thời đều tiêu tốn CPU, memory, ổ đĩa, dung lượng của nhà cung cấp model và băng thông repository; tám agent giành giật một chiếc laptop cho kết quả tệ hơn ba agent chạy thoải mái.
Sharkly giới hạn concurrency ở hai cấp độ. Computer có giới hạn concurrency task với vai trò host, và mỗi Agent có số Task chạy song song tối đa cùng timeout cho từng Task. Giá trị mặc định khá thận trọng: ở Temporary mode, một Agent nhận 50 phần trăm giới hạn của Computer; ở Specified mode, nó bằng số thư mục đã cấu hình. Đặt cao hơn số thư mục và sản phẩm sẽ cảnh báo rằng các thao tác ghi có thể va chạm giữa các task. Cảnh báo đó chính là luận điểm của bài viết này, nén lại trong một hộp thoại.
Hướng dẫn của tài liệu về việc nâng giới hạn rất tỉnh táo: chỉ tăng concurrency sau khi Computer và Runtime hiện tại xử lý khối lượng công việc hiện có một cách ổn định.
Stream tiến độ và review trước khi merge
Cô lập sẽ thành gánh nặng nếu nó cũng đồng nghĩa với vô hình. Năm agent trong năm thư mục ẩn chính là cách công việc biến mất vào những terminal riêng tư. Vì vậy mọi thứ mà run tạo ra đều chảy về bản ghi dùng chung.
Khi một run đang hoạt động, Task hiển thị trạng thái thực thi của nó. Activity ghi lại comment và thay đổi của task theo dòng thời gian; execution log ghi lại thời điểm run bắt đầu và kết thúc, các tool call và Runtime event, nguồn trigger, và mọi chi tiết lỗi; báo cáo của Agent được lưu lại dưới dạng comment gắn với execution trace của nó. Context, tiến độ, blocker và kết quả luôn hiển thị từ lúc yêu cầu đến lúc release, dù các thay đổi file diễn ra trong một thư mục mà không người nào từng mở.
Rồi đến chốt kiểm soát. Ở đây không có gì tự merge. Agent nghiên cứu, thực thi, test và báo cáo. Con người định hướng, trao quyền và chấp nhận kết quả. Khi một run hoàn tất, Agent có thể để Task ở trạng thái chờ con người review, và việc này hiện lên trong Inbox của người phụ trách. Worktree cô lập khiến việc thực thi song song an toàn; chốt review khiến nó đáng tin.
Còn một mảnh nữa khép kín vòng lặp: dọn dẹp. Các run của agent để lại thư mục làm việc và artifact trên Computer, và tính năng dọn dẹp có thể cấu hình sẽ thu hồi các run đã xong sau một khoảng thời gian lưu giữ, với ngưỡng dung lượng trống tối thiểu làm chốt chặn. Công việc đang chạy hoặc trong hàng đợi, các run được pin, và các run thất bại vẫn cần điều tra sẽ không bao giờ bị đụng tới. Đây chính là việc mà các thiết lập DIY luôn quên cho đến khi đĩa đầy.
Sharkly tự động hóa những gì so với thiết lập DIY
Nếu bạn đã đọc hướng dẫn DIY về worktree của chúng tôi, sự tương ứng rất trực tiếp. Lệnh git worktree add bạn viết script cho từng agent trở thành service cục bộ chuẩn bị một thư mục cô lập cho từng run. Phán đoán "bao nhiêu agent là quá nhiều" trở thành giới hạn concurrency rõ ràng kèm cảnh báo khi một cài đặt không an toàn. Lệnh git worktree prune bạn quên trở thành tính năng dọn dẹp dựa trên thời gian lưu giữ. Và phần mà không script nào mang lại cho bạn, một bản ghi dùng chung về việc run nào đã làm gì và liệu có người đã chấp nhận nó hay chưa, chính là Task.
Cặp quyết định trung thực cũng áp dụng ở đây. Một developer làm một mình chạy hai agent trên một máy có thể không cần platform; một script worktree và sự kỷ luật là đủ để đi xa. Hãy dùng Sharkly khi chi phí phối hợp lớn hơn chi phí gõ code: nhiều người cùng giao việc, nhiều Computer, các run cần xếp hàng và review. Dù chọn cách nào, bạn vẫn giữ các Runtime mình đang có; việc dùng model vẫn diễn ra qua subscription hoặc API key đã cấu hình trong những công cụ đó.
Việc bắt đầu được thiết kế cố ý nhỏ gọn. Kết nối một Computer, tạo một Agent ở Temporary mode, và giao cho nó một Task ít rủi ro. Hướng dẫn bắt đầu sẽ dẫn bạn qua vòng lặp đầu tiên trong khoảng mười phút, tài liệu Sharkly đi sâu vào từng khái niệm, và bài Sharkly là gì sẽ bổ sung phần platform xung quanh việc thực thi.
FAQ
Sharkly ngăn merge conflict giữa các agent song song như thế nào?
Mỗi run của Task nhận một thư mục cô lập riêng trên Computer, và các run dựa trên repository có thể mỗi run nhận một git worktree riêng do service cục bộ chuẩn bị. Các agent không bao giờ dùng chung checkout, index hay file untracked, nên những run đồng thời không thể ghi đè công việc đang làm dở của nhau. Những phần chồng lấn khi hai Task cố ý thay đổi cùng một đoạn code vẫn cần một người hòa giải ở bước review.
Tôi có cần tự thiết lập git worktree để dùng Sharkly không?
Không. Ở Temporary mode, service cục bộ chuẩn bị thư mục task cho mọi run, bao gồm cả worktree cho công việc dựa trên repository. Bạn cấu hình chế độ trên Agent một lần; không có lệnh worktree nào cần viết script cho từng run. Để hiểu cơ chế bên dưới, xem tài liệu về git worktree.
Có bao nhiêu agent có thể chạy song song trên một Computer?
Computer có giới hạn concurrency task riêng, và mỗi Agent có số Task chạy song song tối đa. Mặc định, một Agent ở Temporary mode nhận 50 phần trăm giới hạn của Computer, còn ở Specified mode thì nhận một slot cho mỗi thư mục đã cấu hình. Các run vượt giới hạn sẽ chờ trong hàng đợi.
Sharkly có tự động merge các thay đổi của agent không?
Không. Kết quả, bằng chứng và trace của run được trả về Task, và một người review phần tóm tắt thay đổi trước khi bất cứ thứ gì được đưa đi. Người review sẽ chấp nhận, yêu cầu chỉnh sửa, hoặc quyết định bước merge và release. Tự động hóa dừng lại ở đúng chỗ cần đến phán đoán của team.
Khi nào tôi nên dùng Specified mode thay vì worktree cô lập?
Hãy dùng khi việc chuẩn bị một thư mục mới cho mỗi run thực sự tốn kém: repository rất lớn, state hoặc cache sinh ra tốn kém, hay tooling bị ràng buộc vào một đường dẫn local. Hãy chấp nhận rằng mỗi thư mục specified chỉ phục vụ một run tại một thời điểm. Với mọi trường hợp còn lại, Temporary mode là mặc định được khuyến nghị.



