SSD Nodes Learn 🎉 VPS $5.50/மாதம் முதல்
கல்வி வழிகாட்டிகள் Matt Connorஆல் Matt Connor · புதுப்பிக்கப்பட்டது 2026-08-13

VPS-ல் சொந்தமாக AI PR Review Agent அமைப்பது எப்படி?

உங்கள் VPS-ல் AI PR review agent-ஐ நிறுவுவது எப்படி என்பதை அறியுங்கள். Diff-scoped prompts, inline comments மற்றும் API செலவுகளைக் குறைக்கும் முறைகள் குறித்த விரிவான வழிகாட்டி இது.

Self-hosted PR review agent-ன் செயல்பாடுகள்

Self-hosted PR review agent என்பது நீங்கள் சொந்தமாக வைத்திருக்கும் server-ல் இயங்கும் ஒரு சிறிய நிரலாகும். இது ஒரு pull request (PR)-ன் diff-ஐப் படித்து, மாற்றப்பட்ட வரிகளை மட்டும் ஒரு model-க்கு அனுப்பும். அங்கிருந்து வரும் பதில், inline review comments-ஆகப் பதிவிடப்படும். இது உங்கள் branch-ஐ checkout செய்யாது; pull request-ல் தொடப்படாத எந்தக் கோப்பையும் இது படிக்காது. இது வைத்திருக்கும் ஒரே credentials, ஒரு model API (application programming interface) key மற்றும் கருத்துகளைப் பதிவிட மட்டுமே பயன்படும் ஒரு token ஆகும்.

ஒரு model-ஆல் diff-ஐப் படிக்க முடியும். அந்தப் பகுதி ஏற்கனவே தீர்க்கப்பட்டுவிட்டது. diff எங்கே செல்கிறது மற்றும் அந்த key யாரிடம் உள்ளது என்பதுதான் முக்கியம். Hosted review bot-ஐப் பயன்படுத்தினால், ஒவ்வொரு private repository-யிலிருந்தும் diff உங்கள் network-ஐ விட்டு வெளியேறி, மூன்றாம் தரப்பினரின் logs-ல் சேமிக்கப்பட்டு, அவர்களின் retention policy-க்கு உட்பட்டு இருக்கும். நீங்கள் சொந்தமாக வைத்திருக்கும் VPS (virtual private server)-ல், diff ஆனது GitHub-லிருந்து உங்கள் server-க்கு வந்து, அங்கிருந்து model API-க்குச் செல்லும். எதை அனுப்ப வேண்டும் என்பதைத் தீர்மானிக்கும் அந்த நாற்பது வரிக் குறியீட்டை (code) நீங்களே நேரடியாகப் படிக்க முடியும்.

தொடங்குவதற்கு முன் உங்களுக்குத் தேவையானவை

  • Ubuntu 24.04 இயங்கும் ஒரு VPS, அதில் ஏற்கனவே self-hosted GitHub Actions runner பதிவு செய்யப்பட்டிருக்க வேண்டும். runner-ஐப் பதிவு செய்யும்போது அதற்கு pr-review என்ற கூடுதல் label-ஐ வழங்கவும், ஏனெனில் கீழே உள்ள workflow அந்த label-ஐ அடிப்படையாகக் கொண்டே இயங்கும்.
  • Claude Console-லிருந்து பெறப்பட்ட ஒரு Anthropic API key.
  • pull request-ஐ யார் திறக்கலாம் என்பதைக் கட்டுப்படுத்தக்கூடிய ஒரு repository. private repository-ஆக இருந்தால் இது எளிது. பொதுவான (public) repository-களுக்கான fork பகுதி கீழே விவரிக்கப்பட்டுள்ளது, ஆனால் அதில் உள்ள தீர்வு சற்று சிக்கலானது.

VPS-ல் reviewer-ஐ நிறுவுதல்

Runner service, நீங்கள் ./svc.sh install-ஐ இயக்கும்போது உருவாக்கிய unprivileged account-ல் இயங்குகிறது. Job-கள் sudo இன்றி இயங்குவதற்கு, அதே account-ன் கீழ் reviewer-ஐ நிறுவவும். கீழே உள்ள runner-க்கு பதிலாக உங்கள் account பெயரை மாற்றவும்.

sudo apt update && sudo apt install -y gh python3-venv
sudo install -d -m 755 -o runner -g runner /opt/pr-review
sudo -u runner python3 -m venv /opt/pr-review/venv
sudo -u runner /opt/pr-review/venv/bin/pip install anthropic
gh --version

ஆகஸ்ட் 2026 நிலவரப்படி, Ubuntu 24.04-ல் gh --version, gh version 2.45.0-ஐ அச்சிடுகிறது. 2.20-க்கு பிந்தைய எந்தவொரு release-லும் கீழே பயன்படுத்தப்பட்டுள்ள --input flag உள்ளது. Command 'gh' not found என்ற செய்தி வந்தால், universe component enabled செய்யப்படவில்லை என்று பொருள்; எனவே sudo add-apt-repository universe-ஐ இயக்கி மீண்டும் முயற்சிக்கவும்.

Key மற்றும் token-ன் இருப்பிடம்

இரண்டு ரகசியங்கள், இரண்டு வெவ்வேறு ஆயுட்காலங்கள். இவை இரண்டையும் repository-க்குள் வைக்கக்கூடாது.

ANTHROPIC_API_KEY என்பது ஒரு repository ரகசியம். இதை Settings, பிறகு Secrets and variables, அதன் பின் Actions என்ற பகுதியில் அமைக்க வேண்டும். GitHub இதை encrypt செய்து, runtime-ல் அந்த step-ன் environment-க்குள் செலுத்துகிறது. இது ஒருபோதும் disk-ல் கோப்பாக இருக்காது, git history-யிலும் இடம்பெறாது.

