Trỏ một agent vào một repository GitHub và bạn nhận lại một bảng làm việc dùng được ngay: mỗi issue thành một story, ở đúng trạng thái mà lịch sử của nó quy định, kèm theo checklist, nhãn và mốc được mang sang. Rồi cũng chính agent đó nhặt một story lên, nhận nó về mình, đẩy nó qua máy trạng thái và liên kết pull request mà nó đã mở.
Trang này mô tả trọn vòng lặp ấy. Bước tạo dữ liệu có hai lối: GitHub-to-EAT, trình nhập mã nguồn mở của East Agile, làm xong bằng một lệnh (bước 3); API nhập làm đúng công việc đó theo từng lời gọi (bước 4 và 5), và đó là thứ một agent điều khiển khi nó muốn có handle của job. Mọi thứ sau đó đều chạy trên API, bởi trọng tâm là agent có thể tự làm nốt phần còn lại mà không cần ai trông.
Đây không phải một «bản nhập bằng AI» riêng biệt. Bước tạo dữ liệu chính là trình nhập GitHub mà bạn có thể chạy bằng tay từ Cài đặt dự án → Nhập / Xuất, được mô tả trong Hướng dẫn vận hành → Nhập từ các tracker khác. Agent gọi đúng endpoint mà bạn sẽ gọi. Cái trang này bổ sung là tất cả những gì bao quanh nó: ai giữ khóa, kiểm tra bản nhập thế nào trước khi nó ghi, và agent làm gì với bảng khi bảng đã có.

