From d275be601b9ac4cb981acdb528e7930f1e80db5f Mon Sep 17 00:00:00 2001 From: Chris Butler Date: Tue, 28 Apr 2026 05:25:05 -0700 Subject: [PATCH 1/2] Add FAQ: external admission authority via environment protection rules Adds a new entry under Guardrails answering the question of whether external human approval can be required before safe outputs are applied. Explains the guardrail-vs-admission distinction and documents the GitHub Environment protection rules pattern for fail-closed external admission gates using custom safe output jobs. Closes github/agentic-workflows#484 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/src/content/docs/reference/faq.md | 29 ++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/src/content/docs/reference/faq.md b/docs/src/content/docs/reference/faq.md index 23b6363dabe..1780082577a 100644 --- a/docs/src/content/docs/reference/faq.md +++ b/docs/src/content/docs/reference/faq.md @@ -216,6 +216,35 @@ See [Text Sanitization](/gh-aw/reference/safe-outputs/#text-sanitization-allowed Guardrails are foundational to the design. Agentic workflows implement defense-in-depth through compilation-time validation (schema checks, expression safety, action SHA pinning), runtime isolation (sandboxed containers with network controls), permission separation (read-only defaults with [safe outputs](/gh-aw/reference/safe-outputs/) for writes), tool allowlisting, and output sanitization. See the [Security Architecture](/gh-aw/introduction/architecture/). +### Can I require external human approval before safe outputs are applied? + +Yes. The distinction here is between *guardrail validation* (does the agent output look acceptable?) and *external admission* (is this execution intent authorized to proceed?). gh-aw addresses both. + +The safe outputs architecture already enforces permission separation: the agent job runs read-only and never holds write credentials; it only produces a structured artifact. Separate jobs, with scoped write tokens, apply the changes. This boundary is real — a compromised agent cannot directly write to GitHub. + +For a fail-closed **external admission gate** before sensitive operations like deployments or credential use, apply **[GitHub Environment protection rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#required-reviewers)** to a [custom safe output job](/gh-aw/reference/custom-safe-outputs/). The job pauses until a designated reviewer outside the workflow system explicitly approves. No approval means no execution. + +```yaml wrap +safe-outputs: + jobs: + deploy-gate: + description: "Human approval required before deployment" + runs-on: ubuntu-latest + environment: production-deploy # configure required reviewers in Settings → Environments + inputs: + intent: + description: "Deployment intent summary from the agent" + required: true + type: string + steps: + - name: Execute approved deployment + run: echo "Proceeding with: ${{ inputs.intent }}" +``` + +This approval is enforced by GitHub's infrastructure, not by workflow logic the agent could influence. Threat detection still runs before the gate, so the reviewer sees output that has already passed automated scanning. + +Note that the *policy* — which environments require approval, what safe outputs are configured — is defined by whoever controls the repository. The admission decision for each run can be external; the admission policy itself is internal to repository owners. + ### How is my code and data processed? By default, your workflow is run on GitHub Actions, like any other GitHub Actions workflow, and as one if its jobs it invokes your nominated [AI Engine (coding agent)](/gh-aw/reference/engines/), run in a container. This engine may in turn make tool calls and MCP calls. When using the default **GitHub Copilot CLI**, the workflow is processed by the `copilot` CLI tool which uses GitHub Copilot's services and related AI models. The specifics depend on your engine choice: From f2438b3717c862ca9a8a849fe5f35740c87f7746 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 28 Apr 2026 14:27:42 +0000 Subject: [PATCH 2/2] docs(faq): update admission gate example to use needs:detection and safe-outputs.needs Agent-Logs-Url: https://github.com/github/gh-aw/sessions/7f90a3d5-3450-4da8-b7fc-673093cdfe0e Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- docs/src/content/docs/reference/faq.md | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/docs/src/content/docs/reference/faq.md b/docs/src/content/docs/reference/faq.md index 1780082577a..336b0fe8558 100644 --- a/docs/src/content/docs/reference/faq.md +++ b/docs/src/content/docs/reference/faq.md @@ -225,20 +225,17 @@ The safe outputs architecture already enforces permission separation: the agent For a fail-closed **external admission gate** before sensitive operations like deployments or credential use, apply **[GitHub Environment protection rules](https://docs.github.com/en/actions/managing-workflow-runs-and-deployments/managing-deployments/managing-environments-for-deployment#required-reviewers)** to a [custom safe output job](/gh-aw/reference/custom-safe-outputs/). The job pauses until a designated reviewer outside the workflow system explicitly approves. No approval means no execution. ```yaml wrap +jobs: + approval-gate: + runs-on: ubuntu-latest + needs: detection # waits for automated threat scanning to complete + environment: production-deploy # configure required reviewers in Settings → Environments + steps: + - name: Approved + run: echo "Execution approved by reviewer" + safe-outputs: - jobs: - deploy-gate: - description: "Human approval required before deployment" - runs-on: ubuntu-latest - environment: production-deploy # configure required reviewers in Settings → Environments - inputs: - intent: - description: "Deployment intent summary from the agent" - required: true - type: string - steps: - - name: Execute approved deployment - run: echo "Proceeding with: ${{ inputs.intent }}" + needs: [approval-gate] # built-in safe_outputs job waits for manual approval ``` This approval is enforced by GitHub's infrastructure, not by workflow logic the agent could influence. Threat detection still runs before the gate, so the reviewer sees output that has already passed automated scanning.