GITHUB_TOKEN வித்தியாசமாகச் செயல்படுகிறது. ஒவ்வொரு job-க்கும் Actions ஒரு புதிய token-ஐ உருவாக்கி, job முடிந்ததும் அதை அழித்துவிடும். அந்த token என்ன செய்ய முடியும் என்பது workflow-ல் உள்ள permissions: block மூலம் தீர்மானிக்கப்படுகிறது. எனவே, குறைந்தபட்ச அதிகார வரம்பு (least privilege) இங்குதான் நடைமுறைப்படுத்தப்படுகிறது:

permissions:
  contents: read
  pull-requests: write

அந்த token-ஆல் ஒரு review-ஐப் பதிவிட முடியும். ஆனால், ஒரு commit-ஐ push செய்யவோ, branch-ஐ merge செய்யவோ, workflow கோப்பைத் திருத்தவோ அல்லது வேறொரு repository-ஐ அணுகவோ முடியாது. கருத்து தெரிவிக்கக்கூடிய ஒரு agent, ஒரு reviewer மட்டுமே. ஒரு commit-ஐ push செய்யக்கூடிய agent, ஒரு committer ஆவான்; இதற்கு யாரும் ஒப்புதல் அளிக்கவில்லை. Model key-ஐயும் அதே கவனத்துடன் கையாளவும், ஏனெனில் அது உங்கள் கணக்கில் பணத்தைச் செலவழிக்கும். இத்தகைய சிக்கல்கள் குறித்து AI agent-ன் அணுகலுக்கு அப்பாற்பட்ட ரகசியங்கள் பகுதியில் மேலும் அறியலாம்.

Actions, job logs-ல் உள்ள துல்லியமான ரகசியச் சரத்தை (secret string) *** என்று மாற்றுகிறது. இது அந்தச் சரத்தை மட்டும் சரியாகப் பொருத்தி மாற்றும். எனவே, நீங்கள் base64 encode செய்த, இரண்டு வரிகளாகப் பிரித்த அல்லது ஒவ்வொரு எழுத்தாக print செய்த key-கள் அப்படியே தெளிவாகத் தெரியும். Environment-ஐ dump செய்யும் debug step-ஐ ஒருபோதும் சேர்க்க வேண்டாம்.

Fork-லிருந்து வரும் pull request ஏன் உங்கள் API key-ஐப் பார்ப்பதில்லை

GitHub-ன் விதி சுருக்கமானது: GITHUB_TOKEN-ஐத் தவிர, ஒரு forked repository-யிலிருந்து workflow தூண்டப்படும்போது secrets runner-க்கு அனுப்பப்படாது. எனவே, fork-லிருந்து இயங்கும் ஒரு pull_request உங்கள் script-ஐ எந்த ANTHROPIC_API_KEY-உம் இல்லாமல் தொடங்கும், இதனால் முதல் API அழைப்பு invalid x-api-key பிழையுடன் தோல்வியடையும்.

இதற்கு எளிதான தீர்வாக trigger-ஐ pull_request_target-க்கு மாற்றுவது தோன்றும், இது base repository-ன் சூழலில் இயங்குவதால் secrets-ஐப் பெறும். அதை இங்கே செய்ய வேண்டாம். GitHub-ன் பாதுகாப்பு வழிகாட்டுதல், அத்தகைய workflow-கள் "privileged ஆனவை, அதாவது அவை main branch-ன் cache-ஐ மற்ற privileged workflow-களுடன் பகிர்ந்து கொள்கின்றன, மேலும் repository-ல் எழுதும் உரிமையையும் (write access) secrets-ஐ அணுகும் உரிமையையும் கொண்டிருக்கலாம்" என்றும், இதன் முடிவுகள் "repository-யைக் கைப்பற்றப் பயன்படுத்தப்படலாம்" என்றும் எச்சரிக்கிறது.

runner-ஐப் பொறுத்தவரை அதே வழிகாட்டுதல் தெளிவாக உள்ளது: "GitHub-ல் உள்ள public repositories-க்கு self-hosted runners-ஐப் பயன்படுத்தவே கூடாது, ஏனெனில் எந்தவொரு பயனரும் pull requests-ஐ உருவாக்கி சூழலை (environment) சமரசம் (compromise) செய்ய முடியும்."

இது இரண்டு வடிவமைப்பு முடிவுகளை எடுக்கத் தூண்டுகிறது. இந்த job ஒரு guard-ஐக் கொண்டுள்ளது, எனவே இது உங்கள் சொந்த repository-க்கு push செய்யப்படும் branches-ல் மட்டுமே இயங்கும். மேலும், இந்த workflow-ல் actions/checkout படிநிலையே இல்லை. agent-ன் வட்டில் (disk) அந்த branch இருக்காது, எனவே ஒரு hostile pull request என்பது model-க்கு அனுப்பப்படும் வெறும் உரை (text) மட்டுமே. அது உங்கள் VPS-ல் எந்த build script-ஐயும் இயக்க முடியாது, ஏனெனில் உங்கள் VPS-ல் எதுவும் அதை இயக்குவதில்லை. இருப்பினும், உரை (text) என்பது பாதிப்பில்லாதது என்று அர்த்தமல்ல: ஒரு அந்நியரால் எழுதப்பட்ட diff என்பது model-க்கு வரும் நம்பகத்தன்மையற்ற உள்ளீடு (untrusted input). இது நீங்கள் agent-க்கு web search அனுமதிக்கும்போது சந்திக்கும் அதே பாதுகாப்பு எல்லைதான். இங்கே அதைக் கட்டுப்படுத்தும் ஒரே விஷயம் என்னவென்றால், இந்த agent-ஆல் ஒரு comment-ஐப் பதிவிடுவதைத் தவிர வேறு எதையும் செய்ய முடியாது.

Repository-ஐப் பதிவிறக்காமல் diff-ஐ மட்டும் பெறுதல்

