Skip to content
Latchkey

agent-scan workflow (nuxt/nuxt)

The agent-scan workflow from nuxt/nuxt, explained and optimized by Latchkey.

A

CI health: A - excellent

Point runs-on at Latchkey and get job timeouts, self-healing for flaky steps, and up to 58% lower cost, applied automatically.

Grade your own workflow free or run it on Latchkey →
Source: nuxt/nuxt.github/workflows/agent-scan.ymlLicense MITView source

What it does

This is the agent-scan workflow from the nuxt/nuxt repository, a real project running GitHub Actions. It is shown here with attribution under its MIT license.

Below, Latchkey shows a faster, safer version produced by its optimization engine.

The workflow

workflow (.yml)
name: agent-scan

on:
# zizmor: ignore[dangerous-triggers] - DO NOT add action/checkout in this workflow as it use pull_request_target
  pull_request_target:
    types:
      - opened
      - reopened

concurrency:
  group: agent-scan-${{ github.event.pull_request.number }}
  cancel-in-progress: true

permissions:
  issues: write
  pull-requests: write

jobs:
  agentscan:
    runs-on: ubuntu-latest
    steps:
      - name: AgentScan
        id: agentscan
        uses: MatteoGabriele/agentscan-action@c7d61446e7aece6bdd3edcee4558bbfc0392615e # v2.0.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          mode: 'labels'
          trusted-author-associations: 'owner, member'
      - name: Handle flagged PR
        if: (contains(fromJSON('["automation","mixed"]'), steps.agentscan.outputs.classification) || steps.agentscan.outputs.community-flagged == 'true')
        env:
          CLASSIFICATION: ${{ steps.agentscan.outputs.classification }}
          COMMUNITY_FLAGGED: ${{ steps.agentscan.outputs.community-flagged }}
        uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
        with:
          script: |
            const prNumber = context.payload.pull_request.number;
            const classification = process.env.CLASSIFICATION;
            const communityFlagged = process.env.COMMUNITY_FLAGGED === 'true';
            const shouldClose = classification === 'automation' || communityFlagged;

            const issue = context.payload.pull_request
            const labels = issue.labels?.map(l => l.name) || []

            if (!labels.includes('possible bot')) {
              await github.rest.issues.addLabels({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: prNumber,
                labels: ['possible bot'],
              })
            }

            const comments = await github.paginate(github.rest.issues.listComments, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: prNumber,
              per_page: 100,
            })

            const alreadyCommented = comments.some(
              c => c.user.type === 'Bot' && c.body.includes('AI-assisted contribution guidelines')
            )

            if (!alreadyCommented) {
              const closingNote = shouldClose
                ? "We're closing this for now as the account looks automated. If we got that wrong, please just reopen the PR and we'll take another look."
                : 'If this was flagged in error, we apologise! 😳 Just let us know. πŸ™'

              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: prNumber,
                body: [
                  "We've flagged this as a potential contribution without a human behind it. We welcome the thoughtful use of AI tools when contributing to Nuxt, but ask all contributors to follow [two core principles](https://roe.dev/blog/using-ai-in-open-source):",
                  '',
                  '1. **Never let an LLM speak for you** - all comments, issues, and PR descriptions should be written in your own words, reflecting your own understanding.',
                  '2. **Never let an LLM think for you** - only submit contributions you fully understand and can explain.',
                  '',
                  'Please review our [AI-assisted contribution guidelines](https://nuxt.com/docs/community/contribution#ai-assisted-contributions) and update this contribution if needed.',
                  '',
                  closingNote,
                ].join('\n'),
              })
            } else {
              core.info('Possible-bot comment already exists - skipping comment.')
            }

            if (shouldClose && issue.state === 'open' && !alreadyCommented) {
              await github.rest.pulls.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: prNumber,
                state: 'closed',
                title: '🚨 unwelcome pr from bot 🚨',
              })
            }

            const actionTaken = [
              'Added `possible bot` label',
              alreadyCommented ? null : 'posted policy comment',
              shouldClose && !alreadyCommented ? 'closed PR' : null,
            ].filter(Boolean).join(', ')

            core.summary
              .addHeading('AgentScan: Possible Bot Flag', 2)
              .addTable([
                [{ data: 'Property', header: true }, { data: 'Value', header: true }],
                ['Pull Request', `#${prNumber}`],
                ['Classification', classification],
                ['Community flagged', String(communityFlagged)],
                ['Action', actionTaken || 'No action (already handled)'],
              ])

            await core.summary.write()

