Skip to content

Configuration reference

All inputs the Action accepts, in the order you'd typically reach for them. For a minimal starter workflow, see the project README.

Example: full-capability setup

The workflow below enables the action's optional title generation, label application, and breaking-change detection.

name: AI PR Assistant

on:
  pull_request:
    types: [opened, synchronize, reopened, edited]

jobs:
  ai-pr-assistant:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
      issues: write

    steps:
      - name: Generate PR description and metadata
        uses: devsetgo/ai-pr-assistant@main
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          openai_api_key: ${{ secrets.OPENAI_API_KEY }}
          openai_model: gpt-5-mini
          allowed_users: "your-github-username,maintainer-2"
          overwrite_description: smart
          generate_title: true
          overwrite_title: smart
          enable_labels: true
          overwrite_labels: smart
          label_taxonomy: "bug,feature,enhancement,documentation,dependencies,refactor,test,chore,breaking-change"
          detect_breaking_changes: true
          max_diff_tokens: "8000"
          max_tokens: "6000"

Setup walkthrough

  1. Get an API key and add it to GitHub as a secret: OPENAI_API_KEY for OpenAI, or ANTHROPIC_API_KEY for Claude. The Setup guide walks through both, and Choosing a provider covers the inputs.
  2. Create a workflow under .github/workflows/ using the example above.
  3. Add the minimum GitHub permissions needed for the feature set you want:
  4. pull-requests: write for descriptions and titles
  5. issues: write when enable_labels or detect_breaking_changes is true
  6. Turn on optional features one at a time if you want to start simple:
  7. generate_title for title suggestions
  8. overwrite_title to apply the suggested title (see Existing content)
  9. enable_labels for label generation and label creation
  10. detect_breaking_changes to warn on likely breaking changes
  11. overwrite_description to refresh or review the description on PR updates
  12. Adjust openai_model (or anthropic_model), max_tokens, and max_diff_tokens if your repo has large diffs or you want more concise output.
  13. For Azure OpenAI, set azure_endpoint and azure_openai_api_version instead of using the public OpenAI key flow.

Required

Input Description
github_token The GitHub token to use for the Action
openai_api_key or anthropic_api_key The API key for the selected provider (see below), keep it hidden. Only the key for the provider you use is needed

Choosing a provider

Input Description Default
provider openai (also covers Azure OpenAI) or anthropic (Claude, via the direct Anthropic API) openai
openai_api_key The OpenAI API key (or Azure OpenAI key). Required when provider is openai ``
anthropic_api_key The Anthropic API key. Required when provider is anthropic ``
anthropic_model The Claude model to use when provider is anthropic, e.g. claude-haiku-4-5-20251001, claude-sonnet-5, claude-opus-5 claude-haiku-4-5-20251001

A minimal Claude workflow:

      - uses: devsetgo/ai-pr-assistant@main
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          provider: anthropic
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}

For a side-by-side of the models each provider offers, see the Model reference.

The run fails with a clear message if provider isn't openai or anthropic, or if the key for the selected provider is empty. Everything else (title, labels, breaking-change detection, diff handling, the attribution footer) works the same with either provider. Notes specific to Claude:

  • temperature is ignored, for every Claude model. Several current models (Sonnet 5, Opus 5, Opus 4.8/4.7) reject sampling parameters, and the Anthropic SDK no longer exposes them, so the value is never sent, Haiku 4.5 included. openai_model and the Azure inputs are ignored too.
  • Thinking models need headroom. The default, Haiku 4.5, doesn't think. Sonnet 5 and Opus 5 think by default and that counts against max_tokens; if it uses the whole budget the run stops with the "empty description" message rather than writing anything, so raise max_tokens for those models.
  • Refusals fail the run. If Claude declines a request, the Action reports Anthropic request failed and leaves the pull request unchanged.
  • Diff budgeting is approximate. max_diff_tokens is counted with an OpenAI tokenizer, which Claude's tokenizer can exceed, so treat it as a rough budget.

Core behavior

Input Description Default
pull_request_id The ID of the pull request to use Extracted from metadata
allowed_users Comma-separated GitHub usernames this Action will run for (case-insensitive, spaces ignored); empty runs for everyone `` (all users)
overwrite_description never, always or smart: what to do with an existing description, see Existing content never
description_style rich (emoji section headings and GitHub callouts) or plain (bold subheadings and bullets). Structured mode only rich
openai_model The OpenAI model to use when provider is openai, any model compatible with the chat completions endpoint gpt-5-mini
temperature Higher values make the model more creative (0-2). Ignored for reasoning models (gpt-5*, gpt-6*, o1*, o3*, o4*), which only support the default temperature, and always ignored with provider: anthropic 0.6
max_tokens Maximum number of output/completion tokens the model may generate. Reasoning models spend part of this on hidden reasoning tokens before any visible output, so a large diff can need more headroom. It's a ceiling, so a smaller reply costs less 6000

Diff handling

Input Description Default
max_diff_tokens Maximum tokens of PR diff sent to the model, counted with the real tokenizer for openai_model (not a character-count guess); approximate for Claude models 6000
exclude_patterns Comma-separated glob patterns for files dropped from the diff before token budgeting — useful for lockfiles, generated code, and binary/asset files that just waste tokens *.lock,package-lock.json,yarn.lock,pnpm-lock.yaml,*.min.js,*.svg,*.png,*.jpg,*.jpeg,*.gif,*.ico,dist/*,build/*

Prompt customization

Input Description Default
sample_prompt Few-shot example prompt given to the model for tone/style. Classic mode only — see Classic vs. structured mode below See SAMPLE_PROMPT in pr_description/llm.py
sample_response Few-shot example response paired with sample_prompt. Classic mode only See GOOD_SAMPLE_RESPONSE in pr_description/llm.py
completion_prompt The task prompt prepended to the diff content, for both modes See COMPLETION_PROMPT in pr_description/llm.py

Optional capabilities (all opt-in, default off)

Input Description Default
generate_title Also ask the model to propose an improved PR title false
overwrite_title never, always or smart: whether to apply the proposed title (requires generate_title); never only prints it in the action log never
enable_labels Auto-label the PR from label_taxonomy, creating any missing labels in the repo first false
overwrite_labels never, always or smart: what to do when the PR already has labels (requires enable_labels) never
label_taxonomy Comma-separated labels the model may choose from when enable_labels is set bug,feature,enhancement,documentation,dependencies,refactor,test,chore
detect_breaking_changes Flag likely breaking changes on every run: adds a note to the top of the description and applies a breaking-change label, whatever the overwrite_* and enable_labels inputs say false

Existing content: always, never or smart

overwrite_description, overwrite_title and overwrite_labels each decide what happens to content the pull request already has. true and false still work, as always and never.

never always smart
Description Fills in a blank one, otherwise leaves it alone Regenerates it on every run Keeps, extends or replaces it, as the model judges
Title Prints the suggestion in the log Applies the suggestion on every run Replaces a placeholder, or a title the model judges vague or wrong
Labels Labels a PR with none, otherwise leaves them alone Makes taxonomy labels match the model's choice The model reviews the current labels and changes only what's clearly wrong or missing

What smart does with a description:

Existing description Result
Blank, or only this Action's footer Written from scratch, with no review
Generic, an unfilled template, inaccurate, or too thin for the size of the change Replaced
Detailed, but a later push added something it doesn't cover Extended: new text is appended in the same style, and the existing text is kept word for word
Detailed and still accurate Kept, with no write to GitHub

A title is always replaced under smart, without asking the model, if it's blank, a stock word such as dev, wip or update, or just the branch name.

Some guarantees worth knowing:

  • A failed review changes nothing. If the structured request is rejected or its reply is cut off, the existing description, title and labels all stay as they are. The run still passes, with a warning that the model gave no verdict; raise max_tokens if its reply was cut off.
  • Only taxonomy labels are removed. Labels outside label_taxonomy are never touched, and an existing breaking-change label is never removed.
  • Breaking changes always surface. With detect_breaking_changes on, a detected breaking change gets its note above the existing text and its label in every mode, including never. The rest of the description and labels stay as the modes say. The model therefore runs on every push, and a note or label already there stays even if a later run doesn't detect one; remove it by hand if it no longer applies.
  • smart runs the model on every push, so it costs the same as always. It also turns on structured mode, so sample_prompt and sample_response don't apply.

Attribution

Input Description Default
attribution Append a small Created using devsetgo/ai-pr-assistant with <model> footer to the generated description. Set to false to omit it true

The footer is added by the Action after the model responds, not requested in the prompt, so it always names the openai_model you configured. On Azure OpenAI that value is your deployment name, which may differ from the underlying model.

Azure OpenAI

Input Description Default
azure_endpoint Azure OpenAI resource endpoint. Setting this switches the Action to Azure OpenAI instead of the public OpenAI API ``
azure_openai_api_version The Azure OpenAI API version to target ``

Classic vs. structured mode

By default (generate_title, enable_labels, and detect_breaking_changes all false), the Action uses classic mode: the original plain-text behavior, using sample_prompt/sample_response as a few-shot example and returning just a description. This is unchanged from earlier versions of this Action.

Turning on any one of generate_title, enable_labels, or detect_breaking_changes, or a smart overwrite mode, switches to structured mode: a single request constrained by a JSON schema returns the description, title, labels, and breaking-change assessment together. sample_prompt/sample_response are not used in this mode — the schema itself constrains the response shape instead.

In structured mode, the description is a short summary followed by a bulleted list of key points. With description_style: rich, larger changes get emoji section headings, > [!IMPORTANT] and > [!WARNING] callouts for what a reviewer must act on, and a 👀 Review focus section; with plain, they get bold subheadings. When smart extends a description, the new text follows the existing style instead. The title is Title Case, prefixed with its category — e.g. Enhancement: Add Dark Mode Toggle or Bug: Fix Crash on Empty Input (Breaking Change: instead when detect_breaking_changes finds one).

If the API rejects a structured request (for example, an older Azure deployment or API version without structured-output support), the Action falls back once to a classic plain-text request rather than failing the run, and logs a warning. Under smart, that text is only used to fill a blank description.

Permissions

  • Updating the description/title requires pull-requests: write (or equivalent classic GITHUB_TOKEN permissions — see Troubleshooting).
  • enable_labels and detect_breaking_changes additionally require issues: write, since labels live on the issue object in the GitHub API, even for pull requests.

A note on breaking-change detection

A detected breaking change appears as a > [!CAUTION] callout at the top of the description. detect_breaking_changes is judged by the model from the diff content alone, not by static analysis of your language or framework. Treat it as a helpful heuristic that can save you a re-read, not a guarantee — it can both miss real breaking changes and flag things that aren't.