GitHub Agentic Workflows

Common Issues

Frequently encountered issues, organized by workflow stage and component.

If gh extension install github/gh-aw fails, use the standalone installer (works in Codespaces and restricted networks). Pass a tag as the second argument to pin a version (releases). Verify with gh extension list.

Terminal window
curl -sL https://raw.githubusercontent.com/github/gh-aw/main/install-gh-aw.sh | bash
curl -sL https://raw.githubusercontent.com/github/gh-aw/main/install-gh-aw.sh | bash -s -- v0.40.0

Custom Actions Not Allowed in Enterprise Organizations

Section titled “Custom Actions Not Allowed in Enterprise Organizations”

Error: The action github/gh-aw/actions/setup@... is not allowed in {ORG} because all actions must be from a repository owned by your enterprise, created by GitHub, or verified in the GitHub Marketplace.

Cause: Enterprise policies restrict which GitHub Actions can be used.

Solution: An admin must add github/gh-aw@* to the organization’s allowed actions, either through Settings → Actions → Policies → “Allow select actions and reusable workflows” (docs), or by editing a centralized policies/actions.yml:

allowed_actions:
- "actions/*"
- "github/gh-aw@*"

Wait a few minutes for policy propagation, then re-run.

The CLI validates three permission layers. Fix restrictions in Repository Settings → Actions → General:

  1. Actions disabled: Enable Actions (docs)
  2. Local-only: Switch to “Allow all actions” or enable GitHub-created actions (docs)
  3. Selective allowlist: Enable “Allow actions created by GitHub” checkbox (docs)

If a frontmatter setting appears to be silently ignored, the field name may be misspelled. The compiler does not warn about unknown field names — they are silently discarded.

  • Won’t compile: check YAML syntax (indentation, colons with spaces), required fields (on:), and types against the schema; use gh aw compile --verbose.
  • Lock file not generated: fix errors (gh aw compile 2>&1 | grep -i error) and check write permissions on .github/workflows/.
  • Orphaned lock files: clear stale .lock.yml files with gh aw compile --purge after deleting .md workflows.
  • Import file not found: import paths are relative to the repository root (e.g., .github/workflows/shared/tools.md); verify with git status.
  • Multiple agent files error: import only one .github/agents/ file per workflow.
  • Circular dependencies: compilation hangs indicate circular imports — remove the circular reference.

Configure using toolsets: (tools reference):

tools:
github:
toolsets: [repos, issues]

Check GitHub Toolsets, combine toolsets (toolsets: [default, actions]), or inspect with gh aw mcp inspect <workflow>.

Verify package installation, syntax, and environment variables:

mcp-servers:
my-server:
command: "npx"
args: ["@myorg/mcp-server"]
env:
API_KEY: "${{ secrets.MCP_API_KEY }}"

When integrating OpenCode-compatible engines (such as crush), runs can complete without ever invoking MCP or file tools. Use this .crush.json. Port 10004 is the local AWF API proxy port (with --enable-api-proxy); MCP_GATEWAY_PORT and MCP_GATEWAY_API_KEY are expanded from workflow env at runtime (substitute concrete values when running outside a workflow):

{
"provider": {
"copilot-proxy": {
"name": "Copilot Proxy",
"type": "openai-compatible",
"baseURL": "http://host.docker.internal:10004",
"models": ["gpt-4.1", "claude-sonnet-4-6"]
}
},
"model": "copilot-proxy/claude-sonnet-4-6",
"mcp": {
"safeoutputs": {
"type": "http",
"url": "http://host.docker.internal:${MCP_GATEWAY_PORT}/mcp/safeoutputs",
"headers": { "Authorization": "${MCP_GATEWAY_API_KEY}" },
"disabled": false,
"timeout": 30000
}
},
"agent": {
"build": {
"permission": {
"bash": "allow", "edit": "allow", "read": "allow",
"glob": "allow", "grep": "allow", "write": "allow",
"external_directory": "allow"
}
}
}
}

