Accepted. Superseded in part by ADR 0006 for async webhook acknowledgement and worker-time token minting. Agent investigation no longer calls GitHub tools; rate-limit policy applies to server-owned Octokit used for metadata, publish, and workspace prepare.
Large PR reviews drive many GitHub REST calls in a single review run (pg-boss worker job). Production observed sustained Bad credentials errors during bursts; root cause was not proven, but the failure mode matches rate-limit / secondary-limit pressure.
@octokit/plugin-retry alone does not pace requests or honor Retry-After for secondary limits.
-
Global throttling β Compose
@octokit/plugin-throttlingwith@octokit/plugin-retryon everyinstallationOctokit()instance (publish, PR-surface I/O, file listing). Plugin order:retry, thenthrottling(throttling outermost). -
Hook policy (
src/github/octokitThrottle.ts)onRateLimit: retry whenretryCount < PRIMARY_RATE_LIMIT_MAX_RETRIES(2).onSecondaryRateLimit: retry whenretryAfter > 0andretryCount < SECONDARY_RATE_LIMIT_MAX_RETRIES(3).
-
Structured logging β Throttle hooks log
octokit_on_rate_limit/octokit_on_secondary_rate_limitwith method, URL,retryAfter, andretryCount. Circuit open logsgithub_rate_limit_circuit_opened. Never log tokens. -
Circuit breaker β After 3 consecutive classified rate-limit failures in one review or ask run, short-circuit nonessential GitHub API tools for the remainder of the run. Publish/submit tools in
ESSENTIAL_GITHUB_TOOL_NAMESstay available. -
listPullRequestFilesβ Server-side pagination (per_page: 100), capsMAX_PR_FILES_LISTED(default 300) andMAX_PR_FILES_PATCH_BYTES(default 500_000).
- Reviews on large PRs may run longer (throttle waits); ADR 0006 moves review execution out of the webhook request fiber.
- Truncated PRs (>300 files) degrade review coverage by design.
- Throttle state is per-process;
REVIEW_CONCURRENCY > 1or multi-replica deploys can still burst the same installation. - Effective GitHub load scales roughly as
replicas Γ localConcurrencyper queue (see operations.md). - MVP shared circuit: opening a local rate-limit circuit also upserts Postgres
github_installation_rate_limit_circuits(installation_id,open_until,last_error_kind). Other workers check that row before starting review/ask runs and hydrate their local circuit open so they do not immediately re-amplify 403/429 on the same installation.
- Async webhook ack (early
200). - Mid-review installation token re-mint.
- Full Redis Bottleneck clustering (still optional). MVP: Postgres shared circuit above.