Detector / Fixer Chaining¶
Run a detector and its paired fixer in a single workflow run, so the fixer acts on the detector's findings immediately — no separate schedule needed.
Why chain?¶
When a detector and fixer run on separate schedules, the detector creates an issue via github-actions[bot]. GitHub does not trigger other workflows from events created by github-actions[bot], so the fixer must poll on its own schedule. Chaining removes that delay: the fixer job reads the detector's output directly.
How it works¶
The gh-aw compiler (v0.51.0+) exposes safe-output results as workflow_call outputs. A detector that creates an issue will output:
| Output | Description |
|---|---|
created_issue_number |
Number of the first created issue |
created_issue_url |
URL of the first created issue |
A fixer that creates a PR will output:
| Output | Description |
|---|---|
created_pr_number |
Number of the first created pull request |
created_pr_url |
URL of the first created pull request |
Your caller workflow chains them with needs and if:
jobs:
detect:
uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-hunter.lock.yml@v0
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
fix:
needs: detect
if: needs.detect.outputs.created_issue_number != ''
uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-exterminator.lock.yml@v0
with:
additional-instructions: |
Focus on the bug described in ${{ needs.detect.outputs.created_issue_url }}
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
The fixer job only runs when the detector actually created an issue.
Audit creates issue -> create PR in same workflow¶
With current compiler output propagation, you can chain directly from an audit/detector workflow to gh-aw-create-pr-from-issue in the same run:
jobs:
run:
uses: elastic/ai-github-actions/.github/workflows/gh-aw-text-auditor.lock.yml@v0
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
create_pr_from_issue:
needs: run
if: needs.run.outputs.created_issue_number != ''
uses: elastic/ai-github-actions/.github/workflows/gh-aw-create-pr-from-issue.lock.yml@v0
with:
target-issue-number: ${{ needs.run.outputs.created_issue_number }}
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
This pattern gives you: Audit creates issue -> same workflow: if issue was created, then start create-pr-from-issue.
Detector creates issue -> assign to Copilot¶
Instead of chaining to a fixer workflow, you can assign the created issue to GitHub's Copilot coding agent and let it open a PR. This is useful when you don't have a dedicated fixer workflow or want to use Copilot's native implementation flow.
jobs:
detect:
uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-hunter.lock.yml@v0
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
assign-to-copilot:
needs: detect
if: needs.detect.outputs.created_issue_number != ''
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Assign issue to Copilot
env:
GH_TOKEN: ${{ github.token }}
run: |
gh issue edit ${{ needs.detect.outputs.created_issue_number }} \
--repo ${{ github.repository }} \
--add-assignee @copilot
Copilot picks up the assignment, reads the issue, and opens a PR — using its own session and context window. No COPILOT_GITHUB_TOKEN is needed for the handoff job itself since assignment only requires issues: write.
Complete examples¶
Bug Hunter + Bug Exterminator¶
name: Bug Hunt & Fix
on:
schedule:
- cron: "0 11 * * 1-5"
workflow_dispatch:
permissions:
actions: read
contents: write
issues: write
pull-requests: write
jobs:
detect:
uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-hunter.lock.yml@v0
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
fix:
needs: detect
if: needs.detect.outputs.created_issue_number != ''
uses: elastic/ai-github-actions/.github/workflows/gh-aw-bug-exterminator.lock.yml@v0
with:
additional-instructions: |
Focus on the bug described in ${{ needs.detect.outputs.created_issue_url }}
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
Code Duplication Detector + Code Duplication Fixer¶
name: Code Duplication Detect & Fix
on:
schedule:
- cron: "0 12 * * 1-5"
workflow_dispatch:
permissions:
actions: read
contents: write
issues: write
pull-requests: write
jobs:
detect:
uses: elastic/ai-github-actions/.github/workflows/gh-aw-code-duplication-detector.lock.yml@v0
with:
languages: TypeScript, JavaScript
file-globs: "src/**/*.ts, src/**/*.js"
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
fix:
needs: detect
if: needs.detect.outputs.created_issue_number != ''
uses: elastic/ai-github-actions/.github/workflows/gh-aw-code-duplication-fixer.lock.yml@v0
with:
additional-instructions: |
Focus on the duplication described in ${{ needs.detect.outputs.created_issue_url }}
secrets:
COPILOT_GITHUB_TOKEN: ${{ secrets.COPILOT_GITHUB_TOKEN }}
When to chain vs. separate schedules¶
| Approach | Best for |
|---|---|
| Chained (single run) | Fully autonomous loops where you want immediate action on findings |
| Assign to Copilot | Lightweight handoff — detector creates the issue, Copilot implements it natively |
| Separate schedules | Human-in-the-loop review — run the detector, review its issues, then let the fixer run later |
| Detector only | When you only want reports, not automatic fixes |
Notes¶
- The fixer job's
ifcondition prevents it from running when the detector finds nothing (noop). - Both jobs share the same
COPILOT_GITHUB_TOKENsecret. - The caller workflow needs the union of both workflows' permissions (e.g.,
contents: write+pull-requests: writefor the fixer). - Chaining does not replace the standalone examples — you can still run each workflow independently.