Key gotchas:

  • Crush/OpenCode does not auto-discover MCP servers — declare an explicit top-level mcp block with routed URLs (http://host.docker.internal:${MCP_GATEWAY_PORT}/mcp/<server-name>).
  • Use agent.build.permission (singular) — permissions is silently ignored, leaving tools unavailable.
  • external_directory defaults to ask in non-interactive mode, which becomes an implicit deny. Set it to allow only when access outside the workspace (e.g., /tmp, mounted dirs) is required.
  • For direct Copilot endpoints (api.githubcopilot.com), do not append /v1. For other OpenAI-compatible providers, use the provider’s documented base path so /chat/completions is appended correctly. Keep the local proxy URL (http://host.docker.internal:10004) as-is.
  • When using --enable-api-proxy, pass COPILOT_GITHUB_TOKEN in the execute step’s env: so the proxy can authenticate:
- name: Execute
env:
COPILOT_GITHUB_TOKEN: ${{ steps.copilot-token.outputs.token }}
run: |
awf --enable-api-proxy <workflow-args> -- crush run "<prompt>"

Add domains to network.allowed:

network:
allowed:
- github.com
- "*.github.io"

Error: Cannot find module 'playwright' — Playwright is provided as MCP tools, not as an npm package. Use the MCP tools instead of require('playwright'):

// ✗ Don't: const playwright = require('playwright')
// ✓ Do: use MCP tools
await mcp__playwright__browser_navigate({ url: "https://example.com" });
await mcp__playwright__browser_snapshot();

See Playwright Tool documentation for all available tools.

Playwright MCP Initialization Failure (EOF Error)

Section titled “Playwright MCP Initialization Failure (EOF Error)”

Failed to register tools error="initialize: EOF" name=playwright — Chromium crashes before tool registration completes due to missing Docker security flags. Upgrade to 0.41.0+ with gh extension upgrade gh-aw.

All writes (issues, comments, PR updates) must go through the safe-outputs system — declare the types your workflow needs in frontmatter:

safe-outputs:
create-issue:
title-prefix: "[bot] "
labels: [automation]
add-comment: # no configuration required; uses defaults
update-issue: # no configuration required; uses defaults

If your operation isn’t in the Safe Outputs reference, it may not be supported yet. See the Safe Outputs Specification for the full list.

Disable staged mode:

safe-outputs:
staged: false
create-issue:
title-prefix: "[bot] "
labels: [automation]

GitHub Projects reserves field names like REPOSITORY. Use alternatives (repo, source_repository, linked_repo):

# ✗ Wrong: repository
# ✓ Correct: repo
safe-outputs:
update-project:
fields:
repo: "myorg/myrepo"

Delete conflicting fields in Projects UI and recreate.

  • Copilot CLI not found: verify compilation succeeded — compiled workflows include CLI installation steps.
  • Model not available: use the default (engine: copilot) or specify an available model (engine: {id: copilot, model: gpt-4}).

Copilot License or Inference Access Issues

Section titled “Copilot License or Inference Access Issues”

If a workflow fails at the Copilot inference step despite a correctly configured COPILOT_GITHUB_TOKEN (authentication or quota errors), the PAT owner may lack a valid Copilot license or inference access. Test locally with the Copilot CLI:

Terminal window
export COPILOT_GITHUB_TOKEN="<your-github-pat>"
copilot -p "write a haiku"

If this fails, contact your organization administrator to enable Copilot for the token owner.

Before running Copilot-based workflows on GHES, verify:

  • Site admin: GitHub Connect enabled (links GHES to github.com for Copilot cloud services), enterprise-level Copilot licensing activated, and outbound HTTPS allowed to api.githubcopilot.com and api.enterprise.githubcopilot.com.

  • Enterprise/org admin: a Copilot seat assigned to the COPILOT_GITHUB_TOKEN owner, and the org Copilot policy permits usage.

  • Workflow config:

    engine:
    id: copilot
    api-target: api.enterprise.githubcopilot.com
    network:
    allowed:
    - defaults
    - api.enterprise.githubcopilot.com

See Enterprise API Endpoint for GHEC/GHES api-target values.

ErrorCauseFix
Error loading models: 400 Bad RequestEnterprise Copilot not licensed or GitHub Connect not enabledEnable GitHub Connect and enterprise Copilot in site admin settings
403 "unauthorized: not licensed to use Copilot"No Copilot seat for PAT ownerSite admin enables Copilot; org admin assigns a seat to the token owner
403 "Resource not accessible by personal access token"Wrong token type or missing permissionsUse fine-grained PAT with Copilot Requests: Read, or classic PAT with copilot scope — see COPILOT_GITHUB_TOKEN
Could not resolve to a RepositoryGH_HOST not set in custom jobsRecompile (gh aw compile), or set GH_HOST=github.company.com explicitly for local CLI commands
Firewall blocking api.<ghes-host>Domain not in allowed listAdd to network.allowed (see below)
gh aw add-wizard creates PR on github.comNot inside a GHES repo cloneRun from within GHES repo, or use gh aw add + gh pr create

For firewall issues, add the GHES domain to your workflow’s allowed list:

engine:
id: copilot
api-target: api.company.ghe.com
network:
allowed:
- defaults
- company.ghe.com
- api.company.ghe.com
  • Unauthorized expression: use only allowed expressions (github.event.issue.number, github.repository, steps.sanitized.outputs.text). secrets.* and env.* are disallowed.
  • Sanitized context empty: steps.sanitized.outputs.text requires issue/PR/comment events (on: issues:), not push: or similar triggers.
  • Documentation build fails: clean install (cd docs && rm -rf node_modules package-lock.json && npm install && npm run build) and check for malformed frontmatter, MDX syntax errors, or broken links.
  • Tests failing after changes: run make fmt && make lint && make test-unit before iterating.

Add ecosystem identifiers (Network Configuration Guide):

network:
allowed:
- defaults # Infrastructure
- python # PyPI
- node # npm
- containers # Docker
- go # Go modules
  • URLs appearing as (redacted): add domains to the allowed list (Network Permissions) — e.g., allowed: [defaults, "api.example.com"].
  • Cannot download remote imports: verify network (curl -I https://raw.githubusercontent.com/github/gh-aw/main/README.md) and auth (gh auth status).
  • MCP server connection timeout: use local servers (command: "node", args: ["./server.js"]).
  • Cache not restoring: verify key patterns match (caches expire after 7 days) — cache: { key: deps-${{ hashFiles('package-lock.json') }}, restore-keys: deps- }.
  • Cache memory not persisting: configure the cache-memory MCP server — tools.cache-memory.key: memory-${{ github.workflow }}-${{ github.run_id }}.

Integrity Filtering Blocking Expected Content

Section titled “Integrity Filtering Blocking Expected Content”

On public repositories, min-integrity: approved is applied automatically — restricting agent visibility to content from owners, members, and collaborators. As a result, workflows can’t see issues, PRs, or comments from external contributors, and triage workflows don’t process community contributions.

To allow all contributors (only safe when the workflow validates input and uses restrictive safe outputs):

tools:
github:
min-integrity: none

Use min-integrity: unapproved as a middle ground for community triage workflows. See Integrity Filtering for details.

GitHub Actions marks the run as timed_out when the job exceeds timeout-minutes (default: 20 min). The table below maps each engine’s error patterns to the right fix; after updating frontmatter, recompile with gh aw compile. See Long Build Times for caching strategies and self-hosted runner recommendations.

EngineError PatternFix Setting
AllThe job has exceeded the maximum execution time of N minutestimeout-minutes: N in frontmatter
ClaudeBash tool timed out after 60 secondstools: timeout: N (default: 60s)
ClaudeReached maximum number of turns (N). Stopping.max-turns: N
CodexTool call timed out after 120 secondstools: timeout: N (default: 120s)
Copilot(task incomplete, workflow succeeds)max-continuations: N
AnyFailed to register tools error="initialize: timeout"tools: startup-timeout: N
timeout-minutes: 60 # job-level limit
tools:
timeout: 600 # per-tool-call limit (seconds)
startup-timeout: 300 # MCP server startup limit (seconds)
max-turns: 30 # Claude: max turns
max-continuations: 5 # Copilot: autopilot continuations

Common causes: missing tokens, permission mismatches, network restrictions, disabled tools, or rate limits. The fastest path is to ask an agent with the run URL — it audits logs, identifies the root cause, and suggests fixes.

Using Copilot Chat (requires agentic authoring setup):

/agent agentic-workflows debug https://github.com/OWNER/REPO/actions/runs/RUN_ID

Using any coding agent (no setup required):

Debug this workflow run using https://raw.githubusercontent.com/github/gh-aw/main/debug.md
The failed workflow run is at https://github.com/OWNER/REPO/actions/runs/RUN_ID

For manual investigation: gh aw audit <run-id>, gh aw logs, inspect .lock.yml. See the Debugging Workflows guide for a full walkthrough.

Enable verbose mode (--verbose), set ACTIONS_STEP_DEBUG = true, or inspect MCP config (gh aw mcp inspect). The DEBUG environment variable activates detailed internal logging for any gh aw command — output goes to stderr and each line shows the namespace (workflow:compiler), message, and time since the previous entry. Common namespaces: cli:compile_command, workflow:compiler, workflow:expression_extraction, parser:frontmatter. Wildcards match any suffix.

Terminal window
DEBUG=* gh aw compile # all logs
DEBUG=workflow:* gh aw compile my-workflow # specific package
DEBUG=workflow:*,cli:* gh aw compile my-workflow # multiple packages
DEBUG=*,-workflow:test gh aw compile my-workflow # exclude a logger
DEBUG_COLORS=0 DEBUG=* gh aw compile 2>&1 | tee debug.log # capture to file

See Workflow Health Monitoring Runbook for diagnosing errors.

Review reference docs, search existing issues, or create an issue. See Error Reference and Frontmatter Reference.