Documents
GitHub Agentic Workflows
GitHub Agentic Workflows
Type
Topic
Status
Published
Created
Apr 22, 2026
Updated
Apr 22, 2026
Created by
Dosu Bot
Updated by
Dosu Bot

GitHub Agentic Workflows (gh-aw)#

GitHub Agentic Workflows (gh-aw) is a framework for running AI coding agents—Claude, GitHub Copilot CLI, Codex, Gemini, Crush, or OpenCode—inside GitHub Actions from declarative Markdown configuration. Unlike fixed if-then automation, agents read natural language instructions and make context-aware decisions: reading threads end-to-end, ranking issues by engagement, and drafting tailored comments rather than applying a uniform template.

In better-stale-bot, the two files that matter are better-stale-bot.md (the editable source) and its compiled counterpart better-stale-bot.lock.yml (machine-generated, do not hand-edit).

Official documentation:

Installing better-stale-bot#

Recommended: Use the interactive add-wizard (simplest approach):

# 1. Authenticate with GitHub
gh auth login

# 2. Install the gh-aw CLI extension
gh extension install github/gh-aw

# 3. Add the workflow (interactive — sets secret, adds workflow, opens a PR; may need to manually merge the PR)
gh aw add-wizard dosu-ai/better-stale-bot/better-stale-bot

# Optional: skip secret configuration
# gh aw add-wizard dosu-ai/better-stale-bot/better-stale-bot --skip-secret

# 4. Pull locally
git pull

The add-wizard command walks you through setup step-by-step: checks requirements, prompts for missing secrets, downloads the workflow file from the workflows/ directory (not .github/workflows/—the latter is for live/testing in template repositories), compiles it to YAML, and opens a pull request. You may need to manually merge the PR it creates.

Alternative: Manual installation:

# 1. Install gh-aw
gh auth login
gh extension install github/gh-aw

# 2. Add your engine secret in repo Settings → Secrets and variables → Actions
# (ANTHROPIC_API_KEY for Claude, COPILOT_GITHUB_TOKEN for Copilot, OPENAI_API_KEY for Codex)

# 3. Download, compile, and push
mkdir -p .github/workflows
curl -o .github/workflows/better-stale-bot.md \
  https://raw.githubusercontent.com/dosu-ai/better-stale-bot/main/workflows/better-stale-bot.md
gh aw compile better-stale-bot
git add .github/ .gitattributes
git commit -m "Add better-stale-bot workflow"
git push

# 4. Run
gh aw run better-stale-bot

Key Features#

  • Natural Language Workflows — Markdown + YAML frontmatter
  • AI Engine Support — Copilot, Claude, Codex, Gemini, Crush, OpenCode, or custom
  • MCP Server Integration — Tool-based execution with Model Context Protocol
  • Safe Outputs — Declarative, constrained write operations with hard limits
  • Strict Mode — Security-first validation and sandboxing
  • Shared Components — Reusable workflow building blocks
  • Repo Memory — Persistent git-backed storage for agents via cache-memory

Creating Workflows#

There are four ways to author gh-aw workflows:

  1. GitHub Web Interface — Use Copilot on github.com with prompts like "Create a workflow for GitHub Agentic Workflows using https://raw.githubusercontent.com/github/gh-aw/main/create.md" (requires gh aw init first to set up the dispatcher agent).

  2. VSCode/Claude/Codex/Copilot — Interactive coding agent conversation in your editor.

  3. Manual Editing — Create a .md file manually in .github/workflows/, compile with gh aw compile, commit both .md and .lock.yml files.

  4. Adding existing workflows — Use gh aw add <owner/repo/workflow-name> to import workflows from other repositories.

Using the GitHub Web Interface: After running gh aw init, the command creates a dispatcher agent at .github/agents/agentic-workflows.agent.md, sets up MCP integration, and updates .gitattributes. You can then create workflows via /agent agentic-workflows in Copilot Chat on github.com.

create.md action router: The create.md prompt routes to different specialized prompt files:

  • Create new workflow → .github/aw/create-agentic-workflow.md
  • Update existing workflow → .github/aw/update-agentic-workflow.md
  • Debug workflow → .github/aw/debug-agentic-workflow.md
  • Upgrade workflows → .github/aw/upgrade-agentic-workflows.md
  • Create shared workflow → .github/aw/create-shared-agentic-workflow.md

Security Architecture: Five Layers of Defense#

