Question
Can GitHub Agentic Workflows (gh-aw) run on a custom/self-hosted runner, and if so, can Squad's gh-aw integration (workflows/squad.md, workflows/squad-implement-worker.md, workflows/shared/squad.md) run there too?
Answer
Yes to both — but Squad's shared bootstrap component has real gaps that need work before it's supported.
Part 1 — gh-aw supports custom runners
Confirmed against githubnext/gh-aw → docs/src/content/docs/reference/self-hosted-runners.md and docs/src/content/docs/reference/frontmatter.md.
runs-on: accepts all three GitHub Actions forms:
- String —
runs-on: self-hosted
- Array —
runs-on: [self-hosted, linux, x64] (runner must match all labels)
- Object —
runs-on: { group: my-runner-group, labels: [linux, x64] }
Runner scope knobs
| Field |
Controls |
Default |
runs-on: |
main agent job only |
ubuntu-latest |
runs-on-slim: |
all framework jobs (activation, pre-activation, safe-outputs, unlock, APM, cache memory) |
ubuntu-slim |
safe-outputs.runs-on: |
safe-output jobs (takes precedence over runs-on-slim) |
inherits |
safe-outputs.threat-detection.runs-on: |
threat-detection job |
agent job's runner |
aw.json → maintenance.runs_on |
every job in generated agentics-maintenance.yml |
ubuntu-slim |
Hard requirements
- Linux only.
macos-* ❌ (no nested virtualization for Docker), windows-* ❌.
- Working Docker daemon. MCP gateway and sandbox run as containers. Runner user must be in the
docker group or the socket must be world-readable.
- Node.js on
PATH for framework scripts. gh-aw auto-emits actions/setup-node (Node 24) when it detects a non-standard runner; pin explicitly with runtimes: { node: { version: '24' } }.
- Egress to
api.githubcopilot.com, github.com, ghcr.io, plus anything in network.allowed.
- ARC/Kubernetes: requires
containerMode.type="dind" (type="kubernetes" is unsupported) plus runner.topology: arc-dind in frontmatter. Split-daemon topologies may need GH_AW_DOCKER_SOCK_PATH / GH_AW_DOCKER_SOCK_GID.
- Rootless pods: if the cluster enforces
allowPrivilegeEscalation: false, the Copilot CLI install script needs --rootless so it installs to ~/.local/bin instead of /usr/local/bin.
Air-gapped / private cloud
.github/workflows/aw.json supports action_pins (remap owner/repo@ref → internal mirror) and container_pins (remap image + digest). Applied at compile time and baked into .lock.yml, so workflows never reach public registries at runtime. Neither is available in per-workflow frontmatter.
Part 2 — Squad-specific gaps
Four issues found in Squad's current gh-aw integration:
1. runs-on is not merged from imports
Per gh-aw's imports reference: "runs-on must be set in each workflow — it is not merged from imports."
Squad ships as imports: - shared/squad.md, so runs-on cannot be added to workflows/shared/squad.md. It has to live in each top-level workflow (workflows/squad.md, workflows/squad-implement-worker.md) or in a consumer-authored wrapper.
2. Bootstrap runs on the activation job, not the agent job
workflows/shared/squad.md runs npx --yes @bradygaster/squad-cli@$SQUAD_CLI_VERSION init inside jobs.activation.pre-steps — deliberately, so the npm install happens outside the agent's network firewall.
But activation is a framework job, so it obeys runs-on-slim, not runs-on. Setting runs-on: self-hosted alone leaves the Squad install running on a GitHub-hosted runner. Full isolation requires runs-on-slim: as well — and then the self-hosted runner needs Node on PATH and egress to registry.npmjs.org.
3. Hardcoded artifact action versions break GHES
workflows/shared/squad.md pins actions/upload-artifact@v7.0.1 and actions/download-artifact@v8.0.1 directly in its pre-steps / steps.
gh-aw's GHES compatibility mode ({"ghes": true} in aw.json, or gh aw compile --ghes) downgrades its own artifact steps to upload-artifact@v3.2.2 / download-artifact@v3.1.0, but it does not rewrite action references that Squad hardcoded. On GHES those v4+ actions fail with GHESNotSupportedError, so Squad's squad-state artifact handoff breaks — the agent job never receives .squad/ or .github/agents/squad.agent.md.
This is the most consequential gap and likely needs a fix in the shared component (e.g. aw.json action_pins, or version-selectable artifact steps).
4. Customizations get clobbered on update
gh aw add bradygaster/squad/workflows/squad.md@latest rewrites the source .md, so a hand-added runs-on: is lost on the next update. Consumers need a wrapper workflow instead.
Proposed consumer pattern
A thin wrapper in the consumer repo that remote-imports Squad's shared component, keeping runner config out of the file that gh aw add overwrites:
---
name: Squad
on:
slash_command:
name: squad
runs-on: [self-hosted, linux, x64]
runs-on-slim: [self-hosted, linux, x64]
runtimes:
node:
version: '24'
imports:
- bradygaster/squad/workflows/shared/squad.md@<40-char-sha>
safe-outputs:
runs-on: [self-hosted, linux, x64]
---
Air-gapped consumers additionally add action_pins + container_pins to .github/workflows/aw.json to mirror ghcr.io/github/gh-aw-firewall and the actions/* dependencies.
Validation status
Findings are documentation- and source-validated, not runtime-validated:
- ✅ gh-aw runner support verified against upstream docs (
self-hosted-runners.md, frontmatter.md, imports.md)
- ✅ Squad's activation-job bootstrap and hardcoded artifact pins read directly from
workflows/shared/squad.md
- ✅ Import-merge limitation confirmed in gh-aw's imports reference
- ❌ Wrapper workflow has not been compiled with
gh aw compile
- ❌ Nothing executed on an actual self-hosted runner or ARC cluster
Follow-up work
References
Question
Can GitHub Agentic Workflows (gh-aw) run on a custom/self-hosted runner, and if so, can Squad's gh-aw integration (
workflows/squad.md,workflows/squad-implement-worker.md,workflows/shared/squad.md) run there too?Answer
Yes to both — but Squad's shared bootstrap component has real gaps that need work before it's supported.
Part 1 — gh-aw supports custom runners
Confirmed against
githubnext/gh-aw→docs/src/content/docs/reference/self-hosted-runners.mdanddocs/src/content/docs/reference/frontmatter.md.runs-on:accepts all three GitHub Actions forms:runs-on: self-hostedruns-on: [self-hosted, linux, x64](runner must match all labels)runs-on: { group: my-runner-group, labels: [linux, x64] }Runner scope knobs
runs-on:ubuntu-latestruns-on-slim:ubuntu-slimsafe-outputs.runs-on:runs-on-slim)safe-outputs.threat-detection.runs-on:aw.json→maintenance.runs_onagentics-maintenance.ymlubuntu-slimHard requirements
macos-*❌ (no nested virtualization for Docker),windows-*❌.dockergroup or the socket must be world-readable.PATHfor framework scripts. gh-aw auto-emitsactions/setup-node(Node 24) when it detects a non-standard runner; pin explicitly withruntimes: { node: { version: '24' } }.api.githubcopilot.com,github.com,ghcr.io, plus anything innetwork.allowed.containerMode.type="dind"(type="kubernetes"is unsupported) plusrunner.topology: arc-dindin frontmatter. Split-daemon topologies may needGH_AW_DOCKER_SOCK_PATH/GH_AW_DOCKER_SOCK_GID.allowPrivilegeEscalation: false, the Copilot CLI install script needs--rootlessso it installs to~/.local/bininstead of/usr/local/bin.Air-gapped / private cloud
.github/workflows/aw.jsonsupportsaction_pins(remapowner/repo@ref→ internal mirror) andcontainer_pins(remap image + digest). Applied at compile time and baked into.lock.yml, so workflows never reach public registries at runtime. Neither is available in per-workflow frontmatter.Part 2 — Squad-specific gaps
Four issues found in Squad's current gh-aw integration:
1.
runs-onis not merged from importsPer gh-aw's imports reference: "
runs-onmust be set in each workflow — it is not merged from imports."Squad ships as
imports: - shared/squad.md, soruns-oncannot be added toworkflows/shared/squad.md. It has to live in each top-level workflow (workflows/squad.md,workflows/squad-implement-worker.md) or in a consumer-authored wrapper.2. Bootstrap runs on the activation job, not the agent job
workflows/shared/squad.mdrunsnpx --yes @bradygaster/squad-cli@$SQUAD_CLI_VERSION initinsidejobs.activation.pre-steps— deliberately, so the npm install happens outside the agent's network firewall.But activation is a framework job, so it obeys
runs-on-slim, notruns-on. Settingruns-on: self-hostedalone leaves the Squad install running on a GitHub-hosted runner. Full isolation requiresruns-on-slim:as well — and then the self-hosted runner needs Node onPATHand egress toregistry.npmjs.org.3. Hardcoded artifact action versions break GHES
workflows/shared/squad.mdpinsactions/upload-artifact@v7.0.1andactions/download-artifact@v8.0.1directly in itspre-steps/steps.gh-aw's GHES compatibility mode (
{"ghes": true}inaw.json, orgh aw compile --ghes) downgrades its own artifact steps toupload-artifact@v3.2.2/download-artifact@v3.1.0, but it does not rewrite action references that Squad hardcoded. On GHES those v4+ actions fail withGHESNotSupportedError, so Squad'ssquad-stateartifact handoff breaks — the agent job never receives.squad/or.github/agents/squad.agent.md.This is the most consequential gap and likely needs a fix in the shared component (e.g.
aw.jsonaction_pins, or version-selectable artifact steps).4. Customizations get clobbered on update
gh aw add bradygaster/squad/workflows/squad.md@latestrewrites the source.md, so a hand-addedruns-on:is lost on the next update. Consumers need a wrapper workflow instead.Proposed consumer pattern
A thin wrapper in the consumer repo that remote-imports Squad's shared component, keeping runner config out of the file that
gh aw addoverwrites:Air-gapped consumers additionally add
action_pins+container_pinsto.github/workflows/aw.jsonto mirrorghcr.io/github/gh-aw-firewalland theactions/*dependencies.Validation status
Findings are documentation- and source-validated, not runtime-validated:
self-hosted-runners.md,frontmatter.md,imports.md)workflows/shared/squad.mdgh aw compileFollow-up work
gh aw compileworkflows/shared/squad.md(blocks GHES/air-gapped adoption)runs-on/runs-on-slimas documented extension pointsdocs/src/content/docs/guide/gh-aw.mdReferences
workflows/shared/squad.md— Squad's bootstrap componentworkflows/squad.md,workflows/squad-implement-worker.md— top-level workflowsdocs/src/content/docs/guide/gh-aw.md— Squad's gh-aw setup guide