Inline Feedback
The inline feedback feature lets developers interact with the bot directly from inline PR comment threads using @botai commands.
Commands
@botai resolved and @botai dismiss only work inside an inline thread (a PR review comment reply), since they act on one specific finding. @botai explain and @botai ask also require inline context but don't require the parent to be a bot finding. @botai approved, @botai review, @botai ask, and @botai learn also work from a general PR comment.
| Reply | Where | What happens |
|---|---|---|
@botai approved | Inline thread or general comment | The bot acknowledges, dismisses its own prior CHANGES_REQUESTED reviews, submits a GitHub APPROVE, and suppresses open findings so they are not re-flagged on later pushes. Escape hatch after false-positive blocks. If APPROVE fails (permissions), it replies with an error. Note: a failed Actions check from exit code 1 on an earlier REQUEST_CHANGES is separate — re-run that job or do not treat it as a required check if you rely on this override. |
@botai review """your explanation""" | Inline thread | The bot reads your explanation, fetches the current file state, and asks the LLM whether that one finding is resolved. It always posts a reply with its decision |
@botai review | General comment | Re-runs the full PR review, feeding in your explanation (quoted with """...""" in the same comment, or written in earlier general comments since the bot's last review) so the model can recognize when a previously flagged concern is already addressed instead of repeating it |
@botai resolved | Inline thread | The bot immediately marks the finding as resolved and closes the thread. If all open bot findings are now resolved, it auto-approves the PR |
@botai ask """question""" | Inline thread or general comment | Answers a free-form question — inline it uses the surrounding code, general comment it uses the PR summary. Never triggers a re-review |
@botai learn """rule""" | Inline thread or general comment | Saves the rule to a repo-level Learnings file, applied to every future review of the PR's base branch — requires learnings.enabled: true |
Setup
1. Enable in config
Add to .ai-review.yml:
feedback:
enabled: true2. Add the workflow job
The handle-feedback command must run on the pull_request_review_comment event (inline replies) and the issue_comment event (general PR comments, needed for @botai approved/@botai review outside a thread). Add it alongside your existing ai-review job:
name: AI Code Review
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
pull_request_review_comment:
types: [created]
issue_comment:
types: [created]
jobs:
ai-review:
if: github.event_name == 'pull_request' && github.event.pull_request.draft == false
runs-on: ubuntu-latest
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- run: git fetch origin ${{ github.base_ref }}
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npx -y @giolabsuy/ai-code-reviewer@latest review-pr
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
handle-feedback:
if: github.event_name == 'pull_request_review_comment' || github.event_name == 'issue_comment'
runs-on: ubuntu-latest
permissions:
pull-requests: write
# `contents: write` is only required if `learnings.enabled: true` — @botai learn
# and the auto-capture on @botai dismiss commit .ai-review-learnings.md directly
# to the PR's base branch. Use `contents: read` if you don't enable Learnings.
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "20"
- run: npx -y @giolabsuy/ai-code-reviewer@latest handle-feedback
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EVENT_PATH: ${{ github.event_path }}
GITHUB_REPOSITORY: ${{ github.repository }}
GITHUB_ACTOR: ${{ github.actor }}The GITHUB_ACTOR variable is set automatically by GitHub Actions. It identifies who triggered the workflow, which the handler uses to skip its own bot replies.
How it works
When a developer replies to a bot inline comment:
- The
pull_request_review_commentevent fires. - The
handle-feedbackworkflow job starts. - The CLI reads the event payload from
GITHUB_EVENT_PATH. - It checks that the commenter is not the bot itself.
- It looks for
@botai <command>in the reply body. - The matching handler runs (see command details below).
If the reply does not contain @botai, the event is ignored silently.
@botai approved
Use this command to approve the PR from any inline thread reply — regardless of which finding the thread belongs to.
Bot: 🟡 major — Missing input validation on /upload endpoint
Developer (reply): @botai approved
Bot: @lucasgio approved this PR. Proceeding to approve.
[GitHub shows: ✅ lucasgio via @botai approved this pull request]@botai review
Use this command when you've addressed a finding and want the bot to verify. Put your explanation between """ delimiters — the bot will read it along with the current state of the file to decide if the finding is resolved.
Bot: 🔴 critical — Missing authentication guard
This endpoint has no @UseGuards() decorator. Any unauthenticated
user can call it.
Developer (reply): @botai review """Added @UseGuards(JwtAuthGuard) to
the controller method in the latest commit (abc1234)."""
Bot: The guard is now present on the method. The finding is resolved. ✅If the bot determines the fix is insufficient, it replies with maintained and explains what's still missing.
@botai review from a general comment
Use this when you want the bot to reconsider the review as a whole — not one specific finding — after you've explained yourself in the PR conversation. This re-runs a full review, not just a single-finding check.
Developer (general comment): ## Response to AI review
Thanks — both findings addressed in `513e60f`, with one clarification.
### 🟠 MAJOR — "adapter-registration factory may not run at runtime"
The alarming conclusion is a false positive. NestJS eagerly instantiates
all default-scope providers during application bootstrap, regardless of
whether their token is injected elsewhere. See the new
`channels.module.spec.ts` integration test that proves it.
Developer (general comment): @botai review
Bot: Re-revisando el PR teniendo en cuenta tu feedback...
[a new full review runs and posts an updated summary + review event]You don't need to repeat your explanation inside """...""" — the bot collects every general comment posted since its last review summary (skipping its own comments) and feeds that conversation to the model as context, so a bare @botai review after an explanation comment works exactly like the example above. If you prefer to be explicit, @botai review """your explanation""" also works from a general comment and that quoted text is included too.
The re-review runs the same pipeline as a normal push-triggered review (stack detection, per-group LLM calls, merged result) and updates the existing summary comment and review event in place — it does not create a duplicate.
@botai resolved
Use this command to unconditionally close a finding without LLM evaluation — useful when the finding is a false positive or was addressed in a way that's hard to explain in text.
Bot: 🟡 major — Potential race condition in upload handler
Developer (reply): @botai resolved
Bot: Finding resolved by @lucasgio.If this was the last open bot finding on the PR, the bot also submits an APPROVE review automatically.
@botai ask
Ask anything about the PR without anchoring to one specific finding, and without triggering a re-review. Works two ways:
# Inline — uses the code around the comment
Bot: 🟠 major — Registry not populated at bootstrap
Developer (reply): @botai ask """why does this only affect mercado_libre and not tiendanube?"""
Bot: Because only mercado_libre is registered in the CHANNEL_PROVIDERS_FACTORY
in channels.module.ts — tiendanube has no adapter wired yet, so it's...
# General comment — uses the PR's AI Code Review summary
Developer (general comment): @botai ask """what does this PR change in the public API?"""
Bot: This PR doesn't change any existing endpoint contracts. It adds capability
resolution to GET /channels/available — status and capabilities[] are now...@botai learn
Requires learnings.enabled: true in .ai-review.yml (opt-in — see Configuration). Saves a rule to .ai-review-learnings.md, committed directly to the PR's base branch, and every future review of that branch includes it in the system prompt — not just this PR.
Developer (general comment): @botai learn """No reportar console.log en scripts/migrations/**, es intencional para logging de migración."""
Bot: Aprendizaje guardado en `.ai-review-learnings.md` (rama `develop`). Se va
a tener en cuenta en las próximas reviews de este repo.@botai dismiss on an inline finding also auto-captures an entry (the finding's title plus your dismiss reason, if you gave one) — you don't need to also run @botai learn for a one-off false positive you've already dismissed. Use @botai learn for rules you want applied before they'd otherwise be flagged.
The file is plain markdown — open it and delete a line directly to retract a learning; there's no @botai forget command.
Auto-resolve on push
When new commits are pushed to the PR branch, the reviewer checks if any previously flagged lines have changed. If a finding's line was modified, the comment thread is resolved automatically.
Auto-approve when all findings are resolved
Whenever @botai resolved (or @botai review with a resolved outcome) closes the last open bot finding on the PR, the bot submits a GitHub APPROVE review. This means developers don't need to run @botai approved separately once every finding is closed.