Writing a good pull request description is tedious. You've just finished coding, and the last thing you want to do is summarize yet another diff. The result: too many PRs have missing or vague descriptions, making review slower. In this tutorial, you'll build an AI agent that runs inside GitHub Actions, reads the diff, and posts a well-structured description directly to your PR. By the end, every new PR will get instant, explainable context โ automatically.
How it works
When a PR is opened, GitHub Actions triggers a workflow. That workflow checks out the code, computes the diff between the base and head branches, sends it to an LLM (via the OpenAI API), and posts the generated description as a PR comment. You can easily adapt the same pattern to update the PR body, add labels, or request reviewers.
Step 1: Create the AI agent script
First, create a directory for your workflow scripts and add a Python file. This script will be the core of your agent.
# .github/scripts/generate_pr_description.py
import os
import subprocess
import requests
from openai import OpenAI
def get_env(name):
value = os.environ.get(name)
if not value:
raise RuntimeError(f"Missing required environment variable: {name}")
return value
# Read environment variables
api_key = get_env("OPENAI_API_KEY")
github_token = get_env("GITHUB_TOKEN")
pr_number = get_env("PR_NUMBER")
base_sha = get_env("BASE_SHA")
head_sha = get_env("HEAD_SHA")
repo = get_env("GITHUB_REPOSITORY")
# Get the diff between base and head
diff = subprocess.check_output(
["git", "diff", base_sha, head_sha], text=True
)
# Truncate very large diffs to stay within token limits
diff = diff[:8000]
# Create an OpenAI client
client = OpenAI(api_key=api_key)
prompt = f"""Write a pull request description for the following code diff.
Include sections: Summary, Changes, Testing Notes.
Use bullet points and be concise.
Diff:
{diff}
"""
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=[
{"role": "system", "content": "You are an expert code reviewer. Generate a PR description that helps a human reviewer understand the change quickly and accurately."},
{"role": "user", "content": prompt}
],
max_tokens=500,
temperature=0.3
)
pr_description = response.choices[0].message.content
# Post the generated description as a PR comment
comment_body = f"### ๐ค AI Generated PR Description\n\n{pr_description}"
api_url = f"https://api.github.com/repos/{repo}/issues/{pr_number}/comments"
headers = {
"Authorization": f"token {github_token}",
"Accept": "application/vnd.github.v3+json"
}
resp = requests.post(api_url, headers=headers, json={"body": comment_body})
resp.raise_for_status()
print("PR description posted successfully.")
gpt-4o-mini for cost efficiency. You can swap in any model that works with the OpenAI SDK, or use a local model via Ollama with a few adjustments.Step 2: Set up the GitHub Actions workflow
Now create a workflow file that runs this script whenever a PR is opened.
# .github/workflows/pr-description.yml
name: Generate PR Description
on:
pull_request:
types: [opened]
jobs:
generate:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: '3.12'
- name: Install dependencies
run: pip install openai requests
- name: Run AI PR description generator
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: python .github/scripts/generate_pr_description.py
OPENAI_API_KEY in your repository secrets (Settings > Secrets and variables). The GITHUB_TOKEN is provided automatically, but make sure it has read/write permissions for comments โ usually the default is fine.Step 3: Test it on a real PR
Commit these two files, push to a branch, and open a PR. Within seconds, the workflow should run and leave a comment like this:
### ๐ค AI Generated PR Description
**Summary**
- Added user profile endpoint
- Updated API docs
- Added integration tests
**Changes**
- `routes/users.py` โ new GET /api/users/<id>
- `tests/test_users.py` โ coverage for profile and error cases
- `docs/api.md` โ described request/response schema
**Testing Notes**
Run `pytest` to verify all tests pass.
At this point you have a functioning AI agent that writes PR descriptions while you stay in your coding flow.
- Using
PATCH /repos/{repo}/pulls/{pr_number}to update the PR body instead of posting a comment. - Running the workflow on
synchronizeto keep the description in sync with new commits. - Adding a check to skip if the PR already has a human-written description.
- Including changed file names and labels in the prompt for richer output.
You now have a repeatable pattern for using AI agents in CI. The same script can be adapted for code review summaries, ticket updates, and even automated changelog generation. Go try it on your next PR.
Nice approach. I wonder how it handles PRs that are already well-described or if it overrides human-written text.