This tutorial assumes you have a GitHub repository with basic Actions enabled and an OpenAI API key. We'll use openai Python package and actions/github-script.

Manually writing PR descriptions is tedious. An AI agent can analyze your code changes and produce a summary, motivation, testing notes, and even potential risks. Here's how to set it up:

Step 1: Create the Workflow File

In your repo, create .github/workflows/ai-pr-description.yml:

name: AI PR Description

on:
  pull_request:
    types: [opened, synchronize]

jobs:
  generate-description:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0  # needed to get diff
      - name: Get diff
        id: diff
        run: |
          echo "pr_diff=$(git diff origin/${{ github.base_ref }}...${{ github.head_ref }} | head -c 16000)" >> $GITHUB_OUTPUT
      - name: Generate description with AI
        id: ai
        run: |
          python3 -c "
import openai, os, json
openai.api_key = os.getenv('OPENAI_API_KEY')
diff = '''${{ steps.diff.outputs.pr_diff }}'''
response = openai.ChatCompletion.create(
  model='gpt-4o-2024-05-13',
  messages=[
    {'role': 'system', 'content': 'You are a code reviewer and technical writer. Given a git diff, write a concise PR description with sections: ## Summary, ## Changes, ## Testing, ## Risks. Use markdown.'},
    {'role': 'user', 'content': f'Generate PR description for this diff:\n\n{diff}'}
  ],
  temperature=0.3
)
description = response['choices'][0]['message']['content']
# escape for GitHub Actions
print(description.replace('%', '%25').replace('\n', '%0A').replace('\r', '%0D'))
" > description.txt
          echo "description<> $GITHUB_OUTPUT
          cat description.txt >> $GITHUB_OUTPUT
          echo "EOF" >> $GITHUB_OUTPUT
      - name: Update PR description
        uses: actions/github-script@v7
        with:
          script: |
            const { owner, repo, number } = context.issue;
            const desc = process.env.DESCRIPTION;
            await github.rest.pulls.update({
              owner, repo, pull_number: number,
              body: desc
            });
        env:
          DESCRIPTION: ${{ steps.ai.outputs.description }}

Step 2: Add OpenAI API Key as Secret

Go to repo Settings > Secrets and variables > Actions, add OPENAI_API_KEY.

Step 3: Test It

Open a new PR. After a few seconds, the bot will update the description. Example output:

## Summary
Added a new endpoint for user profile updates.

## Changes
- `src/routes/profile.ts`: Implemented PUT /profile route
- `src/services/profileService.ts`: Added validation logic

## Testing
- Unit tests added for service layer
- Manual test with Postman

## Risks
None; endpoints are behind auth.
Pro tip: Customize the system prompt to match your team's style, include JIRA ticket numbers, or enforce checklists.

Step 4: Handle Long Diffs

GitHub limits output. For large PRs, split diff into chunks or use file list only. Example:

files=$(git diff --name-only origin/${{ github.base_ref }}...${{ github.head_ref }})
# Then ask AI to summarize based on file names and commit messages

That's it! Your team will love consistent, informative PR descriptions without extra effort.