Bạn cần những gì
Phần tiêu đề “Bạn cần những gì”- Một dự án — và một phiên đăng nhập hoặc một khóa
ea_user_…để tạo nó. - Một khóa agent — khóa
ea_agent_…giới hạn trong dự án đó. Nó cần vai trò nào là tùy bạn muốn agent chạy bao nhiêu phần của vòng lặp; xem bước 2. Xem thêm Hướng dẫn API → Hai loại khóa. - Một token truy cập cá nhân GitHub — có quyền đọc issue của repository. Mọi lần nhập đều xác thực, vì việc lấy dữ liệu chạy trên API GraphQL của GitHub và GraphQL từ chối một yêu cầu không mang token. Bạn chỉ được bỏ nó khi Tracker lấy dữ liệu thay bạn: một repository công khai, trên một bản triển khai có token dùng chung dự phòng (dịch vụ eastagiletracker.com được lưu trữ sẵn có một; bản tự lưu trữ không có cái nào cho tới khi người vận hành đặt
GITHUB_IMPORT_PAT), và không phải với--engine directcủa GitHub-to-EAT. Xem Token và giới hạn tần suất. - Node.js 22+ — chỉ cho lối GitHub-to-EAT ở bước 3. Lối qua API không cần gì ngoài
curl.
1. Tạo dự án
Phần tiêu đề “1. Tạo dự án”Dự án phải tồn tại trước khóa agent, và phải do một người tạo: khóa agent bị buộc vào một dự án ngay khi được cấp và không thể tự khởi tạo dự án. Hãy tạo nó trong giao diện, hoặc bằng khóa ea_user_… của chính bạn:
curl -X POST https://eastagiletracker.com/api/v1/projects \ -H "X-TrackerToken: $TRACKER_USER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"name": "hello-world", "iteration_length_weeks": 1}'Phản hồi mang theo project_id mà mọi lời gọi bên dưới đều cần.
2. Cấp một khóa agent
Phần tiêu đề “2. Cấp một khóa agent”Chủ dự án tạo khóa agent tại Cài đặt dự án → Agent. Vai trò bạn chọn quyết định agent tự làm được bao nhiêu phần của trang này, và có hai câu trả lời hợp lý:
owner— một khóa chạy trọn vòng lặp, kể cả nhập dữ liệu. Nhập chỉ dành cho chủ sở hữu, vì một lần nhập viết lại toàn bộ hình hài của dự án. Cấp một agent vai tròownerđòi hỏi chính bạn là chủ dự án: vai trò của agent không bao giờ vượt quá vai trò người tạo ra nó.member— đặc quyền tối thiểu. Agent nhận story, di chuyển chúng, bình luận và liên kết pull request, nhưng không nhập được. Bản nhập bạn tự chạy (bước 5) bằng khóa của mình, rồi trao bảng lại cho agent.
Dù chọn cách nào, đừng để nguyên giá trị mặc định. Một khóa agent mới là viewer chừng nào bạn chưa nói khác đi, và một viewer đọc được bảng nhưng không nhận hay di chuyển được story — tức là gần như toàn bộ vòng lặp này.
Khóa agent quan trọng ở đây vì một lý do vượt ra ngoài quyền truy cập. Một khóa agent hành xử như một người tham gia có tên trong đúng một dự án, nên mọi story nó tạo, mọi thay đổi trạng thái nó thực hiện và mọi bình luận nó viết đều được quy cho agent đó trong lịch sử — phân biệt được với công việc của chính bạn thay vì hòa lẫn vào.
export TRACKER_TOKEN="ea_agent_xxxxx"Hãy để agent đọc /meta trước mọi thứ khác:
curl https://eastagiletracker.com/api/v1/meta \ -H "X-TrackerToken: $TRACKER_TOKEN"Nó trả lời hai câu hỏi mà agent lẽ ra phải đoán: khóa bị buộc vào dự án nào (auth.project_id), và mỗi loại story được phép chuyển trạng thái ra sao (transitions). Một feature đi unstarted → started → finished → delivered → accepted; một chore chỉ có unstarted → started → accepted. Đọc tấm bản đồ hơn hẳn viết cứng nó vào mã.
3. Nhập bằng GitHub-to-EAT
Phần tiêu đề “3. Nhập bằng GitHub-to-EAT”GitHub-to-EAT là trình nhập mã nguồn mở của chính East Agile: một công cụ dòng lệnh giấy phép MIT làm trọn bước tạo dữ liệu — bước 4 và 5 bên dưới — bằng một lệnh. Hãy dùng nó khi có người ngồi trước terminal. Hãy dùng API bên dưới nó khi một agent điều khiển mà không ai trông và muốn có handle của job để hỏi trạng thái.
Nó cần Node.js 22+ và không có phụ thuộc lúc chạy nào của riêng nó. Nó chưa được phát hành lên npm, nên hãy cài từ repository:
git clone git@github.com:EastAgile/GitHub-to-EAT.gitcd GitHub-to-EATnpm install --global .Rồi trỏ nó vào khóa bạn cấp ở bước 2 và dự án bạn tạo ở bước 1:
export EAT_AGENT_KEY="ea_agent_xxxxx"github-to-eat --project $PROJECT_ID --repo octocat/hello-worldTrước tiên nó in một bảng chú giải ánh xạ — chính xác từng loại được chọn sẽ đáp xuống ra sao — và hỏi bạn xác nhận trước khi ghi bất cứ thứ gì. Ngoài terminal, trong một pipe, trong CI hay trong một agent, không có chỗ nào để hiện lời nhắc đó, nên một lần chạy có ghi buộc phải truyền --yes; thiếu nó, công cụ thoát với mã 2 và không ghi gì, thay vì đoán câu trả lời của bạn. Chạy lại là an toàn: thứ đã nhập rồi sẽ bị bỏ qua, không bao giờ nhân đôi.
| Cờ | Nó làm gì |
|---|---|
--dry-run | Kiểm tra trước, rồi in ra kế hoạch nó sẽ thực hiện — sẽ nhập bao nhiêu story, sẽ bỏ qua bao nhiêu vì đã có — và không ghi gì. Không cần --yes. |
--include | Nhập những loại nào, phân tách bằng dấu phẩy: issues,prs,milestones,releases,deps. Mặc định là issues, và mọi lựa chọn đều phải chứa nó. Đây cũng chính là các tùy chọn trong bảng ở bước 6. |
--token | Token truy cập cá nhân GitHub của bạn (GITHUB_TOKEN trong môi trường hoặc trong .env cũng được tính). Nó cần quyền repo, hoặc quyền chi tiết Issues: Read, trên repository đó. Bắt buộc với repository riêng tư, với máy chủ không có token dùng chung dự phòng, và luôn luôn với --engine direct. Bỏ nó trên engine mặc định của dịch vụ được lưu trữ thì Tracker tiêu ngân sách dùng chung của chính nó — xem Token và giới hạn tần suất. |
--engine | server, giá trị mặc định, gửi một lời gọi /import/json và để Tracker lấy, ánh xạ và ghi. direct chạy đúng pipeline đó trên máy bạn và ghi qua API công khai — tức là nó tự đọc GitHub nên luôn cần token, không có thì thoát với mã 2. |
--states, --milestones, --story-type, --no-comments, --no-tasks | Thu hẹp hoặc ghi đè ánh xạ cho một lần chạy; không có gì được lưu lại. Mỗi cờ trong số đó đều kéo theo --engine direct. |
Đặt EAT_API_BASE và EAT_APP_BASE để trỏ nó tới một Tracker tự lưu trữ hoặc chạy cục bộ; cả hai mặc định trỏ tới dịch vụ được lưu trữ. README chứa tham chiếu đầy đủ các cờ, các mã thoát và phần khắc phục sự cố.
Mọi thứ bên dưới là chính bản nhập đó nhưng được điều khiển theo từng lời gọi, và đó là thứ bạn muốn khi một agent chạy nó.
4. Chạy thử trước
Phần tiêu đề “4. Chạy thử trước”Nhập là chỉ dành cho chủ sở hữu — hãy dùng khóa agent vai trò owner, hoặc khóa của chính bạn nếu bạn để agent ở mức member. Hãy chạy nó với dry_run trước, trước khi cho nó ghi bất cứ thứ gì:
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/import/json \ -H "X-TrackerToken: $TRACKER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "source": "github", "owner": "octocat", "repo": "hello-world", "include_pull_requests": true, "include_milestones": true, "dry_run": true }'Một lần chạy thử sẽ lấy dữ liệu từ GitHub, đối chiếu và khử trùng lặp y hệt lần thật, báo cáo cùng những con số — imported, skipped, errors, unmatched — rồi hoàn tác toàn bộ giao dịch. Không gì được giữ lại và không sự kiện «đã hoàn tất nhập» nào lọt vào nhật ký kiểm toán của bạn. Đó là cách rẻ nhất để phát hiện rằng bạn vốn định bật mốc, hoặc rằng một repo lớn hơn bạn tưởng, trong khi việc đó còn chưa tốn của bạn đồng nào.
Mọi lời gọi tới /import/json đều bất đồng bộ, kể cả chạy thử: endpoint trả về 202 kèm một handle của job, không phải kết quả, và các con số đến trên job khi bạn hỏi trạng thái nó (bước 5). Job của một lần chạy thử cũng đạt done như lần thật; khác biệt là không gì được ghi.
5. Chạy bản nhập
Phần tiêu đề “5. Chạy bản nhập”Bỏ dry_run đi và gửi lại. Như trước, endpoint trả về 202 kèm một handle của job:
{ "import_id": "…", "status": "pending" }Hỏi trạng thái job cho tới khi nó đạt trạng thái cuối:
curl https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/imports/$IMPORT_ID \ -H "X-TrackerToken: $TRACKER_TOKEN"Trạng thái đi pending → fetching → writing → done | failed. Chỉ hai trạng thái cuối là trạng thái kết thúc: done mang các con số kết quả, failed mang thông báo lỗi và một mã máy ổn định để bạn rẽ nhánh. Trong lúc việc lấy dữ liệu đang phân trang, progress_current và progress_total cho biết nó đang ở trang nào — đáng hiển thị nếu có người đang theo dõi.
Token. Truyền "token": "github_pat_…". Bỏ nó đi thì máy chủ thay bằng token nền tảng dùng chung, vốn chỉ đọc repository công khai và được tính vào mọi lời gọi trên bản triển khai — Token và giới hạn tần suất nói rõ điều đó khiến bạn mất gì. Dù dùng token nào, nó chỉ điều khiển các lời gọi lên GitHub và không gì khác: nó không bao giờ vào log, không bao giờ vào nhật ký kiểm toán, không bao giờ được lưu trữ, và không bao giờ được trả lại trong một phản hồi hay một lỗi.
Chạy lại là an toàn. Một hàng đã được nhập trước đó sẽ được khớp theo id nguồn và bị bỏ qua, chứ không nhân đôi. Lần nhập thứ hai bồi thêm vào bảng những gì xuất hiện kể từ lần đầu.
6. Cái gì đáp xuống bảng
Phần tiêu đề “6. Cái gì đáp xuống bảng”Issue được nhập theo mặc định. Mọi thứ khác đều là tùy chọn, mỗi loại một cờ:
| Từ GitHub | Trở thành | Cờ |
|---|---|---|
| Issue | Một story. Đang mở → unstarted trong Backlog. Đã đóng → accepted, hoặc rejected khi GitHub cho biết issue được đóng dưới dạng not_planned hay duplicate (story khi đó mang một nhãn tương ứng). | mặc định |
| Checklist trong thân issue | Tác vụ — mỗi dòng - [ ] / - [x] thành một tác vụ theo thứ tự trong thân, dòng [x] đến nơi đã ở trạng thái hoàn tất. Checklist vẫn ở lại trong phần mô tả. | mặc định |
| Nhãn | Nhãn, mang sang nguyên trạng. | mặc định |
| Pull request | Một story mang nhãn pull-request. Đang mở → started, đã gộp → accepted, đóng mà không gộp → rejected. | include_pull_requests |
| Mốc | Một epic, đặt tên theo mốc, khử trùng lặp theo tiêu đề — hai issue chung một mốc rơi vào cùng một epic. Khi tắt cờ, nó đi kèm dưới dạng nhãn milestone:<tiêu đề>. | include_milestones |
| Release | Một story release. Đã phát hành → accepted, bản nháp → unstarted. | include_releases |
| Phụ thuộc giữa issue | Một blocker trên story. Chỉ issue, không bao giờ pull request. | include_dependencies |
Loại story được suy ra khi issue không nói rõ. Một nhãn chứa bug, fix hay defect — hoặc một tiêu đề bắt đầu bằng fix hay bug — biến nó thành bug; chore, maintenance, devops hay infra biến nó thành chore; còn lại đều là feature. Điều đó đáng biết trước khi nhập, vì trong East Agile Tracker chỉ feature mới mang point và chỉ feature mới góp vào velocity. Xem Giới thiệu → Story.

