Every pull request gets a first pass before a human ever opens the diff. Normally that first pass is a human — someone context-switches out of their own work, reads eight commits cold, and writes up what they find. We wanted that first pass to happen automatically, the moment a ticket is ready for one, so the human reviewer opens the diff already knowing what to look for.

On our own project, the “ready for review” moment is a specific workflow transition: when a ticket moves to Needs Merge, that’s how we request a pull request. So that’s exactly where we attached the callout — the moment a ticket crosses into Needs Merge, Flow AI reads every commit associated with the ticket and posts a structured review as a follow-up, before anyone asks for one.

Here’s the exact setup, prompt included, and a real example of what it caught.

Step 1: Turn on Flow AI

Project Admin AI Flow settings — enable toggle, LLM provider, model, and API key fields, each showing an inherited-from indicator

Off by default. An administrator has to turn it on, per project, and choose the provider and API key.

Nothing runs until you enable it

Flow AI is opt-in, per project — an admin enables it under Project Admin, and picks the LLM provider, model, and API key it should use. Until that happens, nothing about this walkthrough does anything.

Step 2: Attach a prompt to the transition

Tracker workflow transition AI tab with an LLM Callout Prompt configured on the Accepted to Needs Merge transition, Post Follow-up on Success set to Yes

The AI tab lives right alongside a transition’s Main, Action, Message, and Scripts tabs.

Any transition, any prompt

Open a tracker’s workflow settings, open the transition you care about, and there’s an AI tab next to the usual Main/Action/Message/Scripts tabs. Paste in a prompt, set “Post Follow-up on Success” to Yes, and save. From then on, every time a ticket crosses that transition, the prompt runs — no one has to remember to ask.

Ours is attached to Accepted → Needs Merge, the transition we use to request a pull request.

The exact prompt we run

This is copy-pasted from our own project’s AI tab, unedited. It’s long on purpose — a callout only gets one shot per transition, so it has to specify how to gather the commits, what to check, and exactly how to format the output, rather than leaving any of that to be reinterpreted each time it runs.

LLM Callout Prompt — Accepted → Needs Merge
Review the commits associated with tracker item {{data.tracker_item_id}} for
merge readiness.

INPUT SCOPE
The commits associated with this tracker item are the complete review set.
Branch names are irrelevant to this task: do not look one up, infer one, or
report that you need one. Every input comes from the tracker/SCM tools
available to you — there is no shell, no filesystem, and no way to save,
grep, or page through a result outside those tool calls.

STEP 1 - GATHER
1. Read the tracker item: summary, description, fields. This is the
   statement of intended scope and your baseline for judging whether each
   commit belongs.
2. Retrieve the commits associated with the item. Order them oldest first —
   that is the order they land, and every later check depends on it.
3. Retrieve each commit's diff individually: diff each commit against its
   immediate predecessor in this set (predecessor's hash as one side, the
   commit's own hash as the other). For the oldest commit, diff it against
   one of the branches named in the item's merge-status tool output. Prefer
   these small, single-commit diffs over one diff spanning the whole set —
   a full-range diff is far more likely to exceed what a single tool call
   can return, and there is no way to recover from that here by re-reading
   it in pieces.
4. If a commit's diff still cannot be retrieved (the call errors or is
   truncated), do not retry with a wider range. Judge that commit from its
   message and file list alone, and say so in Limitations.
5. Review every commit returned, not a sample. If the item has no
   associated commits, your entire response is one sentence stating that.

STEP 2 - CHECKS
Judge every commit against its actual diff, not its message, wherever a
diff was available. A message that disagrees with its diff is itself a
finding.

1. SCOPE
   a. Does the commit belong to this tracker item at all, given the item's
      stated intent? Flag unrelated work, however small.
   b. Does it stick to one concern (one layer, one subsystem, one fix)? Flag
      commits mixing unrelated things (app code + build/CI + docs + an
      unrelated bug fix) unless inherently coupled.

2. DEPLOY SAFETY
   Walk the set cumulatively, oldest to newest. For each commit ask: if the
   system were deployed at exactly this commit, with every earlier commit in
   the set applied and no later one, would it work correctly? Flag forward
   dependencies on code that lands later, a CI gate or config flag flipped
   before the commits that make it safe to enable, and schema or migration
   steps ordered against the code that reads them.

3. BURIED FIXES
   Flag any commit framed as mechanical or cosmetic (rename, refactor,
   type-only, lint-only, formatting) whose diff contains a real behavior or
   bug fix. These carry production risk hidden inside a diff reviewers will
   skim as a no-op.

4. HYGIENE
   Message carries the tracker tag matching this item and is a single clear
   sentence, per this repo's commit convention. Separately, flag any merge
   commit in the set: the work should be rebased clean before review.

OUTPUT
Your entire response is the review below, formatted exactly as shown and
nothing else — no preamble, no restatement of the task, no account of which
tools you called, no closing offer of further help. This text is the
deliverable itself; whatever posts it, stores it, or attaches it to the
tracker item is done by the system that invoked you, not by you — do not
call any tool to post, comment, or write it anywhere yourself.

## Commit review
Reviewed N commits associated with this item.

### Per-commit findings
<short-sha> PASS
<short-sha> SCOPE: adds retry logic unrelated to this item's stated fix
<short-sha> DEPLOY: enables the strict-mode flag before the validation code lands
<short-sha> BURIED FIX: "rename handler params" also changes null handling
<short-sha> HYGIENE: missing tracker tag; message describes two changes

### Merge commits
<list, or "none">

### Recommendation
<one of: MERGE AS-IS | REORDER | SPLIT | SQUASH — or, when the findings are
minor, MERGE AS-IS with the imperfections noted>
<2 to 4 sentences. State what you found and why it does or doesn't rise to
the level of asking someone to rewrite history: rebasing, rewording, and
fixup-ing commits is real work with real risk (force-push, disrupted
checkouts, lost CI history), so weigh that cost against the actual
reviewability/bisectability/rollback harm before recommending it. Reserve
REORDER/SPLIT/SQUASH for cases where the messiness genuinely impairs one of
those, name the specific commits and the seam, and frame it as what you'd
suggest and why — not as an order. Otherwise recommend MERGE AS-IS and
note the imperfections as just that.>

### Limitations
<Include this section only if a check could not be completed — including any
commit whose diff could not be retrieved per STEP 1.4. Name what data was
unavailable and which checks it blocked. Omit the heading entirely
otherwise.>

What it looks like when it runs

A real tracker item follow-up comment titled Commit review, showing 11 commits reviewed, per-commit PASS and SCOPE findings, and a REORDER recommendation

Posted automatically the moment the ticket crossed into Needs Merge.

One real example

The follow-up above posts under the name of whoever performed the transition — in this case, the teammate who moved the ticket to Needs Merge, not a bot or service account. That’s not a quirk of this example; the callout always runs and posts as the person who triggered it.

On this ticket it reviewed 11 commits. Eight passed cleanly. Two were flagged under SCOPE: one commit added a directory to .gitignore that the ticket never asked for, and the very next commit reverted it five minutes later — a revert pair that nets out to zero but clutters the history. The recommendation was REORDER: squash those two out with git rebase -i, leave the other nine as-is. That’s the DEPLOY SAFETY, BURIED FIXES, and HYGIENE checks from the prompt above, run against a real diff, producing a real, specific, actionable note — not a generic “looks good to me.”

Where to go from here

Everything above is already live — no waitlist, nothing “coming soon.” Read more about Flow AI, or if you’ve got an idea for a callout worth trying on your own workflow, tell us what you’d build — we might feature it in a future post.