In this categoryDify ยท 9
How to Set Up an AI Code Review Workflow in Dify
Build a Dify workflow that takes a diff or code snippet and returns a structured review covering bugs, security, and style, then call it from CI or a git hook.
A code review workflow takes a diff or a code snippet, runs it through an LLM with a strict review prompt, and returns a structured report you can post on a pull request. In Dify you build this as a Workflow app: an input variable feeds an LLM node, and the published workflow exposes an API endpoint you can call from CI or a local git hook. This guide wires the whole thing end to end.
What you need
- Dify running on Dify Cloud or self-hosted
- A model provider connected (Claude or GPT-class models review code best)
- A diff or code snippet to test with
- About 18 minutes
Step 1: Create a Workflow app
In Studio, click Create from Blank and pick Workflow. A workflow runs once per call and returns a single result, which is exactly what a code review needs. On the canvas you start with a Start node and an End node; you add the review logic between them. Open the Start node and add an input variable named code of type Paragraph. This is where the diff or snippet gets passed in at run time.
Step 2: Add an LLM node and write the review prompt
Add an LLM node between Start and End, then select your model. In the prompt editor, reference the input with the {{#start.code#}} variable so the submitted code lands inside your instructions. Keep the prompt narrow: tell the model it is a senior reviewer, list the exact categories to check, and demand a fixed output shape so downstream tools can parse it.
Step 3: Define the review categories
Listing categories in the prompt keeps every review comparable across runs. Start with three and expand once the output looks reliable.
| Category | What the model checks | Example finding |
|---|---|---|
| Bugs | Logic errors, off-by-one, null and error handling | Unhandled null from getUser() on line 42 |
| Security | Injection, secrets, unsafe input, weak auth | Raw user input concatenated into SQL on line 17 |
| Style | Naming, dead code, complexity, consistency | Function exceeds 80 lines, consider splitting |
Step 4: Wire the End node
Open the End node and add an output variable named review mapped to the LLM node's text output. Click Test Run, paste a sample diff into the code field, and confirm the three headings come back populated. Adjust the prompt until the format is stable, then click Publish and Publish Update to make the workflow live.
Step 5: Call it from CI or a git hook
Open Access API in the app to copy your API key and base URL. The published workflow runs over a single POST request, passing your input variable inside the inputs object. Drop this into a CI job or a pre-push hook so every diff gets reviewed automatically.
Step 6: Run it on every pull request with GitHub Actions
To review code automatically, add a workflow that triggers on pull_request. It checks out the branch with full history, builds the diff against the base branch, sends it to your published workflow, and prints the review in the job log. Using jq to build the JSON body means a diff with quotes or newlines is encoded safely instead of breaking the request.
name: AI Code Review
on:
pull_request:
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Review the diff with Dify
env:
DIFY_API_KEY: ${{ secrets.DIFY_API_KEY }}
run: |
DIFF=$(git diff "origin/${{ github.base_ref }}...HEAD")
BODY=$(jq -n --arg code "$DIFF" \
'{inputs: {code: $code}, response_mode: "blocking", user: "gh-actions"}')
curl -s -X POST https://api.dify.ai/v1/workflows/run \
-H "Authorization: Bearer $DIFY_API_KEY" \
-H "Content-Type: application/json" \
-d "$BODY" | jq -r '.data.outputs.review'Alternative: run it locally with a pre-push hook
If you would rather catch issues before code ever leaves your machine, drop the same call into a git pre-push hook. Save this as .git/hooks/pre-push and make it executable with chmod +x. It reviews the outgoing commits and prints the result, and you can make it block the push by exiting non-zero when the review flags something.
#!/usr/bin/env bash
# Review outgoing commits before they leave your machine.
DIFF=$(git diff origin/main...HEAD)
[ -z "$DIFF" ] && exit 0
BODY=$(jq -n --arg code "$DIFF" \
'{inputs: {code: $code}, response_mode: "blocking", user: "pre-push"}')
REVIEW=$(curl -s -X POST https://api.dify.ai/v1/workflows/run \
-H "Authorization: Bearer $DIFY_API_KEY" \
-H "Content-Type: application/json" \
-d "$BODY" | jq -r '.data.outputs.review')
echo "$REVIEW"
# To block the push on findings, inspect $REVIEW and exit 1 when it is not clean.FAQ
How do I run this on every PR automatically?
Add the GitHub Actions workflow above with the pull_request trigger. GitHub runs it on every new PR and every push to an open PR, so each diff gets reviewed with no manual step. The review lands in the Actions job log; to surface it inline, extend the job to post the text as a PR comment using the GitHub CLI or the pull-request review API.
Does it work with self-hosted Dify?
Yes. The API is identical on a self-hosted instance; only the base URL changes. Swap https://api.dify.ai/v1 for your own host, for example https://dify.example.com/v1, and use the API key from that instance's app. Everything else in the workflow and the hook stays the same.
Which model is best for code review?
Pick a frontier general-purpose model with strong reasoning, since code review rewards understanding intent rather than pattern matching. Set a low temperature so the output stays consistent between runs, and give the model enough context window to hold the whole diff. If a review feels shallow, tighten the prompt before reaching for a bigger model.
How do I parse the output in CI?
A workflow run returns JSON shaped as data.outputs.<your output variable>, so a review mapped to a variable named review is at .data.outputs.review. The examples above pull it with jq -r '.data.outputs.review'. If you need structured findings rather than prose, instruct the LLM node to return JSON and read individual fields with jq, then decide in the script whether to fail the job.
Related guides
Dify Tutorial: Build Your First AI App (Complete Walkthrough)
A beginner walkthrough of Dify: what it is, cloud versus self-host, creating an app, picking an app type, adding a model, writing a prompt with variables, and publishing to get an API or embed.
How to Build an AI Agent in Dify
Create a Dify agent that can call tools, search the web, and run multi-step tasks without writing orchestration code.
Watch related tutorials
19:27
1:42:18
28:14
41:09
9:47
8:23New guides in your inbox
Fresh step-by-step how-to guides as we publish them. One email a week, no more.