All Articles

Risk scoring on pull requests shows you where to look. Agents can do something about it.

Risk scoring on code review focuses human attention. Agents can reduce how much attention is needed — three loops we built on top of Unblocked's Code Review risk labels.

Risk scoring on pull requests shows you where to look. Agents can do something about it.

TL;DR: Risk scoring on pull requests focuses human attention where it matters and let’s agents automatically resolve & reduce risk & find policy gaps.

We built three loops on top of our own risk labels: agents act on the score to drive risk down automatically, optionally review it with a human in loop, and feed what the agent finds back into improving the risk policy in your repo. The first and third run headless.

Background: Unblocked gives agents the organizational understanding of your best engineers. Its context engine connects and reconciles knowledge across your code, conversations, issues, documentation, and production systems, then makes that understanding available wherever work happens. Agents access context through MCP/CLI/APIs, and Unblocked products like Code Review and Unblocked Code apply that context directly to reviewing and writing code. The result is better software, produced with fewer tokens, fewer iterations, and less babysitting.

Risk scoring on code review focuses human attention where it's most needed. Not every PR deserves the same scrutiny, and a score tells your reviewers which ones do.

But a score is not a resolution. That's the part agents can help with. Once a PR carries a machine-readable risk label, an agent can read the change, work out what the risk actually consists of, fix what's safely fixable by driving down risk, and hand a reviewer a smaller problem than the one it started with.

This way you and your agents can reduce risk thanks to understanding risk.

That shape of value is already what teams tell us they get from AI code review:

"Unblocked catches things I probably would've missed and honestly speeds up the whole review cycle. It flags issues early, so by the time my peers look at the PR it's already cleaner, and we all avoid a bunch of unnecessary back-and-forth."

Leah LangfordSenior Software Engineer, Optro

A risk label makes it programmable. It gives an agent a place to start and a threshold to work against.

So we built a proactive agent on top of our risk assessment to see how far it goes. It's three loops, and the third one was emergent from our agent during testing.

Risk assessment ships as part of Unblocked Code Review. You turn it on by adding a .unblocked/risk-policies.yaml to your repository. The docs walk through it. Every PR then gets labeled from risk: lowest through risk: highest, plus a comment explaining the reasoning.

Here’s our cookbook repo that has the risk-triage skill, script, and PR on how it works if you want to just point at an agent and get setup.

Loop 1: act on the score#

A list of PRs with medium or higher risk labels assigned by Unblocked Code Review's risk assessment.
List of PRs with medium or higher risk

Running: gh pr list --search 'label:"risk: medium","risk: high","risk: highest"' returns the live list of labelled PRs using GitHub CLI.

The label is a normal GitHub label, so finding work is one command:

bashgh pr list --state open \
  --search 'label:"risk: medium","risk: high","risk: highest" -is:draft'

From there the loop is:

  1. Find labelled PRs opened in the last 24 hours
  2. Check each out in a scratch worktree, outside the repo
  3. Give an agent the diff and the assessment's reasoning
  4. Agent applies the fixes it's confident in, writes notes on the ones it isn't
  5. Human reviews the diff
  6. Only then does anything go back to GitHub

Step 6 is by design, not a limitation, you can skip the human and fully send with the agent if you prefer.

We setup the skill so triage never writes to GitHub. A separate command does, and it asks first. On a real PR the agent added the two missing tests that would catch a silent failure, and left notes on the two changes it judged were the author's call rather than its own. The quality of that judgement is downstream of context — the agent needs to know which code paths are actually reachable in production, which is what the context engine is for.

Loop 2: review it with a human (optional)#

A diff in one file and notes in another means the reviewer has to correlate by hand. That sucks — you've moved the work, not reduced it.

So we wired the output into Hunk, an open-source terminal diff reviewer that renders agent notes inline, directly above the hunk each one annotates. Two things make it the right surface for this:

  1. Both voices are on the code. Every note carries an author. You see the Unblocked risk assessment note explaining what the policy flagged, and the triage agent note explaining what it did about it, stacked on the same hunk.
  2. You can write back. Add your own note on a hunk, "this needs a flag, not a test", and the next agent run reads it and responds. Hunk exposes human-authored notes to agents, so the review becomes a conversation anchored to specific lines.
