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.")
Use 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
Never hardcode secrets in your workflow. Store 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.

This is a foundation. You can extend it by:
  • Using PATCH /repos/{repo}/pulls/{pr_number} to update the PR body instead of posting a comment.
  • Running the workflow on synchronize to 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.
Remember that AI-generated text can contain inaccuracies. Your PR description is a tool for reviewers โ€” they will appreciate it, but they should still verify the details against the actual code.

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.