gh-aw implements defense-in-depth with five security layers:

  1. Read-only tokens — The AI agent receives a GitHub token scoped to read-only permissions. It can observe the repository but cannot change it.
  2. Zero secrets in the agent — The agent process never receives write tokens, API keys, or other sensitive credentials. Secrets exist only in separate, isolated jobs that run after the agent finishes.
  3. Containerized with network firewall — The agent runs in an isolated container with an Agent Workflow Firewall (AWF) routing all outbound traffic through a Squid proxy with an explicit domain allowlist.
  4. Safe outputs with strong guardrails — The agent cannot write to GitHub directly. It produces a structured artifact describing intended actions. A separate gated job with scoped write permissions applies only what the workflow permits (hard limits per operation, required title prefixes, label constraints).
  5. Agentic threat detection — Before any output is applied, a dedicated threat detection job runs an AI-powered scan checking for prompt injection attacks, leaked credentials, and malicious code patterns.

Workflow Structure: Declarative Markdown + YAML Frontmatter#

Each workflow is a single Markdown file with two parts:

  1. YAML frontmatter (between --- delimiters) — configures triggers, engine, permissions, tools, and safe-output caps.
  2. Markdown body — natural language instructions the AI agent receives at runtime.

The frontmatter block in better-stale-bot.md illustrates all major keys:

KeyPurpose
descriptionHuman-readable summary embedded in the compiled workflow
on: schedule: dailyTrigger; compiled to a scattered cron (e.g., 52 10 * * *)
engine: { id: claude, model: haiku }AI model selection with explicit model; determines which API secret is required; note: an invalid model slug may be resolved to the provider's default model—verify the actual model used via GitHub Actions → Agent Summary → Token Usage. Specifying engine: claude defaults to Sonnet; better-stale-bot uses engine: { id: claude, model: haiku }
permissions: contents: read, issues: readMinimal read-only GitHub permissions for the agent job
tools.github.toolsets: [issues]Scopes the GitHub MCP server to the issues toolset only
cache-memory: trueEnables cross-run file persistence in /tmp/gh-aw/cache-memory/
safe-outputsDeclares allowed write operations with per-type caps and allowlists

