Skip to content
GitHub Agentic Workflows

Triggers

The on: section uses standard GitHub Actions syntax to define workflow triggers. For example:

on:
issues:
types: [opened]

GitHub Agentic Workflows supports all standard GitHub Actions triggers plus additional enhancements for reactions, cost control, and advanced filtering.

Run workflows manually from the GitHub UI, API, or via gh aw run/gh aw trial. Full syntax reference.

Basic trigger:

on:
workflow_dispatch:

With input parameters:

on:
workflow_dispatch:
inputs:
topic:
description: 'Research topic'
required: true
type: string
priority:
description: 'Task priority'
required: false
type: choice
options:
- low
- medium
- high
default: medium

Use ${{ github.event.inputs.INPUT_NAME }} expressions to access workflow_dispatch inputs in your markdown content:

---
on:
workflow_dispatch:
inputs:
topic:
description: 'Research topic'
required: true
type: string
permissions:
contents: read
safe-outputs:
create-discussion:
---
# Research Assistant
Research the following topic: "${{ github.event.inputs.topic }}"
Provide a comprehensive summary with key findings and recommendations.

Supported input types:

  • string - Free-form text input
  • boolean - True/false checkbox
  • choice - Dropdown selection with predefined options
  • environment - Repository environment selector

Run workflows on a recurring schedule using human-friendly expressions or cron syntax.

Fuzzy Scheduling (Recommended for Daily Workflows):

To distribute workflow execution times and prevent load spikes, use fuzzy schedules that let the compiler automatically scatter execution times:

on:
schedule: daily # Compiler scatters execution time deterministically
on:
schedule:
- cron: daily # Each workflow gets a different scattered time

For workflows that need to run around a specific time (with some flexibility), use the around constraint:

on:
schedule: daily around 14:00 # Scatters within ±1 hour (13:00-15:00)

The compiler deterministically assigns each workflow a unique time throughout the day based on the workflow file path. This ensures:

  • Load distribution: Workflows run at different times, reducing server load spikes
  • Consistency: The same workflow always gets the same execution time across recompiles
  • Simplicity: No need to manually coordinate schedules across multiple workflows
  • Flexibility with constraints: Use around to hint preferred times while still distributing load

Human-Friendly Format:

on:
schedule: daily at 02:00 # Shorthand string format (not recommended - creates load spikes)
on:
schedule:
- cron: weekly on monday at 09:00
- cron: monthly on 15 at 12:00