The same workflow, on Latchkey

Removes redundant runs and caps runaway jobs. Added and changed lines are highlighted.

name: agent-scan
 
on:
# zizmor: ignore[dangerous-triggers] - DO NOT add action/checkout in this workflow as it use pull_request_target
  pull_request_target:
    types:
      - opened
      - reopened
 
concurrency:
  group: agent-scan-${{ github.event.pull_request.number }}
  cancel-in-progress: true
 
permissions:
  issues: write
  pull-requests: write
 
jobs:
  agentscan:
    timeout-minutes: 30
    runs-on: latchkey-small
    steps:
      - name: AgentScan
        id: agentscan
        uses: MatteoGabriele/agentscan-action@c7d61446e7aece6bdd3edcee4558bbfc0392615e # v2.0.1
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          mode: 'labels'
          trusted-author-associations: 'owner, member'
      - name: Handle flagged PR
        if: (contains(fromJSON('["automation","mixed"]'), steps.agentscan.outputs.classification) || steps.agentscan.outputs.community-flagged == 'true')
        env:
          CLASSIFICATION: ${{ steps.agentscan.outputs.classification }}
          COMMUNITY_FLAGGED: ${{ steps.agentscan.outputs.community-flagged }}
        uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
        with:
          script: |
            const prNumber = context.payload.pull_request.number;
            const classification = process.env.CLASSIFICATION;
            const communityFlagged = process.env.COMMUNITY_FLAGGED === 'true';
            const shouldClose = classification === 'automation' || communityFlagged;
 
            const issue = context.payload.pull_request
            const labels = issue.labels?.map(l => l.name) || []
 
            if (!labels.includes('possible bot')) {
              await github.rest.issues.addLabels({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: prNumber,
                labels: ['possible bot'],
              })
            }
 
            const comments = await github.paginate(github.rest.issues.listComments, {
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: prNumber,
              per_page: 100,
            })
 
            const alreadyCommented = comments.some(
              c => c.user.type === 'Bot' && c.body.includes('AI-assisted contribution guidelines')
            )
 
            if (!alreadyCommented) {
              const closingNote = shouldClose
                ? "We're closing this for now as the account looks automated. If we got that wrong, please just reopen the PR and we'll take another look."
                : 'If this was flagged in error, we apologise! 😳 Just let us know. πŸ™'
 
              await github.rest.issues.createComment({
                owner: context.repo.owner,
                repo: context.repo.repo,
                issue_number: prNumber,
                body: [
                  "We've flagged this as a potential contribution without a human behind it. We welcome the thoughtful use of AI tools when contributing to Nuxt, but ask all contributors to follow [two core principles](https://roe.dev/blog/using-ai-in-open-source):",
                  '',
                  '1. **Never let an LLM speak for you** - all comments, issues, and PR descriptions should be written in your own words, reflecting your own understanding.',
                  '2. **Never let an LLM think for you** - only submit contributions you fully understand and can explain.',
                  '',
                  'Please review our [AI-assisted contribution guidelines](https://nuxt.com/docs/community/contribution#ai-assisted-contributions) and update this contribution if needed.',
                  '',
                  closingNote,
                ].join('\n'),
              })
            } else {
              core.info('Possible-bot comment already exists - skipping comment.')
            }
 
            if (shouldClose && issue.state === 'open' && !alreadyCommented) {
              await github.rest.pulls.update({
                owner: context.repo.owner,
                repo: context.repo.repo,
                pull_number: prNumber,
                state: 'closed',
                title: '🚨 unwelcome pr from bot 🚨',
              })
            }
 
            const actionTaken = [
              'Added `possible bot` label',
              alreadyCommented ? null : 'posted policy comment',
              shouldClose && !alreadyCommented ? 'closed PR' : null,
            ].filter(Boolean).join(', ')
 
            core.summary
              .addHeading('AgentScan: Possible Bot Flag', 2)
              .addTable([
                [{ data: 'Property', header: true }, { data: 'Value', header: true }],
                ['Pull Request', `#${prNumber}`],
                ['Classification', classification],
                ['Community flagged', String(communityFlagged)],
                ['Action', actionTaken || 'No action (already handled)'],
              ])
 
            await core.summary.write()
 

What changed

This workflow runs 1 job per trigger. On Latchkey the same minutes cost up to 58% less than GitHub-hosted, with zero queue time.

Actions used in this workflow