The Complete Guide to GitHub Actions AI Automation
How to add AI to every stage of your GitHub workflow. PR descriptions, code review, commit messages, and README generation via API.
GitHub Actions can call any HTTP API — which means you can add AI to every stage of your workflow. Here's how to automate the repetitive text work in your PR process.
What You Can Automate
- PR descriptions: Generate a structured description from the diff on every PR open/update
- Code review: Score and comment on code quality on every push
- Commit messages: Suggest conventional commits via a pre-commit hook
- README updates: Re-generate docs on every merge to main
All of these use the same pattern: call Runcept, poll for result, use the output.
Setup
Add a single repo secret:
Settings → Secrets and variables → Actions → New secret
Name: RUNCEPT_API_KEY
Value: your key from runcept.com/dashboard
Reusable Helper
This shell snippet handles the full async job cycle:
run_runcept_agent() {
local agent="$1"
local input="$2"
RESPONSE=$(curl -sS -X POST https://www.runcept.com/api/v1/run \
-H "Authorization: Bearer $RUNCEPT_API_KEY" \
-H "Content-Type: application/json" \
--data-raw "{\"agent\": \"$agent\", \"input\": $input}")
JOB_ID=$(echo $RESPONSE | jq -r '.job_id')
for i in {1..25}; do
sleep 4
RESULT=$(curl -sS "https://www.runcept.com/api/v1/jobs/$JOB_ID" \
-H "Authorization: Bearer $RUNCEPT_API_KEY")
STATUS=$(echo $RESULT | jq -r '.status')
if [ "$STATUS" = "complete" ]; then echo $RESULT; return 0; fi
if [ "$STATUS" = "failed" ]; then echo "Agent failed" >&2; return 1; fi
done
echo "Timeout" >&2 && return 1
}
PR Description Workflow
# .github/workflows/pr-description.yml
name: AI PR Description
on:
pull_request:
types: [opened, synchronize]
jobs:
describe:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate and post PR description
env:
RUNCEPT_API_KEY: ${{ secrets.RUNCEPT_API_KEY }}
GH_TOKEN: ${{ github.token }}
run: |
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD | head -c 8000)
INPUT=$(jq -n --arg diff "$DIFF" '{"diff": $diff}')
RESULT=$(curl -sS -X POST https://www.runcept.com/api/v1/run \
-H "Authorization: Bearer $RUNCEPT_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"agent\": \"pr-description\", \"input\": $INPUT}")
JOB_ID=$(echo $RESULT | jq -r '.job_id')
for i in {1..20}; do
sleep 4
JOB=$(curl -sS "https://www.runcept.com/api/v1/jobs/$JOB_ID" \
-H "Authorization: Bearer $RUNCEPT_API_KEY")
if [ "$(echo $JOB | jq -r '.status')" = "complete" ]; then
DESC=$(echo $JOB | jq -r '.output.description')
gh pr edit ${{ github.event.pull_request.number }} --body "$DESC"
break
fi
done
Code Review Workflow
# .github/workflows/code-review.yml
name: AI Code Review
on: [pull_request]
jobs:
review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Review and gate
env:
RUNCEPT_API_KEY: ${{ secrets.RUNCEPT_API_KEY }}
run: |
DIFF=$(git diff origin/${{ github.base_ref }}...HEAD | head -c 10000)
INPUT=$(jq -n --arg diff "$DIFF" '{"diff": $diff}')
RESULT=$(curl -sS -X POST https://www.runcept.com/api/v1/run \
-H "Authorization: Bearer $RUNCEPT_API_KEY" \
-H "Content-Type: application/json" \
-d "{\"agent\": \"code-reviewer\", \"input\": $INPUT}")
JOB_ID=$(echo $RESULT | jq -r '.job_id')
for i in {1..20}; do
sleep 4
JOB=$(curl -sS "https://www.runcept.com/api/v1/jobs/$JOB_ID" \
-H "Authorization: Bearer $RUNCEPT_API_KEY")
if [ "$(echo $JOB | jq -r '.status')" = "complete" ]; then
SCORE=$(echo $JOB | jq -r '.output.score')
echo "Code quality score: $SCORE"
[ "$SCORE" -ge 65 ] || (echo "Score below threshold" && exit 1)
break
fi
done
Running Both in Parallel
jobs:
describe:
# PR description job
review:
# Code review job
# Both start simultaneously — no 'needs' dependency