A look at a local terminal with Hunk Diff viewer showing Risk label notes and Agent assessment notes.
Hunk Diff viewer locally with Risk label notes and Agent assessment notes
A screenshot of a human being able to add a note to the hunk to steer the agent on what to do next
Be a human in the loop and tell the agent what to do next

The recipe that does this, the skill, the triage script, and the Hunk wiring, is in our cookbook, meant to be forked and adjusted for your repo and needs.

Loop 3: the agent's reading improves your risk policy#

With Unblocked, your risk policies are a file in your repository, not a black box scoring you against someone else's idea of danger. An example policy might be:

yamlpolicies:
  - policy: Database migrations (destructive/alter)
    risk: highest
    criteria: >
      The PR modifies or deletes existing Flyway migration files, or
      adds migrations that DROP, ALTER, or RENAME tables/columns.

Every matching policy sets a minimum score. If Code Review catches 4 low-risk issues and 1 highest-risk the assessment will be highest-risk. Lower matches never pull it down. You can also look at a label and know which policy produced it.

A screenshot of GitHub UI showing Unblocked Code Review write a real risk assessment on a recent PR at Unblocked
A real risk assessment on a recent PR at Unblocked

While building this skill we found on one PR labelled risk: highest, two policies matched: Critical service – Search at high, and the migration policy above at highest.

Then the agent read the migration:

ALTER TABLE ... ADD IF NOT EXISTS inference uuid NULL;

Nullable, no default, no table rewrite, rollback-safe. Additive in every way that matters operationally — but our criteria say "DROP, ALTER, or RENAME," and the statement starts with ALTER TABLE.

That's not the assessment being wrong. It did what the policy said. It's our criteria not distinguishing ALTER TABLE … ADD COLUMN from ALTER TABLE … DROP COLUMN. One is additive, one isn't, and we wrote a rule that couldn't tell them apart.

Here's the change the agent proposed:

yaml    criteria: >
      The PR modifies or deletes existing Flyway migration files, or adds
      migrations that DROP or RENAME tables/columns, ALTER a column type,
      or add a NOT NULL column without a default.

This is the loop we didn't plan for and now we baked this value into the skill and our internal proactive agent. The agent doesn't just flag the divergence — it names the policy, quotes the criteria that matched, and writes the replacement wording. What you get is a proposed edit to risk-policies.yaml as a PR, reviewable like any other change. It stops at proposing; editing the policy stays a human's call. Run this across enough labelled PRs and your labels get more precise, which means human attention gets allocated better. The point of scoring in the first place.

By the way; Unblocked has a risk-policy-generation skill that drafts and improves the file for you by researching your repo's incidents, critical paths, and prior rollbacks first. Just ask Unblocked to init yours in slack, dashboard, or mac app with: write me a risk-policy for [namespace/repo].

Where this goes headless#

We wrote this with a human at the terminal. Loops 1 and 3 don't need one.

The label is a score with a defined floor from a policy you control. That makes it a legible objective for a cloud agent: pick up PRs above a threshold, apply the safe fixes to reduce risk, open a follow-up PR against the contributor's branch, and let the next assessment run judge whether the score came down. The policy file is the validator, and it's version-controlled, so the rules the agent optimizes against are the same ones your team reviews in a PR.

That's a component you can drop into a software factory — an autonomous stage that lowers risk before a human is ever asked to review, with the calibration loop still feeding your policy. Human-in-the-loop is the right default while you're learning how often the agent is right. Once you trust the agent and the validator, open the gates, let those agents merge.

The measurable outcome is reducing human review cycles:

"When I plugged Unblocked into our context-gathering and PR review steps, it brought in the Slack conversations where real architectural decisions get made. We went from three rounds of PR review to one before the code was production-ready."

Pablo VallejoEngineering Manager, Clio

If your own productivity metrics are flat, that's usually a measurement problem before it's a tooling problem.

The takeaway#

Scoring risk focuses human attention. It doesn't reduce how much attention is needed. Agents are here to close the gap, and the same agent runs make your policies better over time.