7. Agent xử lý một story
Phần tiêu đề “7. Agent xử lý một story”Giờ bảng đã có lịch sử, và agent đã có khóa. Từ đây vòng lặp gói gọn trong bốn lời gọi.
Tìm một story, hoặc viết một cái. Lọc bảng để tìm thứ đáng nhặt lên:
curl "https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories?state=unstarted" \ -H "X-TrackerToken: $TRACKER_TOKEN"import_source=github thu hẹp về đúng những gì bản nhập mang vào. Nếu agent tìm ra việc mà repo chưa bao giờ ghi lại, nó tạo story thay vì đi tìm — xem Hướng dẫn API → Tạo một story.
Nhận nó về mình. Agent tự thêm mình làm chủ sở hữu bằng cách POST một thân rỗng:
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/owners \ -H "X-TrackerToken: $TRACKER_TOKEN" \ -H "Content-Type: application/json" \ -d '{}'Thân rỗng nghĩa là bên gọi, nên agent không cần biết id của chính mình. Bảng giờ hiển thị agent là chủ sở hữu, và nhờ đó người đang theo dõi biết việc đã có người nhận.
Bắt đầu nó.
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/transitions \ -H "X-TrackerToken: $TRACKER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"to": "started"}'Rồi agent đi làm việc — đọc repo, viết mã, mở pull request. Phần đó diễn ra trong công cụ lập trình của bạn, không phải ở đây.
Đính kèm pull request.
curl -X POST https://eastagiletracker.com/api/v1/projects/$PROJECT_ID/stories/$STORY_ID/links \ -H "X-TrackerToken: $TRACKER_TOKEN" \ -H "Content-Type: application/json" \ -d '{"url": "https://github.com/octocat/hello-world/pull/42"}'Một URL pull request của GitHub được nhận diện đúng như vậy — bạn không phải nói ra. Story và đoạn mã khép lại nó giờ chỉ cách nhau một cú nhấp, theo cả hai chiều.
Kết thúc nó. Chuyển sang finished rồi dừng ở đó. Một feature vẫn còn delivered và accepted phía trước, và đó là các cửa soát xét: ai đó không phải agent quyết định rằng công việc đã đúng. Một chore không có cửa ấy — started → accepted là toàn bộ chặng còn lại của nó.

