Recipes
Review every pull request
Review every pull request by starting a run on github.pull_request.opened,
asking Scout for a structured review, pausing for a human verdict, and posting
a GitHub review comment.
This is the internal business operations use case Mobius should make easy to recognize. The agent does the first pass, the reviewer stays accountable, and the review lands back where the engineering team already works.
Use this when you want AI review without letting the agent speak for the team automatically. Scout drafts the review, Mobius asks a person, and only the approved path posts to GitHub.
What you'll build
- An
eventtrigger for pull requests inacme/api. - A run name with the repository and pull request number.
- An agent review step.
- One focused agent history per pull request.
- A
request_reviewinteraction step. - A conditional child-loop step that posts the review only after approval.
Prerequisites
- A connected GitHub integration for
acme/api. - An agent named Scout (
agt_scout). - At least one Mobius user who can receive the review interaction.
Build it
- In the app, open Build > Loops.
- Create a loop named
Review every pull request. - Add an Event trigger for
github.pull_request.opened. - Set Run name template to
PR review · ${{ event.repository.full_name }} #${{ event.pull_request.number }}. - Add an agent step named
Review diff. - Ask Scout to return
verdict,risk, andbody. - Set the loop's History control to Pull request so another run for the same pull request can reuse earlier findings.
- Add an interaction step named
Human review. - Use
request_reviewwithany_ofresolution. - Add a child-loop step named
Post review. - Point it at a small
post-github-reviewloop whose only step callsgithub.pull_request.create_review. - Set the child-loop
if:tosteps.human-review.output == "post_comment". - Create the loop as active.
You will end with two loops: the pull request review loop, and a small
post-github-review child loop that owns the GitHub review action. The parent
only starts the child when the interaction output is post_comment.
Finished spec
schema_version: "1"
name: review-every-pull-request
description: Review new pull requests and post a GitHub review comment.
concurrency: allow
run_name:
template: "PR review · ${{ event.repository.full_name }} #${{ event.pull_request.number }}"
defaults:
agent_session:
scope: loop
name: "github:${{ event.repository.full_name }}:pull:${{ event.pull_request.number }}"
title: "${{ event.repository.full_name }} PR #${{ event.pull_request.number }}"
visibility: project
triggers:
- key: pr-opened
name: Pull request opened
kind: event
enabled: true
config:
event_type: github.pull_request.opened
source_id: github
condition: event.repository.full_name == "acme/api"
steps:
- id: scout-review
name: Review diff
kind: agent
config:
agent_id: agt_scout
instructions: |
Review the pull request. Return JSON with verdict, risk, and body.
Keep body suitable for a GitHub pull request review.
- id: human-review
name: Human review
kind: interaction
config:
protocol: request_review
targets:
- usr_platform_lead
prompt: |
Review Scout's pull request notes and choose whether to post them.
resolution_policy: any_of
spec:
mode: select
options:
- value: post_comment
label: Post comment
- value: skip
label: Skip
timeout:
duration: 4h
on_timeout: fail
- id: post-review-if-approved
name: Post review if approved
kind: loop
if: "steps.human-review.output == \"post_comment\""
config:
loop_id: loop_3f8k2m9x4v7n5r6t
inputs:
repo_full_name: "${{ event.repository.full_name }}"
pr_number: "${{ event.pull_request.number }}"
review_event: COMMENT
review_body: "${{ steps.scout-review.output.body }}"The child loop is intentionally small:
schema_version: "1"
name: post-github-review
description: Post an approved GitHub pull request review.
concurrency: allow
inputs:
repo_full_name:
type: string
required: true
pr_number:
type: integer
required: true
review_event:
type: string
required: true
review_body:
type: string
required: true
triggers:
- key: manual
kind: manual
enabled: true
steps:
- id: post-review
name: Post review
kind: action
config:
action_name: github.pull_request.create_review
parameters:
repo_full_name: "${{ inputs.repo_full_name }}"
pr_number: "${{ inputs.pr_number }}"
event: "${{ inputs.review_event }}"
body: "${{ inputs.review_body }}"Today the conditional field lives on loop steps as a step-level if:, so
the posting path is a child loop instead of a direct action step.
For a lighter experiment, stop before the child loop. Let Scout write review notes and ask a human whether the notes are useful. Add the posting path once the review quality is predictable.
Run it
Open a test pull request in acme/api. The run should suspend at the
interaction until a target responds:
run.started
step.started step=scout-review kind=agent
step.completed step=scout-review
step.started step=human-review kind=interaction
interaction.requested step=human-review
wait.opened kind=interaction
step.suspended step=human-review
run.suspendedAfter the response, the run resumes and posts the review:
interaction.responded
wait.resumed
step.completed step=human-review
step.started step=post-review-if-approved kind=loop
step.completed step=post-review-if-approved
run.completedIf the human chooses skip, post-review-if-approved is marked skipped and
the posting child loop never starts.
Variations
- Replace the final review action with
github.issue.create_commentif you want a normal PR comment instead of a review. - Switch History to Fresh run when every review should ignore findings from earlier runs on the same pull request.
- Use
queueif a shared review environment should not run two PR reviews at the same time. - Add
github.pull_request.list_filesas an action step before Scout if the trigger payload does not include enough diff context.
Next
- Read interaction behavior in interactions.
- Check event names in the event catalog.
- Inspect suspended runs in runs.