ஒரே ஒரு கோரிக்கையின் மூலம் முழு diff-ஐயும் plain text வடிவில் பெற முடியும்.

export GH_TOKEN=your_token   # in the workflow this comes from secrets.GITHUB_TOKEN
gh api /repos/OWNER/REPO/pulls/42 -H "Accept: application/vnd.github.diff"

Accept: application/vnd.github.diff media type-ஐப் பயன்படுத்தும்போது, pull request-ஐ விவரிக்கும் JSON object-க்கு பதிலாக unified diff நேரடியாகக் கிடைக்கும். gh api கட்டளையானது அந்தப் பதிலை மாற்றமின்றி அப்படியே அச்சிடும். நீங்கள் காணும் முதல் வரி diff --git a/ என்று தொடங்க வேண்டும். gh: Not Found (HTTP 404) என்ற பதில் வந்தால், அந்த token-க்கு repository-ஐ அணுகும் அனுமதி இல்லை என்று பொருள். fine-grained personal token-ஐப் பயன்படுத்தும்போது, பெரும்பாலும் Pull requests அனுமதி வழங்கப்படாததே இதற்குக் காரணமாக இருக்கும்.

டோக்கன்களைச் செலவிடும் முன் வடிகட்டுதல்

இந்த பகுதிதான் ஒரு bot-ஐ பயனர்கள் வாசிப்பதற்கும், mute செய்வதற்கும் இடையிலான வித்தியாசத்தை தீர்மானிக்கிறது. கீழே உள்ள ஒவ்வொரு வடிகட்டியும் (filter), model ஒரு byte-ஐப் பார்ப்பதற்கு முன்பே இயங்குகிறது.

  • Path filters. Lock files, vendored directories, minified bundles மற்றும் உருவாக்கப்பட்ட code-களைத் தவிர்க்கவும். package-lock.json-ல் ஒரு model இடும் comment தேவையற்ற இரைச்சல் (noise) ஆகும், மேலும் diff-ல் உள்ள பெரும்பாலான bytes இத்தகைய கோப்புகளிலேயே இருக்கின்றன.
  • A size cap. நிர்ணயிக்கப்பட்ட அளவைத் தாண்டினால், review-ஐத் தவிர்த்துவிட்டு வெற்றிகரமாக வெளியேறவும். 4,000 வரிகள் கொண்ட refactor-க்கு, அறுபது தவறான யூகங்களை வழங்குவதற்குப் பதிலாக, அது தானியங்கி முறையில் review செய்ய முடியாத அளவுக்குப் பெரியது என்று ஒரே ஒரு உண்மையான வரியை மட்டும் பதிவிடவும்.
  • A severity threshold and a comment cap. High மற்றும் medium வகை முடிவுகளை மட்டும் தெரிவிக்கவும்; அதிகபட்சம் பத்து கருத்துகள் வரை, மிக முக்கியமான பாதிப்புகளுக்கு முன்னுரிமை அளிக்கவும். பதினோராவது கருத்தை யாரும் வாசிப்பதில்லை.

ஸ்கிரிப்ட்

இதை /opt/pr-review/review.py எனச் சேமிக்கவும். இது தனது உள்ளமைவை (configuration) environment-லிருந்து வாசிப்பதால், குறியீட்டை மாற்றாமலேயே workflow-ல் மாதிரிகளை (models) மாற்ற முடியும்.

#!/usr/bin/env python3
"""Review only the changed lines of one pull request."""
import json
import os
import subprocess
import sys

import anthropic

REPO = os.environ["GITHUB_REPOSITORY"]
PR = os.environ["PR_NUMBER"]
MODEL = os.environ.get("REVIEW_MODEL", "claude-haiku-4-5-20251001")
MAX_DIFF_BYTES = int(os.environ.get("MAX_DIFF_BYTES", "120000"))
MIN_SEVERITY = os.environ.get("MIN_SEVERITY", "medium")
MAX_COMMENTS = 10
RANK = {"low": 0, "medium": 1, "high": 2}
SKIP = ("package-lock.json", "poetry.lock", "/vendor/", "/node_modules/", ".min.js")

raw_diff = subprocess.run(
    ["gh", "api", f"/repos/{REPO}/pulls/{PR}",
     "-H", "Accept: application/vnd.github.diff"],
    check=True, capture_output=True, text=True,
).stdout

ஒவ்வொரு கோப்பிற்கும் தனித்தனியாக diff-ஐப் பிரிப்பதுதான் path filtering-ஐச் சாத்தியமாக்குகிறது. ஒவ்வொரு வரியையும் எண்ணிடுவதுதான் review கருத்துகள் சரியான இடத்தில் விழுவதை உறுதி செய்கிறது. GitHub ஒரு inline கருத்தை diff-ன் ஒரு பகுதியாக இருக்கும் வரியில் மட்டுமே ஏற்கும், எனவே மாதிரி (model) ஒரு உண்மையான வரி எண்ணைக் குறிப்பிட வேண்டும். எண்களை அதற்கு வழங்குவதன் மூலம், அது எண்களைக் கண்டுபிடிப்பதற்குப் பதிலாக, இருக்கும் எண்ணை நகலெடுக்க முடியும்.

def per_file(diff_text):
    """Split a unified diff into one string per file."""
    sections, current = [], []
    for line in diff_text.splitlines():
        if line.startswith("diff --git ") and current:
            sections.append("\n".join(current))
            current = []
        current.append(line)
    if current:
        sections.append("\n".join(current))
    return sections


def annotate(section):
    """Prefix every line that exists in the new file with its line number."""
    out, n, in_hunk = [], 0, False
    for line in section.splitlines():
        if line.startswith("@@"):
            n = int(line.split("+")[1].split(",")[0].split(" ")[0])
            in_hunk = True
            out.append(line)
        elif not in_hunk or line.startswith(("-", "\\")):
            out.append(line)
        else:
            out.append(f"{n}\t{line}")
            n += 1
    return "\n".join(out)


