Until now, every workflow we've discussed is manually invoked — you type a command and the agent runs. That's powerful, but it's only half the picture. The real shift happens when agents react to events without you asking.
This lesson covers the on: frontmatter section — the declarative syntax that tells a workflow when to activate. If you've used GitHub Actions, this will feel familiar. The difference: instead of triggering a CI pipeline, you're triggering an AI agent.
on: SectionEvery agentic workflow file has YAML frontmatter at the top. The on: key declares the trigger — what event or condition causes the workflow to fire:
---
on:
issues:
types: [opened]
safe-outputs:
add-comment:
---
# Auto-Triage New Issues
Read the issue title and body. Assign appropriate labels based on content.
Add a comment acknowledging receipt and estimated triage time.
This workflow fires every time a new issue is opened. No human invocation needed. The agent reads, labels, and responds — all from a single trigger declaration.
Triggers fall into four categories. Most workflows use one; complex workflows combine several.
Fire when something happens in your repository: an issue opens, a PR is created, a comment is posted, a label is applied.
These are the workhorses of agentic automation. They turn your agent into a team member that monitors and responds.
Fire at regular intervals: daily, weekly, every 30 minutes, or at a specific cron time. Use for maintenance tasks, reports, and periodic sweeps.
Supports both standard cron syntax and human-friendly "fuzzy" expressions.
Fire when explicitly invoked via the GitHub UI, CLI (gh aw run), or API. Can accept typed input parameters (strings, booleans, dropdowns).
Use for workflows that need human judgment about when or what to run on.
Fire when someone types /command-name in an issue or PR comment. This is the ChatOps pattern — triggering agent work through conversation.
Enables team members to invoke complex workflows without leaving their issue thread.
Event triggers use standard GitHub webhook event names with optional types: filtering:
# React to new and edited issues
on:
issues:
types: [opened, edited, labeled]
# React to PR creation and new commits
on:
pull_request:
types: [opened, synchronize]
# React to comments (ChatOps pattern)
on:
issue_comment:
types: [created]
# React to new discussions
on:
discussion:
types: [created]
The types: array lets you be precise. Without it, the workflow fires on every event type — which is usually too broad. Always specify types.
GitHub fires issue_comment events for comments on both issues and pull requests. When triggered by a PR comment, the agent gets access to the PR branch. This is what makes ChatOps patterns work for code review.
Schedule triggers support two syntaxes: human-friendly fuzzy expressions and standard cron.
Fuzzy schedules are easier to read and automatically scatter execution times to avoid load spikes:
# Simple intervals
on:
schedule: daily
schedule: weekly on monday
schedule: hourly
schedule: every 30 minutes
# With time preferences
on:
schedule: daily around 14:00 # ±1 hour around 2pm UTC
schedule: daily between 9:00 and 17:00 # Scattered within business hours
schedule: weekly on friday around 5pm
# With timezone offsets
on:
schedule: daily between 9am and 5pm utc-5 # Eastern time business hours
The compiler converts these to deterministic cron expressions based on the workflow's file path — so the same workflow always runs at the same time, but different workflows scatter naturally.
For exact timing, use cron directly:
on:
schedule:
- cron: "0 9 * * 1-5" # 9:00 UTC weekdays
- cron: "30 6 * * 1" # Monday at 06:30 UTC
- cron: "0 9 15 * *" # 15th of month at 09:00 UTC
timezone: "America/New_York" # IANA timezone override
workflow_dispatch)Manual triggers let you define input parameters the user provides when invoking the workflow:
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
Access inputs in your prompt with template syntax: ${{ github.event.inputs.topic }}
This is the bridge between "fully manual" and "fully automatic." You decide when to run it, but the workflow handles the how.
slash_command)Command triggers turn issue comments into agent invocations:
on:
slash_command:
name: investigate
events: [issues, issue_comment]
Now, when anyone types /investigate in an issue comment, the workflow fires with the full issue context. This is the ChatOps pattern — your team interacts with the agent through normal GitHub conversations.
Use cases:
/investigate — Deep-dive into a reported bug/deploy staging — Trigger a deployment/summarize — Generate a summary of a long thread/comply — Run compliance checks on demandA single workflow can respond to multiple triggers. This is common — you want something to run both automatically and on-demand:
on:
# Fire automatically on new issues
issues:
types: [opened]
# Also allow manual invocation for testing
workflow_dispatch:
# And fire on a schedule for catch-up
schedule: daily around 9:00
The workflow runs identically regardless of which trigger fired. This makes testing easy — use workflow_dispatch during development, then let the event triggers handle production.
| Pattern | Trigger Config | What It Enables |
|---|---|---|
| Auto-triage | issues: [opened] |
Label, assign, and acknowledge new issues instantly |
| PR review | pull_request: [opened, synchronize] |
Automated code review on every push |
| ChatOps | slash_command: name: fix |
Team invokes agent via /fix in comments |
| Daily report | schedule: daily around 9:00 |
Stale PR sweep, metrics digest, dependency check |
| CI follow-up | workflow_run: [completed] |
Agent analyzes failures after CI finishes |
| Label-as-command | label_command: deploy |
Apply "deploy" label → agent deploys, removes label |
| External webhook | repository_dispatch: [jira-created] |
Jira/PagerDuty/Slack triggers agent work |
| On-demand + auto | issues: [opened] + workflow_dispatch: |
Automatic in production, manual for testing |
Let's build a complete auto-triage workflow. This is one of the most impactful first automations — it gives every issue reporter instant acknowledgment and applies initial labels:
---
on:
issues:
types: [opened]
reaction: "eyes"
safe-outputs:
add-comment:
add-labels:
permissions:
issues: write
---
# Auto-Triage New Issues
You are a triage agent for this repository.
## Context
Read the issue: "${{ github.event.issue.title }}"
Body:
${{ github.event.issue.body }}
## Task
1. Analyze the issue content and determine:
- Is this a bug report, feature request, question, or documentation issue?
- What area of the codebase does it relate to?
- What priority level seems appropriate (critical, high, medium, low)?
2. Apply labels:
- One type label: `bug`, `enhancement`, `question`, or `documentation`
- One area label if identifiable: `area/api`, `area/ui`, `area/infra`, etc.
- One priority label: `priority/critical`, `priority/high`, `priority/medium`, `priority/low`
3. Add a comment:
- Acknowledge the issue
- Summarize your understanding
- Note any missing information needed for triage
- Be friendly and concise
This workflow activates the moment an issue is created. The reaction: "eyes" immediately adds an 👀 emoji so the reporter knows something is happening. Within seconds, the issue has labels and a helpful comment.
Think about your existing /comply workflow. Right now, it's Layer 2 — a manually invoked command. You type it, it runs. But what if it fired automatically?
---
on:
workflow_dispatch:
---
# Compliance Check
Run compliance checks...
---
on:
pull_request:
types: [opened, synchronize]
workflow_dispatch:
---
# Compliance Check
Run compliance checks...
One line changes the trigger from "when I ask" to "when any PR is opened or updated." The workflow body stays identical. The agent's behavior doesn't change — only when it activates. This is the power of declarative triggers: you graduate workflows from manual to automatic by editing frontmatter, not rewriting logic.
Manual → Event-driven → Scheduled → Combined. Start with workflow_dispatch to build and test. Add event triggers once you trust the output. Add schedule triggers for catch-up sweeps. This is how you safely increase autonomy.
For common patterns, the gh-aw compiler accepts natural-language shorthand instead of full YAML:
# These are equivalent:
on: issue opened
on:
issues:
types: [opened]
# More shorthand examples:
on: pull_request opened
on: issue labeled bug
on: manual
on: manual with input version
on: comment created
on: "deployment failed"
Shorthands are useful for simple, single-trigger workflows. Use full YAML when combining triggers or adding filtering options.
issues event with type opened. The edited type fires when the issue body or title is changed later. issue_comment is for comments, not issue creation.issues event with type opened. The edited type fires on title/body changes. issue_comment fires when a comment is posted. pull_request is for PRs, not issues.daily between 9:00 and 10:00 scatters execution within that window and is the recommended approach when you want "roughly around 9 AM" without load-spike concerns. Combine with an if: weekday condition or use cron: "0 9 * * 1-5" for exact-time weekday-only execution."0 9 * * 1-5" would give you exact 9:00 UTC weekdays — but the question asked for flexibility. Fuzzy syntax like daily between 9:00 and 10:00 scatters within the window, which is the "flexible timing" approach. every 24 hours runs every day including weekends. weekly on monday only runs once a week.slash_command:) enable that event triggers alone cannot?/command-name in a comment and the agent activates in that conversational context. This is uniquely interactive: the team works with the agent through normal GitHub conversation./command-name in issue or PR comments. Schedule triggers handle timers. workflow_dispatch handles typed inputs. repository_dispatch handles external system integration.You now understand the four trigger types and how to declare them. The next lesson covers safe outputs — controlling what an event-triggered agent is allowed to do. Because once an agent activates autonomously, the guardrails matter more than ever.
Frontmatter (Triggers) — GitHub Agentic Workflows reference. Complete syntax for all trigger types, filtering options, and advanced features like lock-for-agent and skip-if-match.
on: configuration for a specific workflow you're imagining, or explain how triggers interact with the safety layers from Lesson 1.