Token và giới hạn tần suất
Phần tiêu đề “Token và giới hạn tần suất”Mọi lần nhập đều xác thực. Việc lấy issue, bình luận và pull request chạy trên API GraphQL của GitHub, và GraphQL từ chối một yêu cầu không mang token — không có bậc ẩn danh, dù trên repository công khai hay riêng tư. Câu hỏi không bao giờ là có token nào đến GitHub hay không, mà chỉ là token của ai.
Token của chính bạn
Phần tiêu đề “Token của chính bạn”Truyền token trong lời gọi nhập, hoặc --token cho GitHub-to-EAT. Một token truy cập cá nhân chi tiết có quyền đọc issue của repository là đủ. Nó chỉ điều khiển các lời gọi lên GitHub và không gì khác: không bao giờ vào log, không bao giờ vào nhật ký kiểm toán, không bao giờ được lưu trữ, và không bao giờ được trả lại trong một phản hồi hay một lỗi.
Hãy mang token của mình cho mọi việc vượt quá một buổi trình diễn. Khi đó bạn tiêu một ngân sách không ai khác chạm vào, và không bước kiểm tra trước nào có thể từ chối bạn vì bản nhập của người khác.
--engine direct không cho bạn lựa chọn. Engine đó đọc GitHub từ máy bạn chứ không qua Tracker, nên token của máy chủ nằm ngoài tầm với; một lần chạy không token sẽ thoát với mã 2 kèm lỗi cách dùng, trước cả khi nó lấy hay ghi bất cứ thứ gì. GITHUB_TOKEN trong môi trường hoặc trong .env của bạn cũng được tính, y như --token.
Thứ bắt buộc phải có token là lượt duyệt issue, không phải cả engine. direct đọc issue, bình luận và pull request qua GraphQL, vốn không có chế độ ẩn danh; nó chỉ chạm tới REST cho danh sách releases và phép dò /rate_limit miễn phí. Công cụ vẫn còn kèm một bộ lấy dữ liệu REST ẩn danh cũ hơn, từng chạy được một lần nhập repository công khai trong hạn mức 60 mỗi giờ, nhưng không đường nào trong CLI còn chạm tới nó và nó sắp bị xóa — vậy hãy coi --token là bắt buộc với direct.
Token dùng chung của bản triển khai
Phần tiêu đề “Token dùng chung của bản triển khai”Đừng gửi token nào và máy chủ sẽ thay bằng token nền tảng mà người vận hành đã cấu hình (GITHUB_IMPORT_PAT). Ba giới hạn đi kèm theo nó:
- Đó là cấu hình tùy chọn. Dịch vụ eastagiletracker.com được lưu trữ sẵn cấp phát một cái, nên lần nhập repository công khai không token vẫn chạy ở đó. Bản tự lưu trữ — tệp nhị phân bạn tải về — không có cái nào cho tới khi người vận hành đặt
GITHUB_IMPORT_PATtrong môi trường, và cho tới lúc đó nó từ chối mọi lần nhập không token bằng400import_github_no_token. - Nó chỉ đọc repository công khai. Dịch vụ được lưu trữ cấp nó ở chế độ chỉ đọc trên các repo công khai, nên một repository riêng tư luôn cần token của chính bạn.
- Mọi bên gọi trên bản triển khai dùng chung một ngân sách. Trước khi một lần nhập không token chạy, máy chủ đọc số điểm GraphQL còn lại của token dùng chung và từ chối bằng
400import_github_shared_quota_lowkhi dưới 500. Ngân sách cạn giữa chừng sẽ khiến job thất bại vớiimport_github_rate_limited_platform. Cả hai thông báo đều chỉ ra cùng một cách khắc phục: cung cấp token của chính bạn.
Token mua cho bạn điều gì
Phần tiêu đề “Token mua cho bạn điều gì”GitHub đo hai API của mình riêng rẽ, và trần khi không xác thực thấp hơn hai bậc độ lớn.
| API GitHub | Dùng cho | Có token | Không có token |
|---|---|---|---|
| GraphQL | Issue, bình luận, pull request, issue con, phụ thuộc | 5.000 điểm mỗi giờ, tính theo số nút mà truy vấn trả về | Bị từ chối — GraphQL không có bậc ẩn danh |
| REST | Release (include_releases) và bước kiểm tra trước /rate_limit | 5.000 yêu cầu mỗi giờ | 60 yêu cầu mỗi giờ, đếm theo địa chỉ IP và chia chung với mọi người phía sau nó |
Một bản nhập không bao giờ rơi xuống bậc 60 lượt mỗi giờ ấy: không có token để gửi thì yêu cầu bị từ chối ngay từ đầu, chứ không thử lại ẩn danh. Con số đó quan trọng với những gì bạn làm xung quanh bản nhập — một script đọc GitHub trực tiếp, hay một shell nằm cùng mạng với các client khác, tiêu hết 60 yêu cầu trong vài giây.
Bạn có thể đọc ngân sách còn lại bất cứ lúc nào; GET /rate_limit được miễn khỏi cả hai giới hạn, nên lần kiểm tra ấy không tốn gì:
curl -H "Authorization: Bearer $GITHUB_TOKEN" https://api.github.com/rate_limitĐiểm GraphQL không phải là số yêu cầu. GitHub tính điểm một truy vấn theo số nút nó trả về, nên một trang gồm 100 issue kèm bình luận và người được giao đã tốn nhiều điểm, và một repository lớn tiêu hết ngân sách theo giờ trong số lời gọi ít hơn nhiều so với những con số thời REST gợi ra. --dry-run (bước 3) và dry_run (bước 4) mỗi cái tốn đúng số điểm như lần lấy dữ liệu thật — chính điều đó khiến các con số của chúng đáng tin — nên hãy dự trù hai lượt khi bạn kiểm tra trước một bản nhập lớn.
Đi tiếp đâu nữa
Phần tiêu đề “Đi tiếp đâu nữa”- Hướng dẫn API — ngữ pháp tìm kiếm, luồng sự kiện, chuyển trạng thái hàng loạt, ghi idempotent và phần còn lại của bề mặt.
- Hướng dẫn vận hành — cũng những thao tác đó nhưng từ giao diện, và mười trình nhập còn lại.
- Giới thiệu — vì sao máy trạng thái và bốn loại story lại có hình hài như vậy.
- GitHub-to-EAT — repository của chính trình nhập: mọi cờ, cả hai engine, và cách đóng góp cho nó.