The markdown body is injected into the agent prompt at runtime via {{#runtime-import .github/workflows/better-stale-bot.md}} , so instruction-only edits (changes to the markdown body) take effect on the next run without recompilation—only frontmatter edits (engine, permissions, safe-outputs, schedule, tools) require gh aw compile. Policy settings like days-before-stale, days-before-close, exempt labels, and instruction logic are in the markdown body and can be changed without recompilation.

The Compile Step#

gh aw compile better-stale-bot

gh aw compile transforms the .md source into a hardened .lock.yml GitHub Actions workflow. The lock file header records the schema version, a hash of the frontmatter, the compiler version (v0.68.1), and the resolved agent model. All referenced GitHub Actions are pinned to exact commit SHAs .

When to recompile: Any edit to the YAML frontmatter—engine, permissions, safe-output caps, schedule, tools—requires recompiling. Edits to the markdown body (instructions, configuration table) take effect on the next run without recompiling.

Compile options: Use gh aw compile --strict for strict mode validation (recommended for production) or gh aw compile --purge to remove stale lock files.

After compilation, commit both files:

git add .github/ .gitattributes

Important: When setting up any gh-aw workflow, .gitattributes must contain:

.github/workflows/*.lock.yml linguist-generated=true merge=ours

This marks lock files as generated (hides them in diffs) and uses ours merge strategy to avoid merge conflicts.

Note: If there is branch protection on the default branch, create a pull request instead of pushing directly when setting up the workflow.

Safe Outputs: Constrained Write Operations#

The AI agent runs with read-only GitHub permissions. All writes are declared upfront as safe-outputs in the frontmatter and enforced by the framework. The agent never writes directly to GitHub; it emits structured JSONL which a separate job applies only after threat detection passes.

The better-stale-bot safe-outputs config:

safe-outputs:
  add-comment:
    max: 30
  add-labels:
    max: 30
    allowed: ["Stale"]
  remove-labels:
    max: 30
    allowed: ["Stale"]
  close-issue:
    max: 30
  noop:
    report-as-issue: false

Key constraints enforced at runtime :

  • max: — per-run cap per output type, enforced independently; exceeding it is rejected, not silently dropped.
  • allowed: on label operations — the agent can only add/remove labels in the allowlist; attempts to use other labels are blocked.
  • noop — a special output that records "nothing to do"; by default opens a tracking issue titled "[aw] No-Op Runs" to report when the agent found no work. Set report-as-issue: false to suppress this issue.

After changing max: values, rerun gh aw compile.

See the Safe Outputs Reference for the full list of constraints (text sanitization, HTTPS-only URLs, domain allowlisting, bot-mention redaction, etc.).

Threat Detection#

Before safe outputs are applied, a dedicated detection job runs a second AI pass against the agent's proposed outputs. It has no MCP connections—only read access to the prompt and output files—and checks for prompt injection, data exfiltration, or policy violations.

The safe_outputs job has an explicit dependency on detection success :

safe_outputs:
  needs: [activation, agent, detection]
  if: (!cancelled()) && needs.agent.result != 'skipped' && needs.detection.result == 'success'

The detection agent runs with a restricted tool setBash, Grep, Read, LS, Glob only; no MCP or write tools—inside the same sandboxed awf container with network firewall enabled.

Cache Memory#

Enabling cache-memory: true in the frontmatter gives the agent a persistent file share at /tmp/gh-aw/cache-memory/ that survives across runs via GitHub Actions Cache. This step stores a short run summary between runs, allowing instructions to tell the agent to read it at the start of later runs to avoid blind reprocessing.

How it works:

  1. The agent job restores the cache keyed by memory-none-nopolicy-{workflowId}-{run_id}, using a prefix fallback to pick up the most recent prior run.
  2. The agent reads and writes files in /tmp/gh-aw/cache-memory/ using standard filesystem tools (Read, Write, Edit restricted to that path).
  3. After the run, the update_cache_memory job saves the updated directory back to the cache.

In better-stale-bot: Step 5 instructs the agent to write a JSON run summary to /tmp/gh-aw/cache-memory/stale-bot-state.json (date, issues labeled/closed/un-staled, using filesystem-safe timestamps). On the next run, Step 1 tells the agent to read this file to avoid reprocessing recently handled issues.

Execution Pipeline#

The compiled lock file defines five jobs with an explicit dependency order :

activation → agent → detection ──────┐
                  └─ update_cache_memory
                                 safe_outputs → conclusion
JobRunnerKey responsibilities
activationubuntu-slimValidates secrets, checks lock-file integrity, builds the prompt (injects frontmatter context + runtime-imports the .md body), uploads activation artifact
agentubuntu-latestInstalls the AI CLI (e.g., Claude Code @2.1.98), starts MCP Gateway + Safe Outputs MCP Server, runs the agent inside awf sandbox with network firewall; emits safe-output JSONL
detectionubuntu-latestRe-runs AI in read-only mode against agent outputs to detect prompt injection or policy violations
update_cache_memoryubuntu-slimSaves /tmp/gh-aw/cache-memory/ back to GitHub Actions Cache
safe_outputsubuntu-slimApplies validated writes to GitHub (comments, labels, issue closures) only if detection succeeded
conclusionubuntu-slimHandles noop tracking issues, missing-tool reports, and agent failure notifications

The agent runs inside the awf container with a strict network firewall (squid proxy, domain allowlist) and reads GitHub exclusively through the GitHub MCP Server (ghcr.io/github/github-mcp-server:v0.32.0) with GITHUB_READ_ONLY=1 enforced .

Observability: Run logs, token usage, safe-outputs JSONL, and firewall audit logs are uploaded as GitHub Actions artifacts on every run. Use gh aw logs and gh aw audit from a local clone for CLI access.

Billing and Cost: LLM usage is charged by the configured engine. Cost scales with model choice, context size, and the amount of work performed. To inspect usage, navigate to GitHub Actions → Agent Summary → Agentic Conversation and Token Usage. Use the gh aw logs and gh aw audit commands for deeper analysis.

Engine & Authentication Setup#

gh-aw supports six AI engines. Each requires a specific secret:

EngineEngine IDRequired SecretNotes
GitHub Copilot CLI (default)copilotCOPILOT_GITHUB_TOKENFine-grained PAT with Copilot Requests permission. Resource owner must be personal account, not org.
Claude (Claude Code)claudeANTHROPIC_API_KEYAPI key from Anthropic Console (https://platform.claude.com/docs/en/get-started). Use engine: claude to default to Sonnet, or engine: { id: claude, model: haiku } for explicit model selection.
OpenAI CodexcodexOPENAI_API_KEYRuntime uses CODEX_API_KEY if present, falls back to OPENAI_API_KEY. Use engine: codex for default model.
Google Gemini CLIgeminiGEMINI_API_KEYAPI key from Google AI Studio. Use engine: gemini for default model.
Crush (experimental)crushCOPILOT_GITHUB_TOKENSame token as Copilot
OpenCode (experimental)opencodeCOPILOT_GITHUB_TOKENSame token as Copilot

Choosing an engine: Copilot is the default choice for most users because it supports the broadest gh-aw feature set. Choose Claude when you want stronger control over turn limits (max-turns) for long reasoning sessions. Choose Gemini or Codex when those models are already part of existing tooling or budget decisions.

Setting secrets: Use the CLI: gh aw secrets set SECRET_NAME --value "YOUR_KEY" or add them via the GitHub UI. Check existing secrets with gh aw secrets bootstrap.

Extended engine configuration: Engines support version pinning, custom model override, custom executable path, custom CLI arguments, custom agent file (Copilot only), custom API endpoint (api-target for GHEC/GHES), custom driver script (Copilot only), and custom token weights.

Timeout configuration:

  • timeout-minutes: job-level wall clock (default 20 min, all engines)
  • tools.timeout: per tool-call limit in seconds (Claude default 60s, Codex default 120s)
  • max-turns: iteration budget (Claude only)
  • max-continuations: autopilot run budget (Copilot only)

Custom API endpoints: All engines support custom API endpoints via engine.env configuration (e.g., Azure OpenAI, corporate proxies).

GitHub App authentication: Also supported for enhanced security with short-lived tokens (does not apply to COPILOT_GITHUB_TOKEN which must be a PAT).

Common authentication errors:

  • 403 for Copilot: missing Copilot Requests permission
  • 401/403 for Claude: invalid ANTHROPIC_API_KEY
  • 401/403 for Codex: invalid OPENAI_API_KEY

CLI Commands Reference#

Installation:

  • gh extension install github/gh-aw — Standard installation
  • gh extension install github/gh-aw@v0.1.0 — Version pinned installation
  • Standalone installer: curl -sL https://raw.githubusercontent.com/github/gh-aw/main/install-gh-aw.sh | bash
  • GitHub Actions: uses: github/gh-aw/actions/setup-cli@main
  • GHES supported with GH_HOST environment variable
  • gh extension upgrade aw — Upgrade to latest version
  • gh aw version — Check installed version

Getting Workflows:

  • gh aw init — Initialize repository (creates .gitattributes, dispatcher agent file, MCP integration). Options: --no-mcp, --codespaces, --completions, --create-pull-request
  • gh aw add-wizard <ref> — Interactive guided setup. Accepts owner/repo/workflow-name format. Checks requirements, prompts for missing secrets
  • gh aw add <ref> — Non-interactive add. Supports @version pinning
  • gh aw new [name] — Create workflow template. --force to overwrite, --engine to inject engine
  • gh aw secrets set <name> — Create/update repository secret (from stdin, --value flag, or --value-from-env)
  • gh aw secrets bootstrap — Analyze workflows, detect required secrets, interactively prompt for missing ones

Building:

  • gh aw fix — Auto-fix deprecated fields. Dry-run by default, --write to apply. --list-codemods to see available fixes
  • gh aw compile [workflow-name] — Compile workflows. Key flags: --watch, --validate, --strict, --zizmor (security scan), --purge, --dependabot, --approve (for new secrets/actions)
  • gh aw validate — Validate without generating lock files (equivalent to compile --validate --no-emit --zizmor --actionlint --poutine)

Testing:

  • gh aw trial <ref> — Test in temporary private repos or specific repos with --host-repo

Monitoring:

  • gh aw list — Quick listing without GitHub API queries. Supports --json, --label filter
  • gh aw status — Detailed status with enabled/disabled state, schedules, run info (with --ref)
  • gh aw logs [workflow-name] — Download and analyze logs with tool usage, network patterns, errors. Cached for speedup. Accepts workflow IDs or display names (case-insensitive). Has --train flag for anomaly detection weights
  • gh aw audit — Rich multi-section reports. 3 modes: single-run audit, cross-run diff, cross-run security report. Accepts run IDs, workflow URLs, job URLs, step URLs
  • gh aw health — Success rates, trends (↑ improving, → stable, ↓ degrading), costs, alerts
  • gh aw checks <pr-number> — Classify CI check state for a PR

Management:

  • gh aw enable/disable — Enable/disable workflows (disable also cancels in-progress runs)
  • gh aw remove — Remove workflows (both .md and .lock.yml). Accepts prefix patterns
  • gh aw update — Update workflows from source field. 3-way merge preserves local changes. --no-merge to override with upstream
  • gh aw upgrade — Upgrade repository agent files and apply codemods. --audit for dependency health audit

Advanced:

  • gh aw mcp — Manage MCP servers (list, list-tools, inspect, add)
  • gh aw mcp inspect — Inspect configured MCP servers
  • gh aw pr transfer — Transfer PR to another repository
  • gh aw mcp-server — Run MCP server exposing gh-aw commands as tools
  • gh aw domains — List network domains configured in workflows

Utility:

  • gh aw completion — Shell completions (bash, zsh, fish, powershell)
  • gh aw hash-frontmatter — Compute deterministic SHA-256 hash of workflow frontmatter

Debugging tip: Use DEBUG=* gh aw compile for all logs or DEBUG=cli:* gh aw compile for CLI-only logs.

Note: Workflow name matching is fuzzy—the CLI auto-suggests similar names on typos.

Check token usage at: GitHub Actions → Agent Summary → Token Usage

GitHub Agentic Workflows | Dosu