From 9112b631bfa2e8d46dbb0bd5f0e7995db8146141 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Sep 2025 12:52:50 +0000 Subject: [PATCH 1/5] Initial plan From fee2d956260f194ec23ee11cb26a096f4f027126 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:01:08 +0000 Subject: [PATCH 2/5] Add "How It Works" section to README with example and mermaid diagram Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- README.md | 43 +++++++++++++++++++ .../js/collect_ndjson_output.test.cjs | 14 +++--- 2 files changed, 50 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 917f55856ff..9b208dac788 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,49 @@ Ready to get your first agentic workflow running? Follow our step-by-step [Quick Learn about the concepts behind agentic workflows, explore available workflow types, and understand how AI can automate your repository tasks. See [Concepts](docs/concepts.md). +## 🔧 How It Works + +GitHub Agentic Workflows transforms natural language markdown files into GitHub Actions that are executed by AI agents. Here's a simple example: + +**Input:** Create `.github/workflows/issue-responder.md` +```markdown +--- +on: + issues: + types: [opened] +permissions: + issues: write +safe-outputs: + add-issue-comment: +--- + +# Issue Auto-Responder + +When a new issue is opened, analyze it and: +1. Determine if it's a bug report, feature request, or question +2. Add an appropriate welcome comment with next steps +3. Ask for additional details if the issue is unclear +``` + +**Output:** The tool compiles this into a standard GitHub Actions workflow that runs an AI agent: + +```mermaid +graph TB + A["📝 Markdown Workflow
.github/workflows/issue-responder.md"] --> B["🔄 gh aw compile"] + B --> C["⚙️ GitHub Actions YAML
.github/workflows/issue-responder.lock.yml"] + C --> D["🚀 GitHub Actions Runner"] + D --> E["🤖 AI Agent (Claude/Codex)"] + E --> F["📊 Analyzes Issue Content"] + F --> G["💬 Posts Intelligent Comment"] + + style A fill:#e1f5fe + style C fill:#f3e5f5 + style E fill:#fff3e0 + style G fill:#e8f5e8 +``` + +The AI agent reads your repository context, understands the issue content, and takes appropriate actions - all defined in natural language rather than complex code. + ## 📚 Samples Explore ready-to-use agentic workflows for research, development, and automation tasks. See [Samples](docs/samples.md) for a complete list of demonstrator workflows including: diff --git a/pkg/workflow/js/collect_ndjson_output.test.cjs b/pkg/workflow/js/collect_ndjson_output.test.cjs index 50aa970599c..d7924369738 100644 --- a/pkg/workflow/js/collect_ndjson_output.test.cjs +++ b/pkg/workflow/js/collect_ndjson_output.test.cjs @@ -154,7 +154,7 @@ describe("collect_ndjson_output.cjs", () => { const failedMessage = mockCore.setFailed.mock.calls[0][0]; expect(failedMessage).toContain("requires a 'body' string field"); expect(failedMessage).toContain("requires a 'title' string field"); - + // setOutput should not be called because of early return const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); @@ -650,7 +650,7 @@ Line 3"} expect(mockCore.setFailed).toHaveBeenCalledTimes(1); const failedMessage = mockCore.setFailed.mock.calls[0][0]; expect(failedMessage).toContain("JSON parsing failed"); - + // setOutput should not be called because of early return const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); @@ -736,7 +736,7 @@ Line 3"} // Check if repair succeeded by looking at mock calls const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); - + if (outputCall) { // Repair succeeded const parsedOutput = JSON.parse(outputCall[1]); @@ -830,7 +830,7 @@ Line 3"} expect(mockCore.setFailed).toHaveBeenCalledTimes(1); const failedMessage = mockCore.setFailed.mock.calls[0][0]; expect(failedMessage).toContain("JSON parsing failed"); - + // setOutput should not be called because of early return const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); @@ -949,7 +949,7 @@ Line 3"} expect(mockCore.setFailed).toHaveBeenCalledTimes(1); const failedMessage = mockCore.setFailed.mock.calls[0][0]; expect(failedMessage).toContain("JSON parsing failed"); - + // setOutput should not be called because of early return const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); @@ -970,7 +970,7 @@ Line 3"} expect(mockCore.setFailed).toHaveBeenCalledTimes(1); const failedMessage = mockCore.setFailed.mock.calls[0][0]; expect(failedMessage).toContain("JSON parsing failed"); - + // setOutput should not be called because of early return const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); @@ -1015,7 +1015,7 @@ Line 3"} // Check if repair succeeded by looking at mock calls const setOutputCalls = mockCore.setOutput.mock.calls; const outputCall = setOutputCalls.find(call => call[0] === "output"); - + if (outputCall) { // Repair succeeded const parsedOutput = JSON.parse(outputCall[1]); From 78be9e971fae817e971b957f744a9b08e89f0021 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Sep 2025 13:11:57 +0000 Subject: [PATCH 3/5] Update README example permissions and add security benefits explanation Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com> --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 9b208dac788..72bc5c9dd6d 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ on: issues: types: [opened] permissions: - issues: write + read-all safe-outputs: add-issue-comment: --- @@ -56,6 +56,8 @@ graph TB The AI agent reads your repository context, understands the issue content, and takes appropriate actions - all defined in natural language rather than complex code. +**Security Benefits:** Workflows use read-only permissions by default, with write operations only allowed through sanitized `safe-outputs`. Access can be gated to team members only, ensuring AI agents operate within controlled boundaries. + ## 📚 Samples Explore ready-to-use agentic workflows for research, development, and automation tasks. See [Samples](docs/samples.md) for a complete list of demonstrator workflows including: From 700107bc86924097c45360c22133bdb223dcc07c Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Wed, 10 Sep 2025 16:43:23 +0000 Subject: [PATCH 4/5] Refactor README example for issue responder workflow and clarify AI agent functionality --- README.md | 29 ++++------------------------- 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 72bc5c9dd6d..25b52734fff 100644 --- a/README.md +++ b/README.md @@ -17,42 +17,21 @@ Learn about the concepts behind agentic workflows, explore available workflow ty GitHub Agentic Workflows transforms natural language markdown files into GitHub Actions that are executed by AI agents. Here's a simple example: -**Input:** Create `.github/workflows/issue-responder.md` ```markdown --- on: issues: types: [opened] -permissions: - read-all +permissions: read-all safe-outputs: add-issue-comment: --- +# Issue Clarifier -# Issue Auto-Responder - -When a new issue is opened, analyze it and: -1. Determine if it's a bug report, feature request, or question -2. Add an appropriate welcome comment with next steps -3. Ask for additional details if the issue is unclear +Analyze the current issue and ask for additional details if the issue is unclear. ``` -**Output:** The tool compiles this into a standard GitHub Actions workflow that runs an AI agent: - -```mermaid -graph TB - A["📝 Markdown Workflow
.github/workflows/issue-responder.md"] --> B["🔄 gh aw compile"] - B --> C["⚙️ GitHub Actions YAML
.github/workflows/issue-responder.lock.yml"] - C --> D["🚀 GitHub Actions Runner"] - D --> E["🤖 AI Agent (Claude/Codex)"] - E --> F["📊 Analyzes Issue Content"] - F --> G["💬 Posts Intelligent Comment"] - - style A fill:#e1f5fe - style C fill:#f3e5f5 - style E fill:#fff3e0 - style G fill:#e8f5e8 -``` +The `gh aw` cli compiles this into a GitHub Actions Workflow (.yml) that runs an AI agent (Claude, Codex, ...) in a containerized environment whenever a new issue is opened in the repository. The AI agent reads your repository context, understands the issue content, and takes appropriate actions - all defined in natural language rather than complex code. From 66b90b61113a61c3291284d436e4c6f7a6630258 Mon Sep 17 00:00:00 2001 From: Peli de Halleux Date: Wed, 10 Sep 2025 16:44:50 +0000 Subject: [PATCH 5/5] Increase patch size displayed in GitHub Actions summary from 50 to 500 lines --- .github/workflows/test-claude-create-pull-request.lock.yml | 2 +- .github/workflows/test-claude-push-to-branch.lock.yml | 2 +- .github/workflows/test-codex-create-pull-request.lock.yml | 2 +- .github/workflows/test-codex-push-to-branch.lock.yml | 2 +- .github/workflows/test-safe-outputs-custom-engine.lock.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/test-claude-create-pull-request.lock.yml b/.github/workflows/test-claude-create-pull-request.lock.yml index 7f415dceee9..20fc3b9a3d0 100644 --- a/.github/workflows/test-claude-create-pull-request.lock.yml +++ b/.github/workflows/test-claude-create-pull-request.lock.yml @@ -1541,7 +1541,7 @@ jobs: echo '## Git Patch' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY echo '```diff' >> $GITHUB_STEP_SUMMARY - head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY + head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY echo '...' >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/test-claude-push-to-branch.lock.yml b/.github/workflows/test-claude-push-to-branch.lock.yml index a8510ef91f5..841806a3cf9 100644 --- a/.github/workflows/test-claude-push-to-branch.lock.yml +++ b/.github/workflows/test-claude-push-to-branch.lock.yml @@ -1660,7 +1660,7 @@ jobs: echo '## Git Patch' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY echo '```diff' >> $GITHUB_STEP_SUMMARY - head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY + head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY echo '...' >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/test-codex-create-pull-request.lock.yml b/.github/workflows/test-codex-create-pull-request.lock.yml index cdfb0bc1d50..d13f998a0ea 100644 --- a/.github/workflows/test-codex-create-pull-request.lock.yml +++ b/.github/workflows/test-codex-create-pull-request.lock.yml @@ -1290,7 +1290,7 @@ jobs: echo '## Git Patch' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY echo '```diff' >> $GITHUB_STEP_SUMMARY - head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY + head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY echo '...' >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/test-codex-push-to-branch.lock.yml b/.github/workflows/test-codex-push-to-branch.lock.yml index 18883a8990c..8857c7708e1 100644 --- a/.github/workflows/test-codex-push-to-branch.lock.yml +++ b/.github/workflows/test-codex-push-to-branch.lock.yml @@ -1411,7 +1411,7 @@ jobs: echo '## Git Patch' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY echo '```diff' >> $GITHUB_STEP_SUMMARY - head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY + head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY echo '...' >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY diff --git a/.github/workflows/test-safe-outputs-custom-engine.lock.yml b/.github/workflows/test-safe-outputs-custom-engine.lock.yml index 4f01406b60d..487945fa3b9 100644 --- a/.github/workflows/test-safe-outputs-custom-engine.lock.yml +++ b/.github/workflows/test-safe-outputs-custom-engine.lock.yml @@ -1270,7 +1270,7 @@ jobs: echo '## Git Patch' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY echo '```diff' >> $GITHUB_STEP_SUMMARY - head -50 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY + head -500 /tmp/aw.patch >> $GITHUB_STEP_SUMMARY || echo "Could not display patch contents" >> $GITHUB_STEP_SUMMARY echo '...' >> $GITHUB_STEP_SUMMARY echo '```' >> $GITHUB_STEP_SUMMARY echo '' >> $GITHUB_STEP_SUMMARY