Trước khi viết logic review, bạn cần một "đường ống" đưa sự kiện PR đến agent và đưa nhận xét quay lại PR. Bài này thiết lập ba mảnh: quyền truy cập (token), kênh sự kiện (webhook hoặc CI), và khung agent (config + secrets).
1. Chọn quyền truy cập tối thiểu
Agent cần đọc diff và ghi comment. Với GitHub, dùng GitHub App (khuyến nghị) hoặc fine-grained PAT với đúng scope:
pull_requests: read/write— đọc diff, đăng review comment.contents: read— đọc file để lấy ngữ cảnh xung quanh.checks: write— báo trạng thái pass/fail (nếu muốn chặn merge).
write vào contents trừ khi agent thực sự cần commit patch.2. Chọn cách nhận sự kiện
Có hai kiểu kích hoạt, chọn theo hạ tầng của bạn:
# Cách A — chạy trong CI (đơn giản nhất để bắt đầu)
# .github/workflows/review.yml
name: agent-review
on:
pull_request:
types: [opened, synchronize, reopened]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with: { fetch-depth: 0 }
- run: python agent/review.py
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
LLM_API_KEY: ${{ secrets.LLM_API_KEY }}
Cách A (CI) dễ debug, chạy trong runner, không cần server luôn bật. Cách B (webhook + server riêng) phù hợp khi bạn muốn kiểm soát tập trung nhiều repo, nhưng phải tự lo hạ tầng và xác thực chữ ký webhook.
3. Cấu trúc khung agent
agent/
review.py # điểm vào: đọc env, điều phối
git_client.py # lấy diff, đăng comment (bọc API)
llm.py # gọi model, parse output
prompts/ # template prompt tách riêng
config.yml # tiêu chí, ngưỡng, danh sách bỏ qua
File config.yml để không hard-code chính sách:
max_files: 40 # bỏ qua PR quá lớn để tránh nhiễu
ignore_paths:
- "**/*.lock"
- "vendor/**"
severity_block: high # chỉ block khi có lỗi mức high
model: "claude-..."
Các bước thiết lập
- Tạo GitHub App / PAT với scope tối thiểu ở trên.
- Lưu
LLM_API_KEYvà token vào secrets của repo (không commit). - Thêm workflow kích hoạt trên
pull_request. - Viết
git_client.pyđể lấy diff:GET /repos/{o}/{r}/pulls/{n}với headerAccept: application/vnd.github.v3.diff. - Chạy thử một PR nháp, in diff ra log để xác nhận đường ống thông.
Khung tư duy "3 cổng an toàn"
- Cổng bí mật: secrets không bao giờ vào log hay prompt.
- Cổng chi phí: giới hạn kích thước diff gửi cho LLM (token = tiền).
- Cổng quyền: agent chỉ hành động trong phạm vi được cấp.
Sai lầm thường gặp
- Cấp token quá rộng (admin cả tổ chức). Rò rỉ một token như vậy là thảm hoạ; luôn least privilege.
- Gửi toàn bộ repo cho LLM. Bạn chỉ cần diff + vài dòng ngữ cảnh quanh chỗ đổi. Gửi cả repo tốn token và làm loãng tín hiệu.
- Không xác thực chữ ký webhook (với Cách B). Bất kỳ ai cũng có thể giả sự kiện; luôn verify
X-Hub-Signature-256. - Quên xử lý PR khổng lồ. PR 3.000 dòng sẽ vượt context và tốn kém; đặt
max_files/max_linesvà bỏ qua hoặc chia nhỏ. - Log ra diff chứa secret. Nếu ai đó vô tình commit key, đừng để log agent nhân bản nó ra nơi khác.
Ví dụ: lấy diff và ngữ cảnh tối thiểu
Đừng gửi cả file. Với mỗi hunk trong diff, kèm 3–5 dòng xung quanh để LLM hiểu biến đến từ đâu:
def get_pr_diff(owner, repo, number, token):
r = requests.get(
f"https://api.github.com/repos/{owner}/{repo}/pulls/{number}",
headers={"Authorization": f"Bearer {token}",
"Accept": "application/vnd.github.v3.diff"})
r.raise_for_status()
return r.text # unified diff, mặc định đã có 3 dòng ngữ cảnh mỗi hunk
Sau khi có diff, lọc theo ignore_paths và max_files từ config.yml TRƯỚC khi gửi cho LLM — đây là chốt chặn chi phí đầu tiên.
Kiểm thử đường ống trước khi làm lõi
- Mở một PR nháp với vài dòng đổi có chủ đích.
- Chạy workflow, in
diffra log CI và xác nhận đúng nội dung. - Dùng token đăng thử một comment tĩnh ("agent đã kết nối") lên PR.
- Xác nhận secret KHÔNG xuất hiện trong log.
- Chỉ khi cả bốn bước xanh mới sang phần suy luận.