Files
accounted/.github/workflows/pr-agent.yml
T
Jakob Wennberg 2d543ac999 feat(agent): move every model call to Sonnet 5 (#1218)
* feat(agent): move every model call to Sonnet 5

Sonnet 5 is verified enabled on our Bedrock account already: a live probe of
eu.anthropic.claude-sonnet-5 in eu-north-1 answered normally, so no model-access
request was needed. The bare anthropic.claude-sonnet-5 is rejected (on-demand
throughput needs the cross-region inference profile), so the eu. prefix we
already use stays.

This is not a model-string swap. Sonnet 5 REJECTS the fixed thinking budget
outright: thinking {type:'enabled', budget_tokens} returns 400 "not supported
for this model. Use thinking.type.adaptive and output_config.effort". Every
chat intent set a budget, so the assistant would have failed on the first turn
after a bare ID change. Reasoning depth is now an effort level (STANDARD high,
DEEP xhigh), and max_tokens is explicit per tier rather than derived from a
budget that no longer exists.

display:'summarized' is load-bearing, not cosmetic. The default is 'omitted',
which still emits thinking blocks but with empty text. Measured on our own
account at xhigh effort: summarized returned ~1k characters of reasoning, the
default returned none. Without it the collapsible "Tänker ..." block in the
chat would have gone silently empty, which no mocked test would have caught.

Ceilings are raised (16k standard, 24k deep) because Sonnet 5's tokenizer
produces roughly 30% more tokens for the same text and max_tokens now caps
thinking and the visible reply together.

Also resolves the Opus 4.7 landmine recorded in the readiness doc: the composer
comment told ops to flip BEDROCK_OPUS_MODEL_ID to Opus 4.7, which would have
400d every thinking intent against the legacy budget shape. Both model
constants now point at Sonnet 5 and the stale instruction is gone.

Checked but deliberately unchanged: forced tool_choice in atom-selection. The
Sonnet 5 docs require thinking:{type:'disabled'} alongside a forced tool_choice
on Bedrock; probed against our account, the forced call succeeds without it, so
no change was made rather than adding a guard we cannot show is needed.

Other call sites moved too: invoice-inbox extraction, document extraction, the
compliance config, and the CI/CD workflows (pr-agent MODEL and MODEL_WEAK,
swedish-compliance-review, compliance-swarm).

Verified: 11315 tests pass, lint and tsc clean on every touched file, guards
pass.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* fix(agent): review triage: keep the no-thinking output ceiling, finish the model sweep

max_tokens now caps thinking and the visible reply together, so collapsing the
two tiers into one made every non-thinking intent inherit a 16000 ceiling where
it used to have 4096. Give it its own MAX_TOKENS_NO_THINKING instead, set to the
old 4096 scaled ~30% for Sonnet 5's tokenizer so the effective reply length is
unchanged rather than quietly cut.

scripts/swedish-compliance-review.mjs still fell back to Sonnet 4.6 when
REVIEW_MODEL was unset, so a manual run silently used the old model. The initial
sweep only covered .ts and .yml.

pr-agent's FALLBACK_MODELS listed the primary model as its own fallback, which is
not a fallback; dropped it and rewrote the surrounding comments, which still
described Opus 4.8 and a 200k window.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 10:16:40 +02:00

88 lines
4.5 KiB
YAML

name: PR Agent
# AI pull-request review (PR-Agent, the original open-source reviewer: repo id
# 662766482, same repo the qodo-ai/Codium-ai names redirect to). Replaces the
# Greptile bot that went silent after #682.
#
# Supply-chain hardening:
# * Pinned to an immutable commit SHA (v0.36.0), NOT a movable tag, because the
# repo now sits under a recently-created, unverified org (The-PR-Agent).
# * Runs on a DEDICATED, minimal IAM key (bedrock:InvokeModel only) supplied via
# PR_AGENT_AWS_* secrets: never the app's general AWS credentials. A leaked
# PR-Agent key can do nothing but invoke the one Bedrock model.
#
# Scope: ONLY /review runs automatically. /describe and /improve are disabled so
# the bot never overwrites hand-written PR descriptions. Users can still invoke
# any command interactively by commenting e.g. "/describe" or "/improve" on a PR.
on:
pull_request:
types: [opened, reopened, ready_for_review, synchronize]
issue_comment:
types: [created, edited]
# One run per PR *per event type*; a new push (pull_request:synchronize) cancels
# a superseded review. The event_name suffix is critical: without it, the
# pull_request and issue_comment triggers share a group, so a bot comment
# (Vercel/Supabase/compliance preview bots fire within ~2s of opening a PR)
# queues an issue_comment run that cancel-in-progress kills the real review with,
# before the job-level `if: sender.type != 'Bot'` ever gets to skip it. Keeping the
# groups separate lets comment runs cancel only each other (all skipped, harmless)
# and never the open/push review.
concurrency:
group: pr-agent-${{ github.event.pull_request.number || github.event.issue.number }}-${{ github.event_name }}
cancel-in-progress: true
permissions:
contents: read
pull-requests: write
issues: write
jobs:
pr_agent:
# Skip bot-authored events (vercel/supabase/etc.) to avoid feedback loops.
if: ${{ github.event.sender.type != 'Bot' }}
runs-on: ubuntu-latest
name: The PR Agent
steps:
- name: The PR Agent
# Pinned to the v0.36.0 commit SHA (immutable): do not switch to @v0.36.0.
uses: The-PR-Agent/pr-agent@8e4d32e5497defd43c023a404f73560c62728961 # v0.39.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# ── DEDICATED Bedrock IAM key (bedrock:InvokeModel only): NOT the
# app's AWS_* secrets. litellm reads AWS_REGION_NAME; AWS_REGION is
# set too for safety. Create these three repo/org secrets:
# PR_AGENT_AWS_ACCESS_KEY_ID, PR_AGENT_AWS_SECRET_ACCESS_KEY,
# PR_AGENT_AWS_REGION (an EU region, e.g. eu-west-1).
AWS_ACCESS_KEY_ID: ${{ secrets.PR_AGENT_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.PR_AGENT_AWS_SECRET_ACCESS_KEY }}
AWS_REGION_NAME: ${{ secrets.PR_AGENT_AWS_REGION }}
AWS_REGION: ${{ secrets.PR_AGENT_AWS_REGION }}
# ── Model: Claude Sonnet 5 via the EU Bedrock inference profile. The
# strong and weak slots both point at it: this account has no larger
# model enabled, so a second id would only be the same model under
# another name. No FALLBACK_MODELS for the same reason: a fallback
# list naming the primary is not a fallback. custom_model_max_tokens
# is required because this id is not in PR-Agent's built-in map.
CONFIG.MODEL: "bedrock/eu.anthropic.claude-sonnet-5"
CONFIG.MODEL_WEAK: "bedrock/eu.anthropic.claude-sonnet-5"
CONFIG.CUSTOM_MODEL_MAX_TOKENS: "200000"
# Input window PR-Agent prunes the diff to fit. Default (~32k) truncated
# large PRs; raise it so the whole diff is reviewed (Sonnet 5 = 1M ctx).
CONFIG.MAX_MODEL_TOKENS: "64000"
LITELLM.DROP_PARAMS: "true"
# ── pr_actions = which GitHub PR *event actions* trigger the bot
# (NOT a command list). Default omits 'synchronize', so pushes are
# skipped; we add it so every push is reviewed too.
GITHUB_ACTION_CONFIG.PR_ACTIONS: '["opened", "reopened", "ready_for_review", "review_requested", "synchronize"]'
# ── Which commands actually run on a handled event. Only review:
# describe/improve off so the bot never rewrites the PR body or
# pushes code suggestions.
GITHUB_ACTION_CONFIG.AUTO_REVIEW: "true"
GITHUB_ACTION_CONFIG.AUTO_DESCRIBE: "false"
GITHUB_ACTION_CONFIG.AUTO_IMPROVE: "false"