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
6 changes: 3 additions & 3 deletions docs/bootstrap-implementation-summary.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ Workers guarantee outputs are discoverable via:

#### Tracker Label

Format: `campaign:{campaign_id}`
Format: `z_campaign_{campaign_id}`

- Applied to ALL worker-created items
- Enables discovery by campaign orchestrator
Expand Down Expand Up @@ -232,7 +232,7 @@ workers:
idempotency-strategy: pr-title-based
priority: 10

tracker-label: campaign:security-q1-2025
tracker-label: z_campaign_security-q1-2025
```

Note: The tracker-label is defined once at the campaign level and automatically applied by all workers.
Expand All @@ -244,7 +244,7 @@ Note: The tracker-label is defined once at the campaign level and automatically
- Dispatches `security-scanner` with `{severity: "high", max-alerts: 20}`
- Scanner finds 15 high-severity alerts
- Scanner creates 15 issues with:
- Label: `campaign:security-q1-2025`
- Label: `z_campaign_security-q1-2025`
- Title: `[scan-owner-repo] High severity alerts found`

2. **Run 2: Discovery (discovery = 15)**
Expand Down
16 changes: 8 additions & 8 deletions docs/campaign-workers.md
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ on:

The `campaign_id` identifies the campaign orchestrating this worker. Use it to:

- Label created items: `campaign:${campaign_id}`
- Label created items: `z_campaign_${campaign_id}`
- Generate deterministic keys: `campaign-${campaign_id}-${work_item_id}`
- Track work in repo-memory: `memory/campaigns/${campaign_id}/`

Expand Down Expand Up @@ -233,7 +233,7 @@ Use this key in:
Before creating any GitHub resource:

1. **Search for existing items** with the deterministic key
2. **Filter by campaign label**: `campaign:${campaign_id}`
2. **Filter by campaign tracker label**: `z_campaign_${campaign_id}`
3. **If found**: Skip or update existing item
4. **If not found**: Proceed with creation

Expand All @@ -256,7 +256,7 @@ if (existingPRs.total_count > 0) {

Apply the campaign tracker label to all created items:

- Label format: `campaign:${campaign_id}`
- Label format: `z_campaign_${campaign_id}`
- Prevents interference from other workflows
- Enables discovery by orchestrator

Expand Down Expand Up @@ -330,7 +330,7 @@ If no existing work found:
1. Create branch with deterministic name
2. Make required changes
3. Create PR with deterministic title
4. Apply labels: `campaign:${campaignId}`, [additional labels]
4. Apply labels: `z_campaign_${campaignId}`, [additional labels]

## Step 4: Report Status

Expand Down Expand Up @@ -362,7 +362,7 @@ PR title pattern: `[${workKey}] ${description}`

Before creating PR:
1. Search for PRs with `${workKey}` in title
2. Filter by `campaign:${campaignId}` label
2. Filter by `z_campaign_${campaignId}` label
3. If found: Update with comment or skip
4. If not: Create new PR
```
Expand Down Expand Up @@ -390,7 +390,7 @@ Issue title pattern: `[${workItemId}] ${description}`

Before creating issue:
1. Search for issues with `[${workItemId}]` in title
2. Filter by `campaign:${campaignId}` label
2. Filter by `z_campaign_${campaignId}` label
3. If found: Update existing issue
4. If not: Create new issue
```
Expand Down Expand Up @@ -496,7 +496,7 @@ await github.issues.addLabels({
owner: payload.repository.split('/')[0],
repo: payload.repository.split('/')[1],
issue_number: pr.number,
labels: [`campaign:${campaignId}`, 'security', 'automated']
labels: [`z_campaign_${campaignId}`, 'security', 'automated']
});

console.log(`Created PR: ${pr.html_url}`);
Expand Down Expand Up @@ -564,7 +564,7 @@ Before using a worker in a campaign:
- Second run should skip/update without errors

3. **Check labels** on created items:
- Verify `campaign:test-campaign` label is applied
- Verify `z_campaign_test-campaign` label is applied
- Confirm tracker-id is in description (if applicable)

4. **Test error cases**:
Expand Down
17 changes: 9 additions & 8 deletions docs/src/content/docs/examples/campaigns.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,17 @@ The campaign coordinates three workers (scanner, fixer, reviewer) that create se

### Key patterns

**Orchestrator responsibilities:**
**Orchestrator responsibilities (dispatch-only):**
- Runs discovery precomputation (writes a manifest for the agent)
- Dispatches workers on schedule
- Discovers worker outputs via labels
- Updates project board
- Reports progress metrics
- Coordinates work by dispatching allowlisted workflows

**Worker responsibilities:**
- Accepts `workflow_dispatch` only
- Uses standardized inputs
- Generates deterministic keys
- Checks for existing work
- Labels outputs with `campaign:<id>`
- Labels outputs with the campaign tracker label (defaults to `z_campaign_<id>`)

## Security Scanner Worker

Expand All @@ -58,7 +57,7 @@ The worker:
3. Generates deterministic key: `campaign-{id}-{repo}-{vuln_id}`
4. Checks for existing PR with that key
5. Creates PR only if none exists
6. Labels PR with `campaign:{id}`
6. Labels PR with `z_campaign_{id}`

## Worker design patterns

Expand Down Expand Up @@ -168,7 +167,7 @@ Workers are regular workflows, not in campaign-specific folders. The dispatch-on
type: create_pull_request
title: "[$KEY] Fix vulnerability 123"
body: "Automated security fix"
labels: "campaign:${{ inputs.campaign_id }}"
labels: "z_campaign_${{ inputs.campaign_id }}"
```

