diff --git a/.github/skills/agentic-workflow-designer/SKILL.md b/.github/skills/agentic-workflow-designer/SKILL.md new file mode 100644 index 00000000000..a397dc18c05 --- /dev/null +++ b/.github/skills/agentic-workflow-designer/SKILL.md @@ -0,0 +1,307 @@ +--- +name: agentic-workflow-designer +description: Conversational skill that interviews users to design new agentic workflows +disable-model-invocation: true +--- + +# Workflow Designer + +Use this skill to run a structured interview with users who know their goal but not the workflow syntax yet, then generate one complete workflow `.md` file. + +## When to Use This Skill + +Use this before `.github/aw/create-agentic-workflow.md` when requirements are unclear or incomplete. + +- Use `skills/agentic-workflow-designer/SKILL.md` to discover and confirm requirements. +- Use `.github/aw/create-agentic-workflow.md` once requirements are clear and ready for implementation. +- Use `.github/aw/agentic-chat.md` when the user wants a specification/pseudo-code instead of a runnable workflow file. + +## Interview Framework + +Ask one question at a time. Move to the next phase only after the current phase is clear. + +### Phase 1: Goal + +Ask: **"What do you want to automate?"** + +Capture: +- Workflow name (kebab-case candidate) +- Brief description +- Optional emoji + +### Phase 2: Trigger + +Ask: **"When should this run?"** + +Follow up only if needed: +- Which event type(s)? +- Any filters (labels, branches, commands)? +- Scheduled cadence (daily/weekly/hourly)? + +Map to the `on:` block. + +### Phase 3: Scope (Read/Write) + +Ask: +- **"What should it read?"** (issues, PRs, code, discussions, CI data) +- **"What should it create or update?"** (comments, issues, PRs, labels) + +Map to: +- `permissions:` (keep read-only for agent job) +- `tools:` +- `safe-outputs:` + +### Phase 4: Data Strategy + +Ask: +- **"What data does the agent need to make decisions?"** +- Follow up: **"Can we pre-fetch and aggregate that data with shell commands so the agent only reads compact JSON?"** + +Capture: +- Whether `steps:` should pre-fetch GitHub data with `gh` + `jq` +- Output paths under `/tmp/gh-aw/data/` +- Whether batch work should use sub-agents + +Map to: +- `steps:` +- Prompt references to pre-computed file paths + +### Phase 5: Guardrails + +Ask: **"Should it block merging, just advise, or silently log?"** + +Capture: +- Visibility expectations (comment, issue, no visible output) +- No-op behavior expectation + +Guide toward safe output behavior and explicit `noop` instructions. + +### Phase 6: Context & Network + +Ask: **"Does it need external APIs, web access, package installs, or MCP servers?"** + +Follow up: +- **"Any third-party services or MCP servers to include (for example Slack, Jira, Datadog, custom internal MCP)?"** +- **"Are you deploying on GitHub.com, GHEC with custom endpoints, or GHES?"** +- For each integration, identify required auth from source docs and map it to GitHub Actions secrets + workflow env variables. +- Ask for exact external domains (FQDN/wildcard). + +Map to: +- `network.allowed` +- Optional MCP/GitHub tool usage in `tools:` +- `secrets:` / `env:` wiring for integration tokens +- GHES/GHEC settings such as `engine.api-target` and `aw.json` `ghes: true` (when applicable) + +### Phase 7: Engine (optional) + +Ask only if ambiguous: **"Any AI engine preference?"** + +If no preference, suggest default: +- "I'd suggest Copilot since you haven't mentioned a preference. Sound good?" + +Map to `engine:` only when not default. + +### Phase 8: Confirmation + +Present a structured summary and ask for approval before generation. + +## Decision Heuristics + +### Trigger Mapping + +| User says... | Maps to | +|---|---| +| "when someone opens a PR" | `on: pull_request:` with `types: [opened]` | +| "when a PR is updated" | `on: pull_request:` with `types: [opened, synchronize]` | +| "every morning", "daily" | fuzzy schedule shorthand `on: schedule: daily on weekdays` (compiler expands to cron) | +| "every Monday", "weekly" | fuzzy schedule shorthand `on: schedule: weekly` (compiler expands to cron) | +| "when I say /review" | `on: slash_command:` with `name: review` (or requested command) | +| "when an issue is labeled bug" | `on: issues:` with `types: [labeled]` and label filter guidance | +| "manually", "on demand" | `on: workflow_dispatch:` | +| "when a deployment fails" | `on: deployment_status:` | +| "when another workflow finishes" | `on: workflow_run:` | + +### Safe Output Mapping + +| User says... | Maps to | +|---|---| +| "post a comment" | `add-comment` | +| "create an issue" | `create-issue` | +| "open a PR", "submit changes" | `create-pull-request` | +| "add labels" | `add-labels` | +| "remove labels" | `remove-labels` | +| "close the issue" | `close-issue` | +| "assign someone" | `assign-to-user` | +| "nothing visible", "just analyze" | no safe outputs required | + +### Network Mapping + +| User says... | Maps to | +|---|---| +| "calls an external API" | ask for exact FQDN/wildcard, then add to `network.allowed` | +| "installs npm packages" | include `node` in `network.allowed` | +| "runs pip install" | include `python` in `network.allowed` | +| "builds Go code" | include `go` in `network.allowed` | +| "no external access" | `network.allowed: [defaults]` (or `[]` if explicitly zero network) | + +### Tool Mapping + +| User says... | Maps to | +|---|---| +| "read GitHub issues/PRs/workflows" | `tools.github` with `mode: gh-proxy` and minimal `toolsets` | +| "edit files" | `edit` tool (default unless restricted) | +| "run commands/tests" | `bash` tool (default unless restricted) | +| "browse web pages/docs" | `web-fetch` and/or `web-search` | +| "test UI flows" | `playwright` | + +### Integration Auth Mapping + +When the user names a third-party service or MCP server: + +1. Confirm whether native tool, MCP server, or safe-output job is the right integration path. +2. Look up the integration's auth requirements and required scopes before finalizing the design. +3. Provide a concrete setup checklist with: + - required GitHub Actions secrets (names to create) + - workflow env variables that consume those secrets + - minimum token scopes/permissions needed + +Output format to use: + +```text +Integration auth setup: +- : + - Secrets to create: , + - Workflow env vars: =${{ secrets. }} + - Required scopes/permissions: +``` + +Never suggest committing plaintext tokens. + +### Data Strategy Mapping + +| User says... | Maps to | +|---|---| +| "analyze PRs", "review issues", "check status" | add `steps:` that pre-fetch with `gh` + `jq` | +| "read the diff", "look at changed files" | add `steps:` using `gh pr diff` or `gh pr view --json files` | +| "search for patterns across repos" | add `steps:` using `gh search` + `jq` filters | +| "just respond to a comment" | no pre-fetch needed (event payload is enough) | +| "process each item individually" | suggest sub-agent pattern with `model: small` | + +## Token Optimization Defaults + +Apply these defaults unless the user explicitly asks otherwise: + +1. Use DataOps by default for GitHub reads: pre-fetch/aggregate with `gh` + `jq` in `steps:`, store compact JSON in `/tmp/gh-aw/data/`, and point the prompt to those files (see `.github/aw/token-optimization.md` for details). +2. Keep tool surface minimal: default to `tools.github.mode: gh-proxy`, include only required toolsets, and prefer `bash` + `gh` for simple reads. +3. For batch workloads, split items into compact data and suggest sub-agent processing with `model: small`. +4. Keep prompts compact: concise imperative instructions, explicit file paths, single-line `noop` guidance, and stable instructions before dynamic content. + +## Progressive Disclosure Rules + +1. Never dump all options at once; ask one targeted question at a time. +2. Skip questions when answers are inferable from prior user statements. +3. Offer smart defaults and request confirmation instead of over-questioning. +4. Ask at most 5 questions before presenting a summary; then ask "anything else?" if needed. +5. Detect done signals (`that's it`, `looks good`, `generate it`) and proceed to generation. + +## Confirmation Format + +Use this exact structure: + +```text +📋 Proposed workflow: +- Name: +- Trigger: +- Engine: +- Tools: +- Safe outputs: +- Network: +- Integrations/Auth: +- Deployment: +- Intent: +``` + +Then ask: **"Ready to generate, or want to adjust anything?"** + +## Generation Template + +After confirmation, generate one workflow file using the same skeleton style as `.github/aw/create-agentic-workflow.md`. + +```markdown +--- +emoji: +description: +on: + +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + mode: gh-proxy + toolsets: [default] +steps: + - name: + run: | + mkdir -p /tmp/gh-aw/data + +safe-outputs: + +network: + allowed: + - defaults + - +--- + +# + +## Task + + +If `steps:` includes pre-fetch commands, read the resulting `/tmp/gh-aw/data/*.json` files instead of broad live re-fetches. + +## Safe Outputs + +- Use configured safe outputs for all visible write actions. +- Call `noop` with a short reason when no action is needed. +``` + +## Validation Checklist + +Before final output, run this internal self-check: + +- [ ] Agent job permissions remain read-only (writes only via safe outputs) +- [ ] `safe-outputs:` covers every write action mentioned in prompt/instructions +- [ ] Network access is scoped; avoid blanket wildcard entries +- [ ] Trigger matches the user's intended activation event +- [ ] Prompt instructs agent to call `noop` when no action is needed +- [ ] Unnecessary defaults are omitted (for example `engine: copilot`) +- [ ] If reading GitHub data, `steps:` pre-fetches compact JSON (DataOps) +- [ ] `tools.github.mode` is `gh-proxy` unless broader MCP toolsets are explicitly needed +- [ ] Only required toolsets are listed (avoid blanket toolset lists) +- [ ] Prompt references specific pre-computed file paths +- [ ] For batch processing (>5 items), sub-agent pattern is suggested +- [ ] For each third-party service/MCP integration, required secrets/env vars are listed +- [ ] Auth guidance includes least-privilege token scope recommendations +- [ ] For GHEC/GHES deployments, `engine.api-target` and GHES compatibility guidance are included when needed + +## References (load only when needed) + +In-repo references: +- `.github/aw/syntax.md` +- `.github/aw/safe-outputs.md` +- `.github/aw/network.md` +- `.github/aw/patterns.md` +- `.github/aw/subagents.md` +- `.github/aw/token-optimization.md` +- `.github/aw/triggers.md` +- `.github/aw/create-agentic-workflow.md` + +Portable HTTPS references: +- `https://github.com/github/gh-aw/blob/main/.github/aw/syntax.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/safe-outputs.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/network.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/patterns.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/triggers.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/create-agentic-workflow.md` diff --git a/.github/skills/agentic-workflows/SKILL.md b/.github/skills/agentic-workflows/SKILL.md index 623b3db448e..b4505045ca5 100644 --- a/.github/skills/agentic-workflows/SKILL.md +++ b/.github/skills/agentic-workflows/SKILL.md @@ -1,17 +1,18 @@ --- name: agentic-workflows -description: Route gh-aw workflow create/debug/upgrade requests to the right prompts. +description: Route gh-aw workflow design/create/debug/upgrade requests to the right prompts. --- # Agentic Workflows Router -Use this skill when a user asks to create, update, debug, or upgrade GitHub Agentic Workflows in this repository. +Use this skill when a user asks to design, create, update, debug, or upgrade GitHub Agentic Workflows in this repository. -This skill is a dispatcher: identify the task type, load the matching `.github/aw/*.md` file, and follow it directly. Keep responses concise and ask a clarifying question if the correct prompt is unclear. +This skill is a dispatcher: identify the task type, load the matching workflow prompt/skill file, and follow it directly. Keep responses concise and ask a clarifying question if the correct prompt is unclear. Read only the files you need: Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/agentic-chat.md` +- `.github/aw/agentic-workflows-mcp.md` - `.github/aw/asciicharts.md` - `.github/aw/campaign.md` - `.github/aw/charts-trending.md` @@ -27,6 +28,7 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/github-agentic-workflows.md` - `.github/aw/github-mcp-server.md` - `.github/aw/llms.md` +- `.github/aw/mcp-clis.md` - `.github/aw/memory.md` - `.github/aw/messages.md` - `.github/aw/network.md` @@ -58,7 +60,9 @@ Load these files from `github/gh-aw` (they are not available locally). - `.github/aw/workflow-editing.md` - `.github/aw/workflow-patterns.md` -After loading the matching workflow prompt, follow it directly: +- `.github/skills/agentic-workflow-designer/SKILL.md` +After loading the matching workflow prompt or skill, follow it directly: +- Design workflows from scratch via interview: `skills/agentic-workflow-designer/SKILL.md` - Create new workflows: `.github/aw/create-agentic-workflow.md` - Update existing workflows: `.github/aw/update-agentic-workflow.md` - Debug, audit, or investigate workflows: `.github/aw/debug-agentic-workflow.md` @@ -72,4 +76,4 @@ After loading the matching workflow prompt, follow it directly: - Choose workflow architecture and patterns: `.github/aw/patterns.md` - Optimize token usage and cost: `.github/aw/token-optimization.md` -When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt. +When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill. diff --git a/pkg/cli/copilot_agents.go b/pkg/cli/copilot_agents.go index 1842e2fce3d..79f3323af1e 100644 --- a/pkg/cli/copilot_agents.go +++ b/pkg/cli/copilot_agents.go @@ -33,6 +33,9 @@ var agenticWorkflowsSkillTemplate string //go:embed data/agentic_workflows_fallback_aw_files.json var agenticWorkflowsFallbackAWFiles string +//go:embed data/agentic_workflow_designer_skill.md +var agenticWorkflowDesignerSkillTemplate string + var listAgenticWorkflowsMarkdownFiles = fetchAgenticWorkflowsMarkdownFiles // ensureAgenticWorkflowsDispatcher ensures that .github/skills/agentic-workflows/SKILL.md @@ -101,6 +104,63 @@ func ensureAgenticWorkflowsDispatcher(verbose bool, skipInstructions bool) error return nil } +// ensureAgenticWorkflowDesignerSkill ensures that +// .github/skills/agentic-workflow-designer/SKILL.md exists and matches the +// bundled workflow designer skill content. +func ensureAgenticWorkflowDesignerSkill(verbose bool, skipInstructions bool) error { + copilotAgentsLog.Print("Ensuring agentic workflow designer skill") + + if skipInstructions { + copilotAgentsLog.Print("Skipping skill creation: instructions disabled") + return nil + } + + gitRoot, err := gitutil.FindGitRoot() + if err != nil { + return err // Not in a git repository, skip + } + + targetDir := filepath.Join(gitRoot, ".github", "skills", "agentic-workflow-designer") + targetPath := filepath.Join(targetDir, "SKILL.md") + + if err := os.MkdirAll(targetDir, constants.DirPermPublic); err != nil { + return fmt.Errorf("failed to create .github/skills/agentic-workflow-designer directory: %w", err) + } + + existingContent := "" + if content, err := os.ReadFile(targetPath); err == nil { + existingContent = string(content) + } + + expectedContent := strings.TrimSpace(agenticWorkflowDesignerSkillTemplate) + if strings.TrimSpace(existingContent) == expectedContent { + copilotAgentsLog.Printf("Agentic workflow designer skill is up-to-date: %s", targetPath) + if verbose { + fmt.Fprintln(os.Stderr, console.FormatInfoMessage("Agentic workflow designer skill is up-to-date: "+targetPath)) + } + return nil + } + + if err := os.WriteFile(targetPath, []byte(agenticWorkflowDesignerSkillTemplate), constants.FilePermPublic); err != nil { + copilotAgentsLog.Printf("Failed to write agentic workflow designer skill: %s, error: %v", targetPath, err) + return fmt.Errorf("failed to write agentic workflow designer skill: %w", err) + } + + if existingContent == "" { + copilotAgentsLog.Printf("Created agentic workflow designer skill: %s", targetPath) + if verbose { + fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created agentic workflow designer skill: "+targetPath)) + } + } else { + copilotAgentsLog.Printf("Updated agentic workflow designer skill: %s", targetPath) + if verbose { + fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Updated agentic workflow designer skill: "+targetPath)) + } + } + + return nil +} + // ensureAgenticWorkflowsAgent ensures that .github/agents/agentic-workflows.md contains the custom agent. func ensureAgenticWorkflowsAgent(verbose bool) error { copilotAgentsLog.Print("Ensuring agentic workflows custom agent") diff --git a/pkg/cli/copilot_agents_test.go b/pkg/cli/copilot_agents_test.go index 9f80098cdba..6db75a430b9 100644 --- a/pkg/cli/copilot_agents_test.go +++ b/pkg/cli/copilot_agents_test.go @@ -339,6 +339,7 @@ func TestBuildAgenticWorkflowsSkillContent(t *testing.T) { if strings.Contains(content, ".github/agents/agentic-workflows") { t.Fatalf("expected generated skill content to avoid agent cross-references:\n%s", content) } + assert.Contains(t, content, "Design workflows from scratch via interview: `skills/agentic-workflow-designer/SKILL.md`") } func TestBuildAgenticWorkflowsSkillContentWithoutAWDirectory(t *testing.T) { @@ -369,6 +370,24 @@ func TestBuildAgenticWorkflowsSkillContentFallsBackToEmbeddedFileList(t *testing assert.NotContains(t, content, agenticWorkflowsSkillFileListPlaceholder, "expected generated skill content to replace the file-list placeholder") assert.Contains(t, content, "- `.github/aw/create-agentic-workflow.md`\n", "expected embedded fallback markdown file list to be used") + assert.Contains(t, content, "- `.github/skills/agentic-workflow-designer/SKILL.md`\n", "expected generated skill content to include agentic-workflow-designer skill") +} + +func TestCheckedInAgenticWorkflowDesignerSkillMatchesEmbeddedTemplate(t *testing.T) { + _, file, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("Failed to locate test file") + } + + gitRoot := filepath.Clean(filepath.Join(filepath.Dir(file), "..", "..")) + actual, err := os.ReadFile(filepath.Join(gitRoot, ".github", "skills", "agentic-workflow-designer", "SKILL.md")) + if err != nil { + t.Fatalf("Failed to read checked-in workflow designer skill file: %v", err) + } + + if strings.TrimSpace(string(actual)) != strings.TrimSpace(agenticWorkflowDesignerSkillTemplate) { + t.Fatalf("Checked-in workflow designer skill file is out of sync with embedded template\nexpected:\n%s\nactual:\n%s", agenticWorkflowDesignerSkillTemplate, string(actual)) + } } func TestCheckedInAgenticWorkflowsSkillMatchesGeneratedContent(t *testing.T) { diff --git a/pkg/cli/data/agentic_workflow_designer_skill.md b/pkg/cli/data/agentic_workflow_designer_skill.md new file mode 100644 index 00000000000..a397dc18c05 --- /dev/null +++ b/pkg/cli/data/agentic_workflow_designer_skill.md @@ -0,0 +1,307 @@ +--- +name: agentic-workflow-designer +description: Conversational skill that interviews users to design new agentic workflows +disable-model-invocation: true +--- + +# Workflow Designer + +Use this skill to run a structured interview with users who know their goal but not the workflow syntax yet, then generate one complete workflow `.md` file. + +## When to Use This Skill + +Use this before `.github/aw/create-agentic-workflow.md` when requirements are unclear or incomplete. + +- Use `skills/agentic-workflow-designer/SKILL.md` to discover and confirm requirements. +- Use `.github/aw/create-agentic-workflow.md` once requirements are clear and ready for implementation. +- Use `.github/aw/agentic-chat.md` when the user wants a specification/pseudo-code instead of a runnable workflow file. + +## Interview Framework + +Ask one question at a time. Move to the next phase only after the current phase is clear. + +### Phase 1: Goal + +Ask: **"What do you want to automate?"** + +Capture: +- Workflow name (kebab-case candidate) +- Brief description +- Optional emoji + +### Phase 2: Trigger + +Ask: **"When should this run?"** + +Follow up only if needed: +- Which event type(s)? +- Any filters (labels, branches, commands)? +- Scheduled cadence (daily/weekly/hourly)? + +Map to the `on:` block. + +### Phase 3: Scope (Read/Write) + +Ask: +- **"What should it read?"** (issues, PRs, code, discussions, CI data) +- **"What should it create or update?"** (comments, issues, PRs, labels) + +Map to: +- `permissions:` (keep read-only for agent job) +- `tools:` +- `safe-outputs:` + +### Phase 4: Data Strategy + +Ask: +- **"What data does the agent need to make decisions?"** +- Follow up: **"Can we pre-fetch and aggregate that data with shell commands so the agent only reads compact JSON?"** + +Capture: +- Whether `steps:` should pre-fetch GitHub data with `gh` + `jq` +- Output paths under `/tmp/gh-aw/data/` +- Whether batch work should use sub-agents + +Map to: +- `steps:` +- Prompt references to pre-computed file paths + +### Phase 5: Guardrails + +Ask: **"Should it block merging, just advise, or silently log?"** + +Capture: +- Visibility expectations (comment, issue, no visible output) +- No-op behavior expectation + +Guide toward safe output behavior and explicit `noop` instructions. + +### Phase 6: Context & Network + +Ask: **"Does it need external APIs, web access, package installs, or MCP servers?"** + +Follow up: +- **"Any third-party services or MCP servers to include (for example Slack, Jira, Datadog, custom internal MCP)?"** +- **"Are you deploying on GitHub.com, GHEC with custom endpoints, or GHES?"** +- For each integration, identify required auth from source docs and map it to GitHub Actions secrets + workflow env variables. +- Ask for exact external domains (FQDN/wildcard). + +Map to: +- `network.allowed` +- Optional MCP/GitHub tool usage in `tools:` +- `secrets:` / `env:` wiring for integration tokens +- GHES/GHEC settings such as `engine.api-target` and `aw.json` `ghes: true` (when applicable) + +### Phase 7: Engine (optional) + +Ask only if ambiguous: **"Any AI engine preference?"** + +If no preference, suggest default: +- "I'd suggest Copilot since you haven't mentioned a preference. Sound good?" + +Map to `engine:` only when not default. + +### Phase 8: Confirmation + +Present a structured summary and ask for approval before generation. + +## Decision Heuristics + +### Trigger Mapping + +| User says... | Maps to | +|---|---| +| "when someone opens a PR" | `on: pull_request:` with `types: [opened]` | +| "when a PR is updated" | `on: pull_request:` with `types: [opened, synchronize]` | +| "every morning", "daily" | fuzzy schedule shorthand `on: schedule: daily on weekdays` (compiler expands to cron) | +| "every Monday", "weekly" | fuzzy schedule shorthand `on: schedule: weekly` (compiler expands to cron) | +| "when I say /review" | `on: slash_command:` with `name: review` (or requested command) | +| "when an issue is labeled bug" | `on: issues:` with `types: [labeled]` and label filter guidance | +| "manually", "on demand" | `on: workflow_dispatch:` | +| "when a deployment fails" | `on: deployment_status:` | +| "when another workflow finishes" | `on: workflow_run:` | + +### Safe Output Mapping + +| User says... | Maps to | +|---|---| +| "post a comment" | `add-comment` | +| "create an issue" | `create-issue` | +| "open a PR", "submit changes" | `create-pull-request` | +| "add labels" | `add-labels` | +| "remove labels" | `remove-labels` | +| "close the issue" | `close-issue` | +| "assign someone" | `assign-to-user` | +| "nothing visible", "just analyze" | no safe outputs required | + +### Network Mapping + +| User says... | Maps to | +|---|---| +| "calls an external API" | ask for exact FQDN/wildcard, then add to `network.allowed` | +| "installs npm packages" | include `node` in `network.allowed` | +| "runs pip install" | include `python` in `network.allowed` | +| "builds Go code" | include `go` in `network.allowed` | +| "no external access" | `network.allowed: [defaults]` (or `[]` if explicitly zero network) | + +### Tool Mapping + +| User says... | Maps to | +|---|---| +| "read GitHub issues/PRs/workflows" | `tools.github` with `mode: gh-proxy` and minimal `toolsets` | +| "edit files" | `edit` tool (default unless restricted) | +| "run commands/tests" | `bash` tool (default unless restricted) | +| "browse web pages/docs" | `web-fetch` and/or `web-search` | +| "test UI flows" | `playwright` | + +### Integration Auth Mapping + +When the user names a third-party service or MCP server: + +1. Confirm whether native tool, MCP server, or safe-output job is the right integration path. +2. Look up the integration's auth requirements and required scopes before finalizing the design. +3. Provide a concrete setup checklist with: + - required GitHub Actions secrets (names to create) + - workflow env variables that consume those secrets + - minimum token scopes/permissions needed + +Output format to use: + +```text +Integration auth setup: +- : + - Secrets to create: , + - Workflow env vars: =${{ secrets. }} + - Required scopes/permissions: +``` + +Never suggest committing plaintext tokens. + +### Data Strategy Mapping + +| User says... | Maps to | +|---|---| +| "analyze PRs", "review issues", "check status" | add `steps:` that pre-fetch with `gh` + `jq` | +| "read the diff", "look at changed files" | add `steps:` using `gh pr diff` or `gh pr view --json files` | +| "search for patterns across repos" | add `steps:` using `gh search` + `jq` filters | +| "just respond to a comment" | no pre-fetch needed (event payload is enough) | +| "process each item individually" | suggest sub-agent pattern with `model: small` | + +## Token Optimization Defaults + +Apply these defaults unless the user explicitly asks otherwise: + +1. Use DataOps by default for GitHub reads: pre-fetch/aggregate with `gh` + `jq` in `steps:`, store compact JSON in `/tmp/gh-aw/data/`, and point the prompt to those files (see `.github/aw/token-optimization.md` for details). +2. Keep tool surface minimal: default to `tools.github.mode: gh-proxy`, include only required toolsets, and prefer `bash` + `gh` for simple reads. +3. For batch workloads, split items into compact data and suggest sub-agent processing with `model: small`. +4. Keep prompts compact: concise imperative instructions, explicit file paths, single-line `noop` guidance, and stable instructions before dynamic content. + +## Progressive Disclosure Rules + +1. Never dump all options at once; ask one targeted question at a time. +2. Skip questions when answers are inferable from prior user statements. +3. Offer smart defaults and request confirmation instead of over-questioning. +4. Ask at most 5 questions before presenting a summary; then ask "anything else?" if needed. +5. Detect done signals (`that's it`, `looks good`, `generate it`) and proceed to generation. + +## Confirmation Format + +Use this exact structure: + +```text +📋 Proposed workflow: +- Name: +- Trigger: +- Engine: +- Tools: +- Safe outputs: +- Network: +- Integrations/Auth: +- Deployment: +- Intent: +``` + +Then ask: **"Ready to generate, or want to adjust anything?"** + +## Generation Template + +After confirmation, generate one workflow file using the same skeleton style as `.github/aw/create-agentic-workflow.md`. + +```markdown +--- +emoji: +description: +on: + +permissions: + contents: read + issues: read + pull-requests: read +tools: + github: + mode: gh-proxy + toolsets: [default] +steps: + - name: + run: | + mkdir -p /tmp/gh-aw/data + +safe-outputs: + +network: + allowed: + - defaults + - +--- + +# + +## Task + + +If `steps:` includes pre-fetch commands, read the resulting `/tmp/gh-aw/data/*.json` files instead of broad live re-fetches. + +## Safe Outputs + +- Use configured safe outputs for all visible write actions. +- Call `noop` with a short reason when no action is needed. +``` + +## Validation Checklist + +Before final output, run this internal self-check: + +- [ ] Agent job permissions remain read-only (writes only via safe outputs) +- [ ] `safe-outputs:` covers every write action mentioned in prompt/instructions +- [ ] Network access is scoped; avoid blanket wildcard entries +- [ ] Trigger matches the user's intended activation event +- [ ] Prompt instructs agent to call `noop` when no action is needed +- [ ] Unnecessary defaults are omitted (for example `engine: copilot`) +- [ ] If reading GitHub data, `steps:` pre-fetches compact JSON (DataOps) +- [ ] `tools.github.mode` is `gh-proxy` unless broader MCP toolsets are explicitly needed +- [ ] Only required toolsets are listed (avoid blanket toolset lists) +- [ ] Prompt references specific pre-computed file paths +- [ ] For batch processing (>5 items), sub-agent pattern is suggested +- [ ] For each third-party service/MCP integration, required secrets/env vars are listed +- [ ] Auth guidance includes least-privilege token scope recommendations +- [ ] For GHEC/GHES deployments, `engine.api-target` and GHES compatibility guidance are included when needed + +## References (load only when needed) + +In-repo references: +- `.github/aw/syntax.md` +- `.github/aw/safe-outputs.md` +- `.github/aw/network.md` +- `.github/aw/patterns.md` +- `.github/aw/subagents.md` +- `.github/aw/token-optimization.md` +- `.github/aw/triggers.md` +- `.github/aw/create-agentic-workflow.md` + +Portable HTTPS references: +- `https://github.com/github/gh-aw/blob/main/.github/aw/syntax.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/safe-outputs.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/network.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/patterns.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/triggers.md` +- `https://github.com/github/gh-aw/blob/main/.github/aw/create-agentic-workflow.md` diff --git a/pkg/cli/data/agentic_workflows_skill.md b/pkg/cli/data/agentic_workflows_skill.md index 5159ad31e33..4e5d5d8395e 100644 --- a/pkg/cli/data/agentic_workflows_skill.md +++ b/pkg/cli/data/agentic_workflows_skill.md @@ -1,18 +1,20 @@ --- name: agentic-workflows -description: Route gh-aw workflow create/debug/upgrade requests to the right prompts. +description: Route gh-aw workflow design/create/debug/upgrade requests to the right prompts. --- # Agentic Workflows Router -Use this skill when a user asks to create, update, debug, or upgrade GitHub Agentic Workflows in this repository. +Use this skill when a user asks to design, create, update, debug, or upgrade GitHub Agentic Workflows in this repository. -This skill is a dispatcher: identify the task type, load the matching `.github/aw/*.md` file, and follow it directly. Keep responses concise and ask a clarifying question if the correct prompt is unclear. +This skill is a dispatcher: identify the task type, load the matching workflow prompt/skill file, and follow it directly. Keep responses concise and ask a clarifying question if the correct prompt is unclear. Read only the files you need: Load these files from `github/gh-aw` (they are not available locally). {{AW_FILE_LIST}} -After loading the matching workflow prompt, follow it directly: +- `.github/skills/agentic-workflow-designer/SKILL.md` +After loading the matching workflow prompt or skill, follow it directly: +- Design workflows from scratch via interview: `skills/agentic-workflow-designer/SKILL.md` - Create new workflows: `.github/aw/create-agentic-workflow.md` - Update existing workflows: `.github/aw/update-agentic-workflow.md` - Debug, audit, or investigate workflows: `.github/aw/debug-agentic-workflow.md` @@ -26,4 +28,4 @@ After loading the matching workflow prompt, follow it directly: - Choose workflow architecture and patterns: `.github/aw/patterns.md` - Optimize token usage and cost: `.github/aw/token-optimization.md` -When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt. +When the task involves OTEL, OTLP, traces, observability backends, or telemetry-driven analysis, also read and follow `skills/otel-queries/SKILL.md` after loading the matching workflow prompt or skill. diff --git a/pkg/cli/init.go b/pkg/cli/init.go index 9e354b0fb32..b3fc4dda062 100644 --- a/pkg/cli/init.go +++ b/pkg/cli/init.go @@ -88,8 +88,13 @@ func InitRepository(opts InitOptions) error { initLog.Printf("Failed to write dispatcher skill: %v", err) return fmt.Errorf("failed to write dispatcher skill: %w", err) } + initLog.Print("Writing agentic workflow designer skill") + if err := ensureAgenticWorkflowDesignerSkill(opts.Verbose, false); err != nil { + initLog.Printf("Failed to write agentic workflow designer skill: %v", err) + return fmt.Errorf("failed to write agentic workflow designer skill: %w", err) + } if opts.Verbose { - fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created dispatcher skill")) + fmt.Fprintln(os.Stderr, console.FormatSuccessMessage("Created dispatcher and designer skills")) } } else { initLog.Print("Skipping agentic workflows dispatcher skill") diff --git a/pkg/cli/init_command.go b/pkg/cli/init_command.go index 0ed5a369e85..036a0fbdb08 100644 --- a/pkg/cli/init_command.go +++ b/pkg/cli/init_command.go @@ -26,6 +26,7 @@ engine selection or secret configuration. This command: - Configures .gitattributes to mark .lock.yml files as generated - Creates the dispatcher skill at .github/skills/agentic-workflows/SKILL.md +- Creates the workflow designer skill at .github/skills/agentic-workflow-designer/SKILL.md - Creates the custom agent at .github/agents/agentic-workflows.md - Removes old prompt files from .github/prompts/ if they exist - Configures VSCode settings (.vscode/settings.json) diff --git a/pkg/cli/init_command_test.go b/pkg/cli/init_command_test.go index 8293924bfa8..60be811100a 100644 --- a/pkg/cli/init_command_test.go +++ b/pkg/cli/init_command_test.go @@ -144,6 +144,10 @@ func TestInitCommandHelp(t *testing.T) { t.Error("Expected help text to mention the Agentic Workflows custom agent") } + if !strings.Contains(helpText, ".github/skills/agentic-workflow-designer/SKILL.md") { + t.Error("Expected help text to mention the agentic workflow designer skill") + } + if !strings.Contains(helpText, "Copilot") { t.Error("Expected help text to mention Copilot") } @@ -242,6 +246,10 @@ func TestInitRepositoryBasic(t *testing.T) { if _, err := os.Stat(skillPath); os.IsNotExist(err) { t.Errorf("Expected dispatcher skill file to be created at %s", skillPath) } + designerSkillPath := filepath.Join(".github", "skills", "agentic-workflow-designer", "SKILL.md") + if _, err := os.Stat(designerSkillPath); os.IsNotExist(err) { + t.Errorf("Expected workflow designer skill file to be created at %s", designerSkillPath) + } agentPath := filepath.Join(".github", "agents", "agentic-workflows.md") agentContent, err := os.ReadFile(agentPath) @@ -351,6 +359,9 @@ func TestInitRepositoryWithNoMCP(t *testing.T) { if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflows", "SKILL.md")); os.IsNotExist(err) { t.Error("Expected dispatcher skill file to still be created with --no-mcp flag") } + if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflow-designer", "SKILL.md")); os.IsNotExist(err) { + t.Error("Expected workflow designer skill file to still be created with --no-mcp flag") + } if _, err := os.Stat(filepath.Join(".github", "agents", "agentic-workflows.md")); os.IsNotExist(err) { t.Error("Expected Agentic Workflows custom agent file to still be created with --no-mcp flag") } @@ -386,6 +397,9 @@ func TestInitRepositoryWithNoSkill(t *testing.T) { if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflows", "SKILL.md")); err == nil { t.Error("Expected dispatcher skill file to NOT be created with skill disabled") } + if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflow-designer", "SKILL.md")); err == nil { + t.Error("Expected workflow designer skill file to NOT be created with skill disabled") + } if _, err := os.Stat(filepath.Join(".github", "agents", "agentic-workflows.md")); os.IsNotExist(err) { t.Error("Expected Agentic Workflows custom agent file to still be created with skill disabled") } @@ -421,6 +435,9 @@ func TestInitRepositoryWithNoAgent(t *testing.T) { if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflows", "SKILL.md")); os.IsNotExist(err) { t.Error("Expected dispatcher skill file to still be created with agent disabled") } + if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflow-designer", "SKILL.md")); os.IsNotExist(err) { + t.Error("Expected workflow designer skill file to still be created with agent disabled") + } if _, err := os.Stat(filepath.Join(".github", "agents", "agentic-workflows.md")); err == nil { t.Error("Expected Agentic Workflows custom agent file to NOT be created with agent disabled") } @@ -456,6 +473,9 @@ func TestInitRepositoryWithNonCopilotEngineSkipsCopilotArtifacts(t *testing.T) { if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflows", "SKILL.md")); err == nil { t.Error("Expected dispatcher skill file to NOT be created for non-Copilot engine") } + if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflow-designer", "SKILL.md")); err == nil { + t.Error("Expected workflow designer skill file to NOT be created for non-Copilot engine") + } if _, err := os.Stat(filepath.Join(".github", "agents", "agentic-workflows.md")); err == nil { t.Error("Expected Agentic Workflows custom agent file to NOT be created for non-Copilot engine") } @@ -513,6 +533,9 @@ func TestInitRepositoryRemovesLegacyDispatcherAgentFile(t *testing.T) { if _, err := os.Stat(skillPath); os.IsNotExist(err) { t.Fatalf("Expected dispatcher skill file to be created at %s", skillPath) } + if _, err := os.Stat(filepath.Join(".github", "skills", "agentic-workflow-designer", "SKILL.md")); os.IsNotExist(err) { + t.Fatalf("Expected workflow designer skill file to be created") + } } func TestInitRepositoryWithMCPBackwardCompatibility(t *testing.T) {