kept = [s for s in per_file(raw_diff)
        if not any(p in s.split("\n", 1)[0] for p in SKIP)]
payload = "\n".join(annotate(s) for s in kept)

if not payload.strip():
    print("every changed file was filtered out")
    raise SystemExit(0)
if len(payload) > MAX_DIFF_BYTES:
    print(f"diff is {len(payload)} bytes, over the {MAX_DIFF_BYTES} cap")
    raise SystemExit(0)

Hunk header வரி எண்களைக் கொண்டுள்ளது. @@ -12,7 +12,9 @@ என்பது புதிய கோப்பின் hunk வரிசை 12-ல் தொடங்குகிறது என்பதைக் குறிக்கிறது, எனவே counter அங்கிருந்து தொடங்கி, சேர்க்கப்பட்ட மற்றும் மாற்றப்படாத வரிகளில் மட்டும் முன்னேறுகிறது. நீக்கப்பட்ட வரிகள் எண்ணிடப்படாமல் கடந்து செல்லும், ஏனெனில் அவை புதிய கோப்பில் இருப்பதில்லை. backslash-ல் தொடங்கும் வரிகளுக்கான guard, கோப்பின் இறுதியில் git எழுதும் no-newline குறியீட்டைத் தவிர்க்கிறது; இல்லையெனில் அது அடுத்தடுத்த அனைத்து எண்களையும் ஒவ்வொன்றாகத் தள்ளிவிடும்.

இரண்டு exits-களும் status 1-க்கு பதிலாக 0-ஐப் பயன்படுத்துகின்றன. வடிகட்டப்பட்ட அல்லது அதிக அளவுள்ள pull request ஒரு பச்சை நிறக் குறியைக் காட்ட வேண்டும். மனிதர்களால் நடவடிக்கை எடுக்க முடியாத சிவப்பு நிறக் குறி புறக்கணிக்கப்படும், ஒருமுறை ஒரு குறி புறக்கணிக்கப்பட்டால், மற்ற அனைத்தும் புறக்கணிக்கப்படும்.

SYSTEM = (
    "You review one pull request diff. Every line that exists in the new file is "
    "prefixed with its line number and a tab character. "
    "Report only defects you can see in the lines shown: a crash, a resource leak, "
    "a security mistake, a wrong boundary condition, a broken contract with code "
    "that is visible in this diff. Do not comment on style, naming or formatting. "
    "Do not guess about code you cannot see. Leave out anything you are not "
    "certain about. An empty findings list is a normal and common answer. "
    'Reply with JSON only, in this shape: {"findings": [{"path": "src/app.py", '
    '"line": 42, "severity": "high", "comment": "what is wrong, then why"}]} '
    "Every line number must be one you can see in the left column of that file."
)

client = anthropic.Anthropic()
message = client.messages.create(
    model=MODEL,
    max_tokens=2000,
    system=SYSTEM,
    messages=[{"role": "user", "content": payload}],
)
print(f"stop={message.stop_reason} in={message.usage.input_tokens} "
      f"out={message.usage.output_tokens}", file=sys.stderr)

text = message.content[0].text
findings = json.loads(text[text.find("{"):text.rfind("}") + 1])["findings"]
findings = [f for f in findings if RANK.get(f["severity"], 0) >= RANK[MIN_SEVERITY]]
findings.sort(key=lambda f: -RANK.get(f["severity"], 0))
del findings[MAX_COMMENTS:]

if not findings:
    print("nothing above the severity threshold; posting no comment")
    raise SystemExit(0)

review = {
    "event": "COMMENT",
    "body": f"Automated review of the changed lines. {len(findings)} finding(s).",
    "comments": [
        {"path": f["path"].removeprefix("b/"), "line": f["line"], "side": "RIGHT",
         "body": f"**{f['severity']}** {f['comment']}"}
        for f in findings
    ],
}
subprocess.run(
    ["gh", "api", "-X", "POST", f"/repos/{REPO}/pulls/{PR}/reviews", "--input", "-"],
    input=json.dumps(review), text=True, check=True,
)

அந்தத் தொகுதியில் உள்ள மூன்று விவரங்கள் முக்கியமானவை. JSON ஆனது முதல் { மற்றும் கடைசி }-க்கு இடையில் வெட்டப்படுகிறது, ஏனெனில் மாதிரி சில நேரங்களில் தனது பதிலை code fence-க்குள் வைக்கும், மேலும் json.loads அந்த fence-ஐக் கண்டு தடுமாறும். path-லிருந்து தொடக்கத்திலுள்ள b/ நீக்கப்படுகிறது, ஏனெனில் அந்த prefix diff header-லிருந்து வருகிறது, ஆனால் GitHub-க்கு repository-ஐச் சார்ந்த path தேவைப்படுகிறது. மேலும் --input - முழு review-வையும் ஒரே API அழைப்பாக அனுப்புகிறது, இதனால் பத்து கண்டுபிடிப்புகள் பத்து அறிவிப்புகளாக வராமல் ஒரே அறிவிப்பாக வரும்.

அறிக்கை செய்ய எதுவும் இல்லாதபோது, ஸ்கிரிப்ட் எதையும் பதிவிடாது. ஒவ்வொரு pull request-லும் "no issues found" என்று எழுதும் bot, மக்கள் அதைப் படிக்காமல் கடந்து செல்லப் பழக்கிவிடும், இதனால் முக்கியமான அறிவிப்பு வரும்போதும் அவர்கள் அதைக் கவனிக்காமல் கடந்து விடுவார்கள்.

பணிப்பாய்வில் (workflow) இணைத்தல்

இதை .github/workflows/pr-review.yml கோப்பாகச் சேமிக்கவும்:

name: pr-review

on:
  pull_request:
    types: [opened, synchronize, reopened]
    paths-ignore:
      - '**.md'
      - 'docs/**'

permissions:
  contents: read
  pull-requests: write

concurrency:
  group: pr-review-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  review:
    if: github.event.pull_request.head.repo.full_name == github.repository && !contains(github.event.pull_request.labels.*.name, 'no-ai-review')
    runs-on: [self-hosted, linux, pr-review]
    steps:
      - name: Review the changed lines
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
          PR_NUMBER: ${{ github.event.pull_request.number }}
          REVIEW_MODEL: claude-haiku-4-5-20251001
          MIN_SEVERITY: medium
        run: /opt/pr-review/venv/bin/python /opt/pr-review/review.py

GITHUB_REPOSITORY அந்த env: தொகுப்பில் இல்லை, ஏனெனில் Actions ஒவ்வொரு பணிக்கும் (job) அதை ஏற்கனவே அமைத்துவிடுகிறது. concurrency குழு கட்டணக் கணக்கீட்டிற்கு முக்கியமானது: இது இல்லையெனில், ஒரு branch-ல் மூன்று விரைவான திருத்தங்களை (quick fixes) அனுப்பும்போது, மூன்று முழுமையான ஆய்வுகள் (reviews) நடைபெறும், நீங்கள் மூன்றிற்கும் கட்டணம் செலுத்த வேண்டியிருக்கும். இதைப் பயன்படுத்தினால், கடைசியாக அனுப்பப்பட்டது மட்டுமே எஞ்சியிருக்கும்.

if: வரி இரண்டு பணிகளைச் செய்கிறது. முதல் பாதி, fork-களிலிருந்து வரும் pull request-களைத் தவிர்க்கிறது; இவை ஏற்கனவே key இல்லாததால் தோல்வியடையும். இரண்டாம் பாதி உங்கள் குழுவிற்கு ஒரு off switch-ஐ வழங்குகிறது: ஒரு pull request-ல் no-ai-review label-ஐச் சேர்த்தால், அந்தப் பணி இயங்காது.

ஒரு pull request-ஐத் திறந்து என்ன நடக்கிறது என்று கவனிக்கவும்:

gh run list --workflow=pr-review.yml --limit 3
gh run view --log
gh pr view 42 --comments

சில நொடிகளில் முடிந்து, log-ல் nothing above the severity threshold; posting no comment என்று காட்டினால், அது சரியாகச் செயல்படுகிறது என்று அர்த்தம். சிறிய மற்றும் தெளிவான pull request-களில் இதுவே எதிர்பார்க்கப்படும் முடிவாகும்.

தானியங்கி pull request மதிப்பாய்விற்கு எவ்வளவு செலவாகும்?

Diff-ன் அளவுதான் உள்ளீட்டின் பெரும்பகுதியாக இருப்பதால், அதன் அளவே விலையைத் தீர்மானிக்கிறது. கீழே 500 வரிகள் கொண்ட ஒரு diff மற்றும் system prompt ஆகியவற்றின் அளவு, மதிப்பீடாக இல்லாமல் token counting endpoint மூலம் கணக்கிடப்பட்டுள்ளது.

ChartTokens for one 500 line pull request diff, measured August 2026
The data behind this chart
[
  {
    "label": "Haiku 4.5",
    "input_tokens": "8,000",
    "output_tokens": "1,200"
  },
  {
    "label": "Sonnet 5",
    "input_tokens": "10,400",
    "output_tokens": "1,560"
  },
  {
    "label": "Opus 5",
    "input_tokens": "10,400",
    "output_tokens": "1,560"
  }
]

அந்த diff, Haiku 4.5-ல் 8,000 input tokens-ஆகவும், Sonnet 5-ல் 10,400 tokens-ஆகவும் கணக்கிடப்பட்டது. ஒரே உரை, ஆனால் வெவ்வேறு எண்ணிக்கை. 4.7-க்கு பிந்தைய Claude மாதிரிகள் புதிய tokenizer-ஐப் பயன்படுத்துகின்றன; இது ஒரே உள்ளீட்டிற்கு சுமார் 30% கூடுதல் tokens-ஐ உருவாக்குகிறது. இதை Anthropic அதன் விலை நிர்ணயப் பக்கத்தில் குறிப்பிட்டுள்ளது. ஒரு புதிய மாதிரியை பழைய மாதிரியுடன் ஒப்பிடும்போது, மில்லியன் tokens-க்கான விலையை மட்டும் பார்க்காமல் இதையும் கணக்கில் கொள்ளவும்.

ஆகஸ்ட் 2026 நிலவரப்படி பட்டியல் விலைகள்: Haiku 4.5-க்கு ஒரு மில்லியன் input tokens-க்கு $1 மற்றும் output tokens-க்கு $5. Sonnet 5-க்கு 31 ஆகஸ்ட் 2026 வரை அறிமுக விலையாக $2 மற்றும் $10, அதன் பிறகு $3 மற்றும் $15. Opus 5-க்கு $5 மற்றும் $25.

ChartCost of that one review at list prices, August 2026
The data behind this chart
[
  {
    "label": "Haiku 4.5",
    "cost_per_pr_cents": 1.4,
    "cost_200_prs_usd": "2.80"
  },
  {
    "label": "Sonnet 5",
    "cost_per_pr_cents": 3.64,
    "cost_200_prs_usd": "7.28"
  },
  {
    "label": "Opus 5",
    "cost_per_pr_cents": 9.1,
    "cost_200_prs_usd": "18.20"
  }
]

இது Haiku 4.5-ல் ஒரு pull request-க்கு 1.4 cents மற்றும் Opus 5-ல் 9.1 cents ஆகும். மாதம் 200 pull requests-ஐ merge செய்யும் ஒரு குழு, Haiku 4.5-ல் சுமார் $2.80, Sonnet 5-ல் $7.28, அல்லது Opus 5-ல் $18.20 செலவழிக்கும். 1 செப்டம்பர் 2026 முதல், Sonnet 5-ன் விலையை 1.5-ஆல் பெருக்கிக் கொள்ளவும்.

