Building a PR Description Agent for GitHub Actions
In this guide, you'll build a GitHub Action that uses a Mastra agent to read pull request diffs, generate multi-language summaries, and write them directly to the PR description in the GitHub UI. The action runs whenever a pull request is created or updated and regenerates the description as the diff changes.
This approach is similar to AI-powered PR tools like CodeRabbit and Greptile, but built using native GitHub Actions workflows and Mastra agents.
The setup consists of three parts:
- A Mastra agent that generates the description
- A GitHub Actions workflow that triggers on pull requests
- A Node.js script that connects the workflow to the agent
The finished action writes a description with summaries in English, Spanish, and Japanese, each marked with a flag emoji for easy scanning. For example:
🇬🇧 English
This PR integrates Astro into the project, adding configuration files and updating scripts to support Astro development.
🇪🇸 Español
Este PR integra Astro en el proyecto, añadiendo archivos de configuración y actualizando scripts para soportar el desarrollo con Astro.
🇯🇵 日本語
このPRは、Astroをプロジェクトに統合し、Astro開発をサポートするための設定ファイルを追加し、スクリプトを更新します。
Before you beginDirect link to Before you begin
- A Mastra project (see Quickstart)
- An API key from a supported model provider. If you don't have a preference, use OpenAI
- Node.js
v22.13.0or later
Set up repository secretsDirect link to Set up repository secrets
The workflow needs access to your model provider API key. Add it as a repository secret in GitHub:
-
Go to your repository on GitHub
-
Navigate to Settings > Secrets and variables > Actions
-
Click New repository secret
-
Add your API key with the name
OPENAI_API_KEY(or the appropriate key for your provider)
The workflow references this secret as ${{ secrets.OPENAI_API_KEY }} and makes it available to the Mastra agent at runtime.
Create the description agentDirect link to Create the description agent
The PR description agent is responsible for turning a git diff into a clear, reviewer-friendly pull request description.
This agent receives the raw diff from a pull request. It generates descriptions in the configured languages and formats the output using emoji flags so each language section is easy to scan in the PR.
import { Agent } from "@mastra/core/agent";
export const descriptionAgent = new Agent({
id: "description-agent",
name: "PR Description Agent",
instructions: `You are a helpful assistant that creates clear, concise PR descriptions.
When given a git diff of changed files, you will:
1. Analyze the changes to understand what was modified
2. Write a brief summary and list of changes
3. Output the same content in English, Spanish, and Japanese
Guidelines:
- Be concise but informative
- Focus on the "what" and "why" of changes
- Use technical terms appropriately
- Keep bullet points short and scannable
- Each language section should contain the same information, naturally translated
Output format:
### 🇬🇧 English
[1-2 sentence summary]
- [Change 1]
- [Change 2]
- [Change 3]
---
### 🇪🇸 Español
[Same summary in Spanish]
- [Same changes in Spanish]
---
### 🇯🇵 日本語
[Same summary in Japanese]
- [Same changes in Japanese]
`,
model: "openai/gpt-4o"
});
Test the agent locallyDirect link to Test the agent locally
Before deploying the workflow, you can test the agent in Mastra Studio to verify it generates descriptions correctly.
-
Get a diff from any public GitHub PR by appending
.diffto the PR URL:https://github.com/owner/repo/pull/123.diff -
Open the PR Description Agent in Studio and paste the diff content with this prompt:
"Please create a PR description for the following changes. <paste the diff content here>"
The agent will return a formatted description with sections in English, Spanish, and Japanese.
GitHub ActionsDirect link to GitHub Actions
GitHub Actions run your workflows in short-lived environments on GitHub's infrastructure. Each run starts with a clean virtual machine, checks out your code, installs dependencies, runs your workflow steps, and then shuts down. Nothing persists between runs unless you explicitly save it as an artifact or cache.
Create the workflowDirect link to Create the workflow
GitHub Actions workflows live in the .github/workflows directory. Create a .github directory at the root of your project, then create a workflows directory inside it. Add a file named pr-description.yml.
This workflow runs whenever a pull request is opened or updated. It generates a diff for the PR, calls the Mastra agent to describe the changes, and writes the description directly into the PR in the GitHub UI.
name: PR Description Generator
on:
pull_request:
types: [opened, synchronize]
permissions:
contents: read
pull-requests: write
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
PR_DIFF_FILE: /tmp/pr_diff.txt
PR_DESCRIPTION_FILE: /tmp/pr_description.md
jobs:
generate-description:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/setup-node@v4
with:
node-version: '22'
cache: 'npm'
- run: npm ci
- id: pr
run: |
BASE_REF=$(gh pr view ${{ github.event.pull_request.number }} --json baseRefName -q '.baseRefName')
git fetch origin $BASE_REF
git diff origin/$BASE_REF...HEAD -- . ':!package-lock.json' > $PR_DIFF_FILE
- run: npx tsx .github/scripts/generate-description.ts
- run: gh pr edit ${{ github.event.pull_request.number }} --body-file $PR_DESCRIPTION_FILE
The workflow explainedDirect link to The workflow explained
on: pull_request: Runs when a pull request is opened or updated.permissions: pull-requests: write: Allows the workflow to update the PR description.env: Defines shared file paths used across steps and reads required values from repository secrets, including the model API key used by the Mastra agent.actions/checkout@v4+ git commands: Checks out the full repository history, fetches the PR base branch, and writes the PR diff to/tmp/pr_diff.txt.actions/setup-node@v4: Sets up the Node.js runtime used by the workflow.npm ci: Installs the repository's Node.js dependencies from the lockfile.generate-description.ts: Reads/tmp/pr_diff.txt, calls the Mastra agent, and writes the generated description to/tmp/pr_description.md.gh pr edit: Updates the pull request description using the contents of/tmp/pr_description.md.
The workflow excludes package-lock.json when generating the diff. Lockfiles are often large and noisy, and including them can overwhelm the agent's context window and make the resulting description harder to reason about.
Create the workflow scriptDirect link to Create the workflow script
Create a scripts directory inside .github and add a file named generate-description.ts.
This script reads the PR diff from PR_DIFF_FILE, generates a description using the Mastra agent, and writes the result to PR_DESCRIPTION_FILE for the workflow to publish to the pull request.
import { readFileSync, writeFileSync } from "fs";
import { mastra } from "../../src/mastra";
const agent = mastra.getAgent("descriptionAgent");
await agent.generate(
`Please create a PR description for the following changes.
Git diff:
\`\`\`diff
${readFileSync(process.env.PR_DIFF_FILE!, "utf-8")}
\`\`\``,
{
onError: () => {
writeFileSync(
process.env.PR_DESCRIPTION_FILE!,
"This PR diff is too large to generate a description automatically."
);
},
onFinish: (result) => {
writeFileSync(process.env.PR_DESCRIPTION_FILE!, result.text);
}
}
);
The workflow script explainedDirect link to The workflow script explained
mastra.getAgent("descriptionAgent"): Gets the Mastra agent that generates the PR description.agent.generate(...): Reads the pull request diff fromPR_DIFF_FILEand asks the agent to write a PR description.onErrorcallback: Writes a fallback message toPR_DESCRIPTION_FILEwhen the diff is too large to process.onFinishcallback: Writes the generated PR description toPR_DESCRIPTION_FILE.
Next stepsDirect link to Next steps
You now have a GitHub Action that generates multi-language PR descriptions using a Mastra agent. Once the workflow and supporting files are merged into your main branch, the agent will run automatically the next time a pull request is created or updated. You can monitor the run in the Actions tab of your repository.
From here, you can customize the agent instructions, change the output languages, or extend the workflow to handle other events.
To learn more:
- Read the agents documentation
- Give your agent tools to fetch additional context
- Explore other GitHub Actions triggers like issue comments or releases