A basic software factory built from GitHub Agentic Workflows. Label an issue and get a spec. Approve it and get a tested pull request. An independent agent reviews it, and you merge.
There's nothing to host: it runs in GitHub Actions on your Copilot subscription. Each station is a Markdown file of plain-English instructions.
issue ─◆ label factory ─▶ SPEC ─▶ spec comment ─◆ label build ─▶ BUILD ─▶ draft PR ─▶ CI gates + REVIEW ─◆ you merge
(you) (you) agent (you approve) agent code 2nd model (you)
weekly: LEARN reads the factory's PRs and reviews, and proposes AGENTS.md rules in an issue. You decide.
Companion to the talk Software Factories: from driving an agent to designing the line. Want to read and own the orchestrator itself? See factory-starter, the same line as about 800 lines of Python that you run anywhere.
You need a GitHub account with Copilot, and the GitHub CLI.
- Use this template (the green button above) to create your own repository, then clone it.
- Run
./setup.sh. It installs thegh awextension, creates the labels, lets Actions open pull requests, and stores your Copilot token. It links to a pre-filled token page, so you only click Generate and paste. - Open an issue with the Factory ticket template.
examples/first-ticket.mdis a good first one: Split the bill evenly. - Add the label
factory. A spec comment with testable acceptance criteria appears in a couple of minutes. Read it. - Happy with it? Add the label
build. A draft pull request appears, with an evidence table that maps each criterion to the test that proves it.
Then CI runs the gates and the review station posts an independent review. With the optional GH_AW_CI_TRIGGER_TOKEN this starts by itself. Without it, GitHub holds the checks on a bot-opened PR until a maintainer acts: click Ready for review on the draft PR and both start. Read the evidence and the review, then merge. Or don't.
What a run looks like. On 22 Oct 2026, issue #1 ("Split the bill evenly") became PR #3. It's left open, unmerged, as a reference run.
| Station | Time | Usage (AI credits, from the run footer) | Result |
|---|---|---|---|
| Spec | 5 min 23 s | 12.2 | 7 testable criteria, including edge cases the ticket didn't mention |
| Build | 5 min | 17.4 | 4 files, 6 new tests, an evidence table mapping each criterion to a test |
| Gates (CI) | under 1 min | n/a | test · compile · tests_kept: pass |
| Review | about 4 min (agent 1.6 min) | 1.0 | all 7 criteria met, "ready for a human to merge" |
| Station | File | Trigger | The agent may | It writes only through |
|---|---|---|---|---|
| Spec | factory-spec.md |
you add factory |
read the issue and code | one comment, plus spec-ready or needs-info |
| ◆ Approve | n/a | you add build |
n/a | n/a |
| Build | factory-build.md |
build label |
edit and run tests in its sandbox | one draft PR |
| Gates | ci.yml |
the PR | n/a (plain code) | test · compile · tests_kept (no test may disappear) |
| Review | factory-review.md |
the PR (label factory) |
read and run tests, using a different model family from the builder | inline comments and one review: comment or request changes, never approve |
| ◆ Merge | n/a | you | n/a | n/a |
| Learn | factory-learn.md |
weekly, or manually | read PRs, reviews and CI | one issue proposing AGENTS.md rules |
The builder uses a Claude Sonnet model and the reviewer a GPT-5 model, both through your Copilot subscription. They are set as model: sonnet and model: gpt-5 (gh-aw aliases), so the review comes from another vendor's model with a fresh context. Change them in each file's engine: block.
- The agent job is read-only. It runs in a sandbox behind a network firewall, with no write permissions.
- Writes are safe outputs. The agent can only ask for the outputs a workflow allows (a comment, labels, one PR), up to the limits you set. A separate job with write permission validates and applies them, after an automatic threat-detection job has scanned them for prompt injection, leaked secrets and malicious code. The build agent's commits arrive as a git bundle, and that separate job opens the PR. Drafts are enforced by policy.
- Protected files. A PR from an agent can't change dependency manifests or agent instruction files such as
AGENTS.md. That's whylearnproposes rules in an issue and a human edits the guide. - Untrusted input is fenced. Only people with write access can trigger the stations, because labels are the trigger. In public repositories, content from untrusted authors is filtered out of the agent's context (
min-integrity: approved). - Code decides what the agent reads. A small deterministic job before each station fetches exactly its context: the ticket a maintainer labelled, the spec written by the factory's own spec station, the PR diff. Other people's comments on the thread never reach the agent.
- Nothing merges itself. The review can't approve, and the factory has no merge permission. You merge.
The .md files are the source; the .lock.yml files are generated GitHub Actions. After editing a station, run gh aw compile and commit both. Ideas:
- Your own repo: copy
.github/workflows/factory-*.md,ci.yml,.github/scripts/andAGENTS.md. Put your real test and lint commands inci.ymland in the build station's step 4, and rewriteAGENTS.mdfor your codebase. - Organisation billing: add
copilot-requests: writeunderpermissions:. Then no personal token is needed. - Other engines:
engine: claude(withANTHROPIC_API_KEY) orengine: codex(withOPENAI_API_KEY). - More stations: browse githubnext/agentics, e.g.
gh aw add-wizard githubnext/agentics/ci-doctor. - Other ingress:
repository_dispatchlets Jira, PagerDuty or any HTTP caller start a workflow (triggers). - Watch it:
gh aw logs,gh aw audit <run>andgh aw healthshow what each station did and what it cost.
- A station "reported no action". Run
gh aw audit <run-id>; it shows the agent's reasoning and anything the integrity filter removed. The stations get their ticket and spec from the context jobs above. That's partly a workaround for gh-aw#70242, where issue bodies can be labelled untrusted at runtime, and it doesn't lowermin-integrity. - A run fails after the agent succeeded, with
safe_outputs"abandoned" or cancelled. The publishing job didn't get a runner.gh run rerun <run-id> --failedpublishes the saved result without running the agent again. - Checks waiting on the factory's PR. See step 5: add
GH_AW_CI_TRIGGER_TOKEN, or click Ready for review.
Each station run is one Copilot agent session, billed as premium requests on the token's account. GitHub Agentic Workflows is in public preview, so details change; gh aw upgrade updates the workflows. Start on a low-risk repository and keep the human merge.
MIT. See LICENSE.