இரண்டு காரணிகள் உண்மையான கட்டணத்தை இந்த மதிப்பீட்டை விட அதிகரிக்கச் செய்யும். synchronize ஒவ்வொரு push-க்கும் மதிப்பாய்வைத் தூண்டுகிறது, எனவே எட்டு முறை push செய்யப்படும் ஒரு active branch-க்கு எட்டு மதிப்பாய்வுகள் தேவைப்படும்; concurrency விதி, push-கள் மிக நெருக்கமாக நடக்கும்போது மட்டுமே உதவும். மேலும், path filters சரியாகச் செயல்படுவதாகவே இந்த எண்கள் கணக்கிடப்பட்டுள்ளன: வடிகட்டப்படாத ஒரு lock file மட்டும் உள்ளீட்டின் அளவை இருமடங்காக்கக்கூடும்.

Prompt caching இதில் உதவாது. Cached prefix அழைப்புகளுக்கு இடையே byte-identical ஆக இருக்க வேண்டும், ஆனால் diff ஒவ்வொரு முறையும் மாறுகிறது. System prompt மட்டுமே நிலையான பகுதி, அதுவும் குறைந்தபட்ச cacheable நீளத்தை விட மிகக் குறைவாகவே உள்ளது. பொதுவான விதிக்கு, prompt caching எப்போது லாபகரமானது என்பதைப் பார்க்கவும். மேலே உள்ள மூன்று மாதிரிகளில் எதைத் தேர்ந்தெடுப்பது என்பதற்கு, எந்த வேலைக்கு எந்த Claude மாதிரியைப் பயன்படுத்துவது என்பதைப் பார்க்கவும்.

இதைச் செயல்படுத்தும் முன் உங்கள் diff-களை அளவிடவும்

payload உருவாக்கப்பட்ட பிறகு இந்த வரியைச் சேர்த்து, கடந்த மாதத்தின் சில pull requests-ஐக் கொண்டு script-ஐ நீங்களே இயக்கிப் பார்க்கவும்:

print(client.messages.count_tokens(
    model=MODEL, system=SYSTEM, messages=[{"role": "user", "content": payload}]
).input_tokens)

Count endpoint மாதிரியை இயக்காது, எனவே இது input அல்லது output tokens-ஐப் பயன்படுத்தாது. நீங்கள் குறிப்பிடும் மாதிரியின் tokenizer-ஐ மட்டுமே இது பயன்படுத்தும். உங்கள் repository-ல் உள்ள பத்து உண்மையான pull requests-ஐக் கொண்டு இதை இயக்கி, சராசரிக்கு (mean) பதிலாக median-ஐ எடுத்துக்கொள்ளுங்கள்; அப்போதுதான் ஒரு பெரிய migration உங்கள் மதிப்பீட்டைச் சிதைக்காது.

Review bots ஏன் முடக்கப்படுகின்றன மற்றும் அதைத் தவிர்ப்பது எப்படி

இந்த bots மீதான நம்பிக்கையை இரண்டு செயல்பாடுகள் சிதைக்கின்றன. மேலே உள்ள குறியீட்டில் (code) இவை இரண்டிற்கும் தீர்வு உள்ளது.

அனைத்தையும் ஒரே நேரத்தில் ஆய்வு செய்தல். நாற்பது கருத்துகளைப் பதிவிடும் ஒரு bot-ன் எந்தவொரு கருத்தும் வாசிக்கப்படுவதில்லை. Severity threshold மற்றும் பத்து கருத்துகள் என்ற வரம்பு ஆகியவை கண்ணியத்திற்காக அல்ல; முக்கியமான கண்டுபிடிப்புகள் கண்ணுக்குத் தெரிவதற்காகவே இவை உருவாக்கப்பட்டுள்ளன. கருத்துகளைக் குறைப்பதற்கு முன்பு severity அடிப்படையில் வரிசைப்படுத்துவதன் மூலம், தன்னிச்சையான பத்து கருத்துகளுக்குப் பதிலாக, மிகக் குறைந்த முக்கியத்துவம் கொண்டவை நீக்கப்படுவதை உறுதி செய்யலாம்.

சரிபார்க்க முடியாத ஒன்றைப் பற்றி உறுதியாகக் கருத்து தெரிவித்தல். பொறியாளர்கள் ஒரு bot-ஐ நிரந்தரமாக முடக்க இதுவே முக்கிய காரணமாகிறது. 40,000 வரிகளைக் கொண்ட codebase-ல் 200 வரிகளை மட்டும் பார்க்கும் ஒரு model, தான் பார்த்திராத ஒரு கோப்பைப் பற்றி "இது redis_client.py-ல் உள்ள cache invalidation-ஐப் பாதிக்கிறது" என்று தவறாகக் கூறக்கூடும். System prompt-ல் இதற்கான கட்டுப்பாட்டைத் தெளிவாகக் குறிப்பிட வேண்டும்: காட்டப்பட்ட வரிகளில் தெரியும் குறைபாடுகளை மட்டும் அறிக்கை செய்யவும், உறுதியாகத் தெரியாத எதையும் தவிர்க்கவும். பொதுவான துல்லியத்தைக் கோருவதை விட, தோல்வியைச் சுட்டிக்காட்டி நேரடியாகக் கூறுவது சிறப்பாகச் செயல்படும். ஒரு சிறிய மாற்றத்திற்குப் பிறகு, சொல்ல ஏதுமில்லை என்றால், எதையாவது கண்டுபிடித்துச் சொல்ல வேண்டிய அவசியமில்லை என்பதை model-க்கு உணர்த்துவது தேவையற்ற கருத்துகளைத் தவிர்க்க உதவும்.

