Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 26 additions & 3 deletions .github/aw/execute-agentic-campaign-workflow.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Workflow Execution

This campaign is configured to **actively execute workflows**. Your role is to run the workflows listed in sequence, collect their outputs, and use those outputs to drive the campaign forward.
This campaign orchestrator can execute workflows as needed. Your role is to run the workflows listed in sequence, collect their outputs, and use those outputs to drive the campaign forward.

**IMPORTANT: Active execution is an advanced feature. Exercise caution and follow all guidelines carefully.**
**IMPORTANT: Workflow execution is an advanced capability. Exercise caution and follow all guidelines carefully.**

---

Expand Down Expand Up @@ -49,7 +49,7 @@ The following workflows should be executed in order:

For each workflow:

1. **Check if workflow exists** - Look for `.github/workflows/<workflow-id>.md` or `.github/workflows/<workflow-id>.lock.yml`
1. **Check if workflow exists** - Look for `.github/workflows/<workflow-id>.md`

2. **Create workflow if needed** - Only if ALL guardrails above are satisfied:

Expand All @@ -68,6 +68,20 @@ For each workflow:

on:
workflow_dispatch: # Required for execution
inputs:
priority:
description: 'Priority level for this execution'
required: false
type: choice
options:
- low
- medium
- high
default: medium
target:
description: 'Specific target or scope for this run'
required: false
type: string

tools:
github:
Expand All @@ -85,6 +99,9 @@ For each workflow:

You are a focused workflow that <specific task>.

Priority: \$\{\{ github.event.inputs.priority \}\}
Target: \$\{\{ github.event.inputs.target \}\}

## Task

<Clear description of what to do>
Expand All @@ -94,6 +111,8 @@ For each workflow:
<What information to provide or actions to take>
```

**Note**: Define `inputs` under `workflow_dispatch` to accept parameters from the orchestrator. Use `\$\{\{ github.event.inputs.INPUT_NAME \}\}` to reference input values in your workflow markdown. See [DispatchOps documentation](https://githubnext.github.io/gh-aw/guides/dispatchops/#with-input-parameters) for input types and examples.

- Compile it with `gh aw compile <workflow-id>.md`
- **CRITICAL: Test before use** (see testing requirements below)

Expand All @@ -118,15 +137,19 @@ For each workflow:

4. **Execute the workflow** (skip if just tested successfully):
- Trigger: `mcp__github__run_workflow(workflow_id: "<workflow-id>", ref: "main")`
- **Pass input parameters based on decisions**: If the workflow accepts inputs, provide them to guide execution (e.g., `inputs: {priority: "high", target: "security"}`)
- Wait for completion: Poll `mcp__github__get_workflow_run(run_id)` until status is "completed"
- Collect outputs: Check `mcp__github__download_workflow_run_artifact()` for any artifacts
- **Handle failures gracefully**: If execution fails, note it in status update but continue campaign

5. **Use outputs for next steps** - Use information from workflow runs to:
- Inform subsequent workflow executions (e.g., scanner results → upgrader inputs)
- Pass contextual inputs to worker workflows based on campaign state and decisions
- Update project board items with relevant information
- Make decisions about campaign progress and next actions

**Note**: Workflows that accept `workflow_dispatch` inputs can receive parameters from the orchestrator. This enables the orchestrator to provide context, priorities, or targets based on its decisions. See [DispatchOps documentation](https://githubnext.github.io/gh-aw/guides/dispatchops/#with-input-parameters) for input parameter examples.

---

## Guidelines
Expand Down
211 changes: 209 additions & 2 deletions .github/workflows/security-alert-burndown.campaign.lock.yml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 8 additions & 9 deletions pkg/campaign/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,15 +325,14 @@ func BuildOrchestrator(spec *CampaignSpec, campaignFilePath string) (*workflow.W
promptData.MaxProjectCommentsPerRun = spec.Governance.MaxCommentsPerRun
}

// Add workflow execution instructions when workflows are configured
if len(spec.Workflows) > 0 {
workflowExecution := RenderWorkflowExecution(promptData)
if workflowExecution == "" {
orchestratorLog.Print("Warning: Failed to render workflow execution instructions, template may be missing")
} else {
appendPromptSection(markdownBuilder, "WORKFLOW EXECUTION (PHASE 0)", workflowExecution)
orchestratorLog.Printf("Campaign '%s' orchestrator includes workflow execution", spec.ID)
}
// All campaigns include workflow execution capabilities
// The orchestrator can dispatch workflows and make decisions regardless of initial configuration
workflowExecution := RenderWorkflowExecution(promptData)
if workflowExecution == "" {
orchestratorLog.Print("Warning: Failed to render workflow execution instructions, template may be missing")
} else {
appendPromptSection(markdownBuilder, "WORKFLOW EXECUTION (PHASE 0)", workflowExecution)
orchestratorLog.Printf("Campaign '%s' orchestrator includes workflow execution", spec.ID)
}

orchestratorInstructions := RenderOrchestratorInstructions(promptData)
Expand Down
3 changes: 3 additions & 0 deletions pkg/campaign/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ func renderTemplate(tmplStr string, data CampaignPromptData) (string, error) {
"if": func(condition bool) bool {
return condition
},
"add1": func(i int) int {
return i + 1
},
}

// Parse template with custom delimiters to match Handlebars style
Expand Down
Loading
Loading