Supported Formats:

  • Daily (Fuzzy): daily → Scattered time like 43 5 * * * (compiler determines)
  • Daily (Fuzzy Around): daily around HH:MM → Scattered time within ±1 hour of target
    • daily around 14:0020 14 * * * (scattered between 13:00-15:00)
    • daily around 9am38 8 * * * (scattered between 08:00-10:00)
    • daily around midnight27 0 * * * (scattered between 23:00-01:00)
    • daily around noon → Scattered time between 11:00-13:00
    • With UTC offsets: daily around 3pm utc-533 19 * * * (3 PM EST → scattered around 8 PM UTC)
    • With time zones: daily around 14:00 utc+947 5 * * * (2 PM JST → scattered around 5 AM UTC)
    • Supports all time formats: HH:MM, midnight, noon, Npm, Nam with optional UTC offsets
  • Daily (Fixed): daily at HH:MM or daily at midnight/noon or daily at Npm/Nam
    • daily at 02:000 2 * * * (⚠️ Warning: fixed time)
    • daily at midnight0 0 * * * (⚠️ Warning: fixed time)
    • daily at 3pm0 15 * * * (⚠️ Warning: fixed time)
    • daily at 6am0 6 * * * (⚠️ Warning: fixed time)
  • Weekly (Fuzzy): weekly or weekly on <day> or weekly on <day> around HH:MM
    • weekly → Scattered day and time like 43 5 * * 3 (compiler determines)
    • weekly on monday → Scattered time like 43 5 * * 1 (compiler determines)
    • weekly on friday → Scattered time like 28 14 * * 5 (compiler determines)
    • weekly on monday around 09:00 → Scattered time within ±1 hour like 32 9 * * 1 (08:00-10:00)
    • weekly on friday around 5pm → Scattered time within ±1 hour like 18 16 * * 5 (16:00-18:00)
    • weekly on sunday around midnight → Scattered time within ±1 hour like 47 23 * * 0 (23:00-01:00)
    • With UTC offsets: weekly on monday around 08:00 utc+9 → Scattered around 11 PM UTC previous day
    • Supports all time formats: HH:MM, midnight, noon, Npm, Nam with optional UTC offsets
  • Weekly (Fixed): weekly on <day> at HH:MM or weekly on <day> at Npm/Nam
    • weekly on monday at 06:3030 6 * * 1 (⚠️ Warning: fixed time)
    • weekly on friday at 17:000 17 * * 5 (⚠️ Warning: fixed time)
    • weekly on friday at 5pm0 17 * * 5 (⚠️ Warning: fixed time)
  • Monthly: monthly on <day> or monthly on <day> at HH:MM or monthly on <day> at Npm/Nam
    • monthly on 15 at 09:000 9 15 * *
    • monthly on 10 0 1 * *
    • monthly on 15 at 9am0 9 15 * *
  • Intervals: every N minutes/hours or every Nm/Nh/Nd/Nw/Nmo (minimum 5 minutes)
    • every 10 minutes*/10 * * * * (minute intervals don’t scatter)
    • Hourly (Fuzzy): every 2h → Scattered minute like 53 */2 * * * (compiler determines)
    • Hourly (Fuzzy): every 1h → Scattered minute like 28 */1 * * * (compiler determines)
    • Hourly (Fixed): 0 */2 * * * → (⚠️ Warning: fixed minute offset)
    • every 1d0 0 * * *
    • every 1w0 0 * * 0
    • every 1mo0 0 1 * *
  • UTC Offsets: Add utc+N or utc-N or utc+HH:MM to convert from local time to UTC
    • daily at 02:00 utc+90 17 * * * (2 AM JST → 5 PM UTC previous day)
    • daily at 14:00 utc-50 19 * * * (2 PM EST → 7 PM UTC)
    • weekly on monday at 09:30 utc+05:300 4 * * 1 (9:30 AM IST → 4 AM UTC)
    • daily at 3pm utc+90 6 * * * (3 PM JST → 6 AM UTC)
  • Time Formats: HH:MM (24-hour), midnight, noon, Npm (1pm-12pm), Nam (1am-12am)
    • 12am = midnight (00:00)
    • 12pm = noon (12:00)
    • 1am = 01:00, 11pm = 23:00

The human-friendly format is automatically converted to standard cron expressions, with the original format preserved as a comment in the generated workflow file.

Standard Cron Format:

on:
schedule:
- cron: "0 9 * * 1" # Every Monday at 9 AM UTC
stop-after: "+7d" # Stop after a week

Trigger on issue events. Full event reference.

on:
issues:
types: [opened, edited, labeled]

Trigger on pull request events. Full event reference.

on:
pull_request:
types: [opened, synchronize, labeled]
names: [ready-for-review, needs-review]
reaction: "rocket"

Pull request workflows block forks by default for security. Use the forks: field to allow specific fork patterns:

on:
pull_request:
types: [opened, synchronize]
forks: ["trusted-org/*"] # Allow forks from trusted-org

Available patterns:

  • ["*"] - Allow all forks (use with caution)
  • ["owner/*"] - Allow forks from specific organization or user
  • ["owner/repo"] - Allow specific repository
  • Omit forks field - Default behavior (same-repository PRs only)

The compiler uses repository ID comparison for reliable fork detection that is not affected by repository renames. See the Security Guide for detailed security implications.

on:
issue_comment:
types: [created]
pull_request_review_comment:
types: [created]
discussion_comment:
types: [created]
reaction: "eyes"

Trigger workflows after another workflow completes. Full event reference.

on:
workflow_run:
workflows: ["CI"]
types: [completed]
branches:
- main
- develop

Workflows with workflow_run triggers include automatic security protections:

Automatic repository and fork validation: The compiler automatically injects repository ID and fork checks to prevent cross-repository attacks and fork execution. This safety condition ensures workflows only execute when triggered by workflow runs from the same repository and not from forked repositories.

Branch restrictions required: Include branches to limit which branch workflows can trigger the event. Without branch restrictions, the compiler emits warnings (or errors in strict mode). This prevents unexpected execution for workflow runs on all branches.

See the Security Guide for detailed security behavior and implementation.