Review-ஐ COMMENT ஆகப் பதிவிடவும், ஒருபோதும் REQUEST_CHANGES ஆகப் பதிவிட வேண்டாம். ஒரு model-ன் கருத்து merge செய்வதைத் தடுக்கும் அதிகாரத்தைக் கொண்டிருக்கக்கூடாது. அவ்வாறு நடந்தால், காலக்கெடு நெருக்கடியில் இருப்பவர்கள் அந்த bot-உடன் விவாதிப்பதற்குப் பதிலாக, அந்த முழு workflow-ஐயும் நீக்கிவிடுவார்கள்.

தோல்வி முறைகள் மற்றும் நீங்கள் காணும் செய்திகள்

மதிப்பாய்வை (review) பதிவேற்றும்போது HTTP 422 பிழை. gh ஆனது gh: Unprocessable Entity (HTTP 422)-ஐ அச்சிடுகிறது, மேலும் பதில் பகுதியில் (response body) அந்தப் புலத்தின் பெயர் இருக்கும்: Pull request review thread line must be part of the diff. GitHub-ஆல் அந்தக் கருத்தை (comment) இணைக்க முடியவில்லை. இதற்கு வழக்கமான காரணங்கள்: மாதிரி (model) உருவாக்கிய வரி எண், b/ முன்னொட்டைக் கொண்ட path, அல்லது நீக்கப்பட்ட வரியில் கருத்து தெரிவித்தல். நீக்கப்பட்ட வரியில் கருத்து தெரிவிக்க, side-ஐ RIGHT-க்கு பதிலாக LEFT என அமைக்க வேண்டும். பதிவேற்றுவதற்கு முன் review JSON-ஐ அச்சிட்டு, ஒரு கருத்தை diff-உடன் ஒப்பிட்டுச் சரிபார்க்கவும்.

மாதிரி API-லிருந்து invalid x-api-key பிழை. முதல் messages.create அழைப்பின்போது இந்த நிலை தோல்வியடைகிறது. ஒன்று, களஞ்சியத்தில் (repository) ANTHROPIC_API_KEY ரகசியம் (secret) அமைக்கப்படவில்லை, அல்லது pull request ஒரு fork-லிருந்து வந்ததால் Actions எந்த ரகசியத்தையும் அனுப்பவில்லை. if: வரியில் உள்ள fork guard அதைத் தவிர்த்திருக்க வேண்டும், எனவே முதலில் அந்த வரியைச் சரிபார்க்கவும்.

gh: Resource not accessible by integration (HTTP 403) பிழை. job token-ஆல் pull request-ல் எழுத முடியவில்லை. permissions: தொகுதியில் pull-requests: write-ஐச் சேர்க்கவும். அது ஏற்கனவே அங்கு இருந்தால், Settings, பின்னர் Actions, பிறகு General பகுதிக்குச் செல்லவும். அங்குள்ள நிறுவனக் கொள்கை (organisation policy), workflow token எவற்றையெல்லாம் கோரலாம் என்பதைத் தடுத்திருக்கலாம்.

json.decoder.JSONDecodeError பிழை. மாதிரி (model) பகுப்பாய்வு செய்யக்கூடிய JSON-ஐத் தரவில்லை. இதற்குப் பொதுவான காரணம், பதில் (response) token வரம்பை எட்டி, object-ன் பாதியிலேயே நின்றுவிட்டது. இதற்காக log வரியில் stop_reason அச்சிடப்படும்: max_tokens என்ற மதிப்பு இருந்தால், max_tokens-ஐ அதிகரிக்கவும் அல்லது MAX_COMMENTS-ஐக் குறைக்கவும்.

Workflow இயங்கவே இல்லை. pull request-க்கு gh run list எதையும் காட்டவில்லை. paths-ignore மாற்றப்பட்ட அனைத்துக் கோப்புகளையும் வடிகட்டிவிடவில்லை என்பதைச் சரிபார்க்கவும். பின்னர் fork guard மற்றும் label guard-ஐச் சரிபார்க்கவும். இறுதியாக, VPS-ல் sudo systemctl status 'actions.runner.*' மூலம் runner இயங்குகிறதா என்று பார்க்கவும். runner ஆஃப்லைனில் இருந்தால், pull request-ல் எந்தப் பிழைச் செய்தியும் இன்றி job வரிசையில் (queued) காத்திருக்கும்.

ஒவ்வொரு மதிப்பாய்வும் காலியாக வருகிறது. ஒரு முறை இயக்கும்போது MIN_SEVERITY-ஐ low என அமைக்கவும். முடிவுகள் தெரிந்தால், threshold சரியாக வேலை செய்கிறது என்று அர்த்தம். எதுவும் தெரியவில்லை என்றால், payload-ஐ அச்சிட்டு, வடிகட்டிகள் (filters) முழு diff-ஐயும் நீக்கிவிடவில்லை என்பதை உறுதிப்படுத்தவும்.

உங்கள் பிற ஏஜெண்டுகளுடன் இதை இயக்குதல்