## Independent workflows
Expand All @@ -183,7 +182,9 @@ on:
workflow_dispatch:

# Creates items with campaign label for discovery
labels: ["campaign:security-audit", "security"]
labels: ["z_campaign_security-audit", "security"]

The recommended campaign tracking label format is `z_campaign_<id>`. If you need compatibility with older tooling that filters `campaign:*` labels, you can optionally apply both labels.
```

The campaign discovers these via tracker labels without controlling execution.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ ProjectOps complements [GitHub's built-in Projects automation](https://docs.gith

**Use descriptive project names** that clearly indicate purpose and scope. Prefer "Performance Optimization Q1 2026" over "Project 1".

**Leverage tracking labels** (`campaign:<id>`) for grouping related work across issues and PRs, enabling orchestrator discovery.
**Leverage tracking labels** (`z_campaign_<id>`) for grouping related work across issues and PRs, enabling campaign discovery.

**Set meaningful field values** like status, priority, and effort to enable effective filtering and sorting on boards.

Expand Down
94 changes: 73 additions & 21 deletions docs/src/content/docs/guides/campaigns/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,91 @@ banner:

## What are Agentic Campaigns?

**GitHub agentic campaigns** are AI-powered orchestration workflows that coordinate multiple **[agentic workflows](/gh-aw/reference/glossary/#agentic-workflow)** toward a shared goal across one or more repositories.
**[Agentic campaigns](/gh-aw/reference/glossary/#agentic-campaign)** are initiatives that coordinate multiple [agentic workflows](/gh-aw/reference/glossary/#agentic-workflow) toward a shared goal.

Just as [agentic workflows](/gh-aw/introduction/overview/) use natural language instructions to give an AI agent tasks and [safe outputs](/gh-aw/reference/safe-outputs/) to enable controlled GitHub operations, campaigns use **[campaign specs](/gh-aw/guides/campaigns/specs/)** to give an **orchestrator agent** high-level strategic instructions. The orchestrator agent interprets your campaign's objective and KPIs, then autonomously manages worker workflows to achieve the goal.
In practice, a campaign runs on a schedule, kicks off worker workflows in small batches, and tracks progress in [GitHub Projects](/gh-aw/reference/glossary/#github-projects-projects-v2).

## When to Use Campaigns
## When to use Campaigns

Use campaigns when your goal requires:
- **Multiple workflow runs** across one or more repositories
- **Coordination** of worker workflows doing similar tasks
- **Tracking** of created issues and pull requests
- **Progress reporting** against strategic objectives
- **Governance** with pacing controls and safety limits
Choose a campaign when you need coordination across repos or multiple workflows, with progress tracked in one place.

If a single workflow is enough (even on a schedule), start with a standalone agentic workflow.
- **Coordinate multiple worker workflows** that each do part of the job
- **Work across many repositories** (using campaign scope)
- **Track progress in one place** (a single [GitHub Project](/gh-aw/reference/glossary/#github-projects-projects-v2))
- **Roll out changes in batches across repos** (repeatable runs with per-run limits and central tracking)

## How Campaigns Work
If you only need one workflow in one repo, a single scheduled agentic workflow is usually simpler.

Campaigns provide an orchestration layer on top of your existing workflows:
If you're not sure yet, start small (one repo, one worker), then expand scope or add workers once you know what you need.

1. **Define your goal** in a [campaign spec](/gh-aw/guides/campaigns/specs/) with objectives, KPIs, and governance rules
2. **Compile to orchestrator** – the spec becomes a workflow that runs on schedule (daily by default)
3. **Orchestrator coordinates** – dispatches worker workflows, tracks their outputs, updates a GitHub Project board
4. **Progress tracked** – campaign publishes metrics and status updates against your KPIs
## Campaign Specs

**Key concepts:**
- **Campaign spec**: YAML configuration defining goals, governance, and worker coordination
- **Orchestrator agent**: AI agent managing campaign execution, worker dispatch, and progress tracking
- **Worker workflows**: Your existing dispatchable workflows that do the actual work
To create a campaign, you write a single markdown file:

- `.github/workflows/<id>.campaign.md`

That file has two parts:

- **[Frontmatter](/gh-aw/reference/glossary/#frontmatter)**: the configuration ([GitHub Project URL](/gh-aw/reference/glossary/#github-projects-projects-v2), scope, worker list, governance limits)
- **Markdown body**: the narrative (objective, KPIs, prioritization, constraints)

Here’s a small example:

```markdown wrap
---
id: dependency-upgrades
project-url: "https://github.com/orgs/ORG/projects/1"
scope:
- "org:ORG"
workflows:
- dependency-scanner
- dependency-upgrader
---