The slash_command: trigger creates workflows that respond to /command-name mentions in issues, pull requests, and comments. See Command Triggers for complete documentation.

Basic Configuration:

on:
slash_command:
name: my-bot

Shorthand Format:

on:
slash_command: "my-bot"

With Event Filtering:

on:
slash_command:
name: summarize
events: [issues, issue_comment] # Only in issue bodies and comments

Complete Workflow Example:

---
on:
slash_command:
name: code-review
events: [pull_request, pull_request_comment]
permissions:
contents: read
pull-requests: write
tools:
github:
toolsets: [pull_requests]
safe-outputs:
add-comment:
max: 5
timeout-minutes: 10
---
# Code Review Assistant
When someone mentions /code-review in a pull request or PR comment,
analyze the code changes and provide detailed feedback.
The current context is: "${{ needs.activation.outputs.text }}"
Review the pull request changes and add helpful review comments on specific
lines of code where improvements can be made.

The command must appear as the first word in the comment or body text. Command workflows automatically add the “eyes” (👀) reaction and edit comments with workflow run links.

An additional kind of issue and pull request trigger is available in GitHub Agentic Workflows to specific label names using the names: field:

on:
issues:
types: [labeled, unlabeled]
names: [bug, critical, security]

This filtering is especially useful for LabelOps workflows where specific labels trigger different automation behaviors.

An additional option reaction: is available within the on: section to enable emoji reactions on the triggering GitHub item (issue, PR, comment, discussion) to provide visual feedback about the workflow status:

on:
issues:
types: [opened]
reaction: "eyes"

The reaction is added to the triggering item. For issues/PRs, a comment with the workflow run link is also created. For comment events in command workflows, the comment is edited to include the run link.

Available reactions: +1 👍, -1 👎, laugh 😄, confused 😕, heart ❤️, hooray 🎉, rocket 🚀, eyes 👀

Job outputs (add_reaction): reaction_id, comment_id (issues/PRs only), comment_url (issues/PRs only)

Automatically disable workflow triggering after a deadline to control costs.

on:
schedule:
- cron: "0 9 * * 1"
stop-after: "+25h" # 25 hours from compilation time

Accepts absolute dates (YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY, January 2 2006, 1st June 2025, ISO 8601) or relative deltas (+7d, +25h, +1d12h30m) calculated from compilation time. The minimum granularity is hours - minute-only units (e.g., +30m) are not allowed. Recompiling the workflow resets the stop time.

Require manual approval before workflow execution using GitHub environment protection rules:

on:
workflow_dispatch:
manual-approval: production

The manual-approval field sets the environment on the activation job, enabling manual approval gates configured in repository or organization settings. This provides human-in-the-loop control for sensitive operations.

The field accepts a string environment name that must match a configured environment in the repository. Configure approval rules, required reviewers, and wait timers in repository Settings → Environments. See GitHub’s environment documentation for environment configuration details.

Conditionally skip workflow execution when a GitHub search query has matches. Useful for preventing duplicate scheduled runs or waiting for prerequisites.

Basic Usage (String Format):

on:
schedule:
- cron: "0 13 * * 1-5"
skip-if-match: 'is:issue is:open in:title "[daily-report]"'

Advanced Usage (Object Format with Threshold):

on:
schedule:
- cron: "0 9 * * 1"
skip-if-match:
query: "is:pr is:open label:urgent"
max: 3 # Skip if 3 or more PRs match

How it works:

  1. A pre-activation check runs the search query against the current repository
  2. If the number of matches reaches or exceeds the threshold, the workflow is skipped
  3. The query is automatically scoped to the current repository
  4. String format implies max: 1 (skip if any matches found)

Common Use Cases:

Prevent duplicate scheduled reports:

on:
schedule:
- cron: "0 9 * * 1"
skip-if-match: 'is:issue is:open label:weekly-summary'

Wait for deployment PRs to close:

on:
workflow_dispatch:
skip-if-match: "is:pr is:open label:deployment"

Skip if processing queue is full (3+ items):

on:
schedule:
- cron: "0 */6 * * *"
skip-if-match:
query: "is:issue is:open label:needs-processing"
max: 3

The search uses GitHub’s issue/PR search API with efficient per_page=1 query. Supports all standard GitHub search qualifiers (is:, label:, in:title, author:, etc.).