Reviewer அளவில் சிறியது என்பதால், ஏற்கனவே மற்ற அனைத்தையும் இயக்கும் அதே server-ல் இதையும் நிறுவுவது எளிதானது எனத் தோன்றலாம். ஆனால், repository-ன் பாதுகாப்பு முக்கியமானது என்றால், இதைத் தனித்தே வைத்திருக்கவும். இந்தச் செயல்முறை உங்கள் code-ல் கருத்து தெரிவிக்கக்கூடிய ஒரு token-ஐயும், உங்கள் பணத்தைச் செலவிடக்கூடிய ஒரு key-யையும் கொண்டுள்ளது. மேலும், self-hosted runner என்பது வடிவமைப்பிலேயே workflow code இயங்கும் இடமாகும். sudo உரிமைகள் இல்லாத பிரத்யேக unprivileged account மற்றும் வேறு எந்தப் பணியும் இயங்காத ஒரு host-ஐப் பயன்படுத்துவதே அடிப்படைத் தேவையாகும். நீங்கள் code-ஐ checkout செய்யும் interactive ஏஜெண்டுகளையும் இயக்கினால், ஒவ்வொரு ஏஜெண்டிற்கும் ஒரு disposable VM பயன்படுத்துவதே சிறந்த முறையாகும். VPS-ல் coding ஏஜெண்டை இயக்குவது பொதுவான அமைப்பைப் பற்றி விளக்குகிறது. Anthropic API உங்களுக்குப் புதியது என்றால், VPS-ல் முதல் Claude API app-ஐ உருவாக்குவது இதைவிட எளிமையான தொடக்கமாக இருக்கும்.

FAQ

AI PR review agent-க்கு எனது repository-ல் write access தேவைப்படுமா?

தேவைப்படாது. ஒரு review-ஐப் பதிவிட pull-requests: write மற்றும் diff-ஐப் பெற contents: read ஆகிய அனுமதிகள் மட்டுமே அதற்குத் தேவை. இதுவே முழுமையான பட்டியல். இதை workflow-ன் permissions: பகுதியில் நீங்கள் அமைக்கலாம்; இது ஒவ்வொரு job-ன் GITHUB_TOKEN செய்யக்கூடிய செயல்களைக் கட்டுப்படுத்தும். இந்த இரண்டு வரிகளைக் கொண்டு, அந்த agent ஒரு pull request-ல் கருத்துகளைப் பதிவிட முடியுமே தவிர, commit-ஐ push செய்யவோ அல்லது branch-ஐ merge செய்யவோ முடியாது. REQUEST_CHANGES-க்கு பதிலாக event: COMMENT மூலம் review-களைப் பதிவிடுங்கள்; அப்போதுதான் அது merge-ஐத் தடுக்க முடியாது.

எனது review comment ஏன் HTTP 422 பிழையுடன் தோல்வியடைகிறது?

GitHub ஒரு inline review comment-ஐ, pull request diff-ன் ஒரு பகுதியாக இருக்கும் வரியில் மட்டுமே ஏற்கும். அந்த வரியில் இல்லையெனில் அது Pull request review thread line must be part of the diff பிழையைத் தரும். path என்பது repository-ஐப் பொறுத்தவரை சரியாக உள்ளதா என்பதையும், diff header-ல் இருந்து எந்த b/ முன்னொட்டும் (prefix) இல்லாமல் உள்ளதா என்பதையும் சரிபார்க்கவும். மேலும், அந்த வரி எண் அந்த file-ன் ஒரு பகுதியாக (hunk) இருப்பதை உறுதி செய்யவும். side என்பது சேர்க்கப்பட்ட அல்லது மாற்றப்படாத வரிக்கு RIGHT என்றும், நீக்கப்பட்ட வரிக்கு LEFT என்றும் இருக்க வேண்டும். diff-ன் ஒவ்வொரு வரியையும் model-க்கு அனுப்பும் முன்பே அதன் புதிய file வரி எண்ணுடன் முன்னொட்டுவது, model தானாகவே தவறான எண்களை உருவாக்குவதைத் தடுக்கிறது.

forks-லிருந்து வரும் pull request-களைக் கொண்ட public repository-ல் இதை இயக்க முடியுமா?

இந்த வடிவமைப்பில் முடியாது. ஒரு fork-லிருந்து தூண்டப்படும் (triggered) workflow-க்கு GitHub secrets-ஐ வழங்காது. எனவே, model key கிடைக்காமல் அந்த run தோல்வியடையும். மேலும், "public repository-களுக்கு self-hosted runner-களை ஒருபோதும் பயன்படுத்தக்கூடாது" என்று GitHub குறிப்பிடுகிறது. ஏனெனில், எவர் வேண்டுமானாலும் ஒரு pull request-ஐ உருவாக்கி, உங்கள் கணினியில் code-ஐ இயக்கச் செய்ய முடியும். ஒரு public project-க்கு, reviewer-ஐ repository-க்குள்ளேயே push செய்யப்படும் branch-களுக்கு மட்டும் கட்டுப்படுத்துங்கள் (இதைத்தான் if: guard செய்கிறது), அல்லது review செய்யும் படிநிலையை GitHub-hosted runner-க்கு மாற்றுங்கள். அப்போது அந்த diff உங்கள் சொந்த infrastructure-ஐ விட்டு வெளியேறுவதை நீங்கள் ஏற்க வேண்டியிருக்கும்.

pull request review-க்கு நான் எந்த model-ஐப் பயன்படுத்த வேண்டும்?

Haiku 4.5-ல் தொடங்கவும். ஒரு குறிப்பிட்ட வகை பிழைகளை மட்டும் கண்டறியும் வகையில் வரையறுக்கப்பட்ட diff-ஐப் படிப்பது கடினமான தர்க்கச் சிக்கல் அல்ல. மலிவான model-ஐப் பயன்படுத்துவது மாதாந்திரக் கட்டணத்தைக் குறைவாக வைத்திருக்க உதவும். உங்கள் language அல்லது framework-ல் உள்ள உண்மையான பிழைகளை அது தவறவிடுவதாகக் கருதினால் மட்டும் Sonnet 5-க்கு மாறவும்; அதை ஊகிக்காமல் அளவீடு செய்து முடிவு செய்யவும். மூன்றில் Opus 5 அதிகச் செலவு பிடிக்கும் model ஆகும். ஒவ்வொரு feature branch-லும் ஒவ்வொரு push-க்கும் இதைப் பயன்படுத்துவதை விட, release branch-ல் இதைப் பயன்படுத்துவது நியாயமானது.