Permissions first

Every workflow step that calls a model needs explicit access to GitHub Models; otherwise the step fails. Grant it in the workflow's permissions block:

permissions:
  contents: read
  issues: write
  models: read

This reads repository contents and reads, creates or updates issues and comments, while enabling GitHub Models access.

Triaging bug reports with the AI inference action

The AI inference action lets a workflow call a model to analyze or generate text. A workflow that screens incoming bug reports can check whether a new issue contains enough detail to be actionable and reply when it does not.

Create bug-reproduction-instructions.yml under .github/workflows — creating the directory if needed. It runs when an issue is opened and captures the issue title and body for later steps.

name: Bug Report Reproduction Check

on:
  issues:
    types: [opened]

permissions:
  contents: read
  issues: write
  models: read

jobs:
  reproduction-steps-check:
    runs-on: ubuntu-latest
    steps:
      - name: Fetch Issue
        id: issue
        uses: actions/github-script@v7
        with:
          script: |
            const issue = await github.rest.issues.get({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number
            })
            core.setOutput('title', issue.data.title)
            core.setOutput('body', issue.data.body)

Add a step that runs only for issues carrying the bug label. It invokes the AI inference action with a system prompt describing what good reproduction instructions look like, plus the issue content:

- name: Analyze Issue For Reproduction
  if: contains(join(github.event.issue.labels.*.name, ','), 'bug')
  id: analyze-issue
  uses: actions/ai-inference@v1
  with:
  model: mistral-ai/ministral-3b
  system-prompt: |
    Given a bug report title and text for an application, return 'pass' if there is enough information to reliably reproduce the issue, meaning the report clearly describes the steps to reproduce the problem, specifies the expected and actual behavior, and includes environment details such as browser and operating system; if any of these elements are missing or unclear, return a brief description of what is missing in a friendly response to the author instead of 'pass'. Consider the following title and body:
  prompt: |
    Title: ${{ steps.issue.outputs.title }}
    Body: ${{ steps.issue.outputs.body }}

The step returns either pass when the report is sufficient, or a description of what is missing. The model can be swapped by changing the model value to the identifier listed on any model page in the GitHub Models catalog, which offers more than 40 models.

A final step posts a comment only when the returned value is not pass:

- name: Comment On Issue
  if: contains(join(github.event.issue.labels.*.name, ','), 'bug') && steps.analyze-issue.outputs.response != 'pass'
  uses: actions/github-script@v7
  env:
    AI_RESPONSE: steps.analyze-issue.outputs.response
    with:
      script: |
        await github.rest.issues.createComment({
          owner: context.repo.owner,
          repo: context.repo.repo,
          issue_number: context.issue.number,
          body: process.env.AI_RESPONSE
        })

This pattern yields AI-driven branching logic: prompt the model to emit a fixed string when criteria are met, then condition workflow behavior on that value.

An issue on GitHub named "Doesn't work on firefox" with no description and a bug label. The github-actions bot responds asking for more information - specifically reproduction steps, expected and actual behavior, and browser and operating system details.

Release notes from merged pull requests

The GitHub CLI with the gh-models extension covers cases where you gather data and act on it inside a workflow — summarizing each merged pull request straight into a changelog issue.

Prepare a release label and a single issue with that label titled Publish next release changelog, then create release-notes.yml in .github/workflows. It fires when a pull request is closed, and its job runs only if the pull request was merged.

name: Add to Changelog

on:
  pull_request:
    types:
      - closed

permissions:
  pull-requests: read
  issues: write
  contents: read
  models: read

jobs:
  add_to_changelog:
    if: github.event.pull_request.merged == true
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

Install the extension in a step, passing the workflow token that now carries GitHub Models permissions:

- name: Install gh-models extension
  run: gh extension install https://github.com/github/gh-models
  env:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

The remaining work sits in one step:

- name: Summarize pull request and append to release issue
  env:
    GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
  run: |-
    PR_NUMBER="${{ github.event.pull_request.number }}"

    # Fetch PR and save to a file
    gh pr view "$PR_NUMBER" --json title,body,comments,reviews > pr.json
    
    # Generate a summary using the model by reading from file
    cat pr.json | gh models run xai/grok-3-mini \
      "Given the following pull request information, generate a single, clear, and concise one-line changelog entry that summarizes the main change (feature, fix, or bug) introduced by this PR. Use neutral, user-facing language and avoid technical jargon or internal references. Only write the line, with no additional introduction or explanation text." > summary.md

    # Fetch release issue number
    RELEASE_ISSUE=$(gh issue list --label release --limit 1 --json number --jq '.[0].number')

    # Fetch current release issue body
    RELEASE_ISSUE_BODY=$(gh issue view "$RELEASE_ISSUE" --json body --jq '.body')

    # Append summary to release issue body
    FORMATTED_LINE="- $(cat summary.md) (#$PR_NUMBER)"
    NEW_BODY="${RELEASE_ISSUE_BODY}"$'\n'"$FORMATTED_LINE"

    # Update the release issue with the new body
    gh issue edit "$RELEASE_ISSUE" --body "$NEW_BODY"

The pull request title, body, comments and reviews are passed to a model via gh models run; the release issue is fetched and appended with the summarized line.

A pull request named Publish Next Release Changelog. The description has two bullet list items - each one describing a change in 8-12 words with a link to the merged pull request.

Scheduled issue summaries with a prompt file

A scheduled workflow can open a weekly issue that summarizes, groups and prioritizes newly opened issues. Create weekly-issue-summary.yml in .github/workflows, triggering every Monday at 9 a.m.:

name: Weekly Issue Summary

on:
  workflow_dispatch:
  schedule:
    - cron: '0 9 * * 1'

permissions:
  issues: write
  contents: read
  models: read

jobs:
  create_weekly_summary:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Install gh-models extension
        run: gh extension install https://github.com/github/gh-models
        env:
          GH_TOKEN: ${{ github.token }}

Collect the past week's open issues into a file:

 - name: Get issues from the past week and summarize
  id: get_issues
    run: |-
      LAST_WEEK=$(date -d "7 days ago" +"%Y-%m-%d")
      gh search issues "created:>$LAST_WEEK" --state=open --json title,body,url --repo ${{ github.repository }} > issues.json

      # further code will go here
    env:
      GH_TOKEN: ${{ github.token }}

Feed that file to a gh models run call:

cat issues.json | gh models run --file prompts/issue-summary.prompt.yml > summary.md

Here the command takes its instructions from a prompt file instead of an inline prompt. Create a prompts directory containing issue-summary.prompt.yml:

name: Issue summarizer
description: Summarizes weekly issues
model: openai/gpt-4.1
messages:
  - role: system
    content: You are a helpful issue summarizer. When given issue content, respond in markdown format.
  - role: user
    content: "Please summarize the following issues into a few short bullet points. Include links if provided. If possible, pull out general themes and help the team prioritize based on impact. Issues begin here:\n {{input}}"

The file holds the model, the system and user prompts, and optionally parameters that tune the response. Using a .prompt.yml file also connects to GitHub Models' repository integration for iterating on the prompt in a rich UI.

Still in the workflow, directly beneath the gh models run command, create the issue carrying the summary:

ISSUE_TITLE="Issue Summary - $(date -d '7 days ago' '+%B %d') to $(date '+%B %d')"
gh issue create --title "$ISSUE_TITLE" --label summary --body-file summary.md
An issue with the title "Issue Summary - June 16 to June 23". It has three sections - an issue summary which details and links each issue that has been opened, general themes which contains three groupings for the issues, and suggested prioritization. The top issue is on data integrity - issue 37.

The three approaches scale with your needs: the AI inference action for simple analysis and branching, gh-models with inline prompts for gathering and acting on repository data, and prompt-file-driven workflows for scheduled, more elaborate jobs.