# Dependency Upgrades

Upgrade dependencies across repos.
```

See: [Campaign specs](/gh-aw/guides/campaigns/specs/).

## From markdown to GitHub Actions

Just like regular workflows, campaigns get compiled:

- You run `gh aw compile`
- The compiler produces a **[workflow lock file](/gh-aw/reference/glossary/#workflow-lock-file-lockyml)** (`.campaign.lock.yml`) that GitHub Actions runs

This is the same idea as [compilation](/gh-aw/reference/glossary/#compilation) for normal workflows: you edit human-friendly markdown, GitHub Actions runs the compiled YAML.

## Orchestrator + workers (who does what)

Campaigns split responsibilities on purpose:

- **Orchestrator (generated from the spec)**
- Runs on a schedule
- Coordinates and decides what to do next
- Uses **[safe outputs](/gh-aw/reference/glossary/#safe-outputs)** to dispatch worker workflows
- **Workers (you provide these)**
- Are normal agentic workflows triggered via [`workflow_dispatch`](/gh-aw/reference/glossary/#workflow_dispatch)
- Do the actual GitHub writes (issues/PRs/Projects/comments) using their own safe outputs

## What you’ll see in GitHub

When a campaign is working, you’ll usually see:

- A compiled workflow named `<id>.campaign.lock.yml` in `.github/workflows/`
- A GitHub Project filling up with issues/PRs created by workers
- Tracking labels on those issues/PRs like `z_campaign_<id>`
- Optional [labels](/gh-aw/reference/glossary/#labels) you can use to group and filter related workflows
- Worker workflow runs that create PRs and move items through statuses

If you want the full execution story, see: [Campaign lifecycle](/gh-aw/guides/campaigns/lifecycle/).

## Next steps

- [Creating campaigns](/gh-aw/guides/campaigns/creating-campaigns/) – issue-based or CLI creation
- [Getting started](/gh-aw/guides/campaigns/getting-started/) – step-by-step tutorial
- [Creating campaigns](/gh-aw/guides/campaigns/creating-campaigns/) – issue-based or CLI creation
- [Campaign specs](/gh-aw/guides/campaigns/specs/) – configuration reference
- [Campaign Lifecycle](/gh-aw/guides/campaigns/lifecycle/) – execution model
- [CLI commands](/gh-aw/guides/campaigns/cli-commands/) – command reference
23 changes: 10 additions & 13 deletions docs/src/content/docs/guides/campaigns/lifecycle.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,23 @@ banner:
content: '<strong>Do not use.</strong> Campaigns are still incomplete and may produce unreliable or unintended results.'
---

Campaign orchestrators execute on a schedule to coordinate worker workflows, discover outputs, and update project boards. This page explains the execution model, state management, and workflow coordination.
Campaign orchestrators execute on a schedule to coordinate worker workflows and discover outputs. Orchestrators are dispatch-only: they can coordinate, but all GitHub writes (Projects, issues/PRs, comments) happen in worker workflows.

## Execution flow

```mermaid
graph TD
A[Orchestrator Triggered] --> B[Phase 0: Dispatch Workers]
B --> C[Phase 1: Discover Items]
C --> D[Phase 2: Plan Updates]
D --> E[Phase 3: Apply Updates]
E --> F[Phase 4: Status Report]
A[Orchestrator Triggered] --> B[Pre-step: Discovery Precomputation]
B --> C[Agent: Decide & Dispatch Workers]
C --> D[Workers: Apply Side Effects]
D --> E[Next Run: Discover Outputs]
```

Each run follows this sequence:

1. **Phase 0** - Dispatches worker workflows via `workflow_dispatch` (if configured)
2. **Phase 1** - Discovers issues and pull requests with campaign tracker labels
3. **Phase 2** - Plans project board updates within governance limits
4. **Phase 3** - Applies updates to project board
5. **Phase 4** - Posts status update to project with progress summary
1. **Pre-step** - A deterministic discovery script runs (via `actions/github-script`) and writes `./.gh-aw/campaign.discovery.json`
2. **Agent** - Reads the discovery manifest and campaign spec, then dispatches worker workflows via `safe-outputs.dispatch-workflow`
3. **Workers** - Create/update issues/PRs, apply labels, and update Project boards using their own safe-outputs

## Campaign states

Expand Down Expand Up @@ -140,9 +137,9 @@ Completed 2025-03-15. Final metrics:
- Confirm discovery scope includes correct repos/orgs

**Project updates hit limit**
- Increase `max-project-updates-per-run` in governance
- Increase `max-project-updates-per-run` in governance (used as a pacing signal for generated instructions)
- Accept incremental processing across multiple runs
- Verify project token has required permissions
- Verify the worker workflow token has required Projects permissions

**Items processed multiple times**
- Ensure workers use deterministic keys
Expand Down
Loading