Open-PR Bound Pattern in Design-Control-Loop Phase G: Workflow Control Implementation
The open-PR bound pattern in Phase G of the design-control-loop skill enforces a single-pull-request limit per agent by querying GitHub for existing open PRs matching a unique loop label, preventing scheduled runs from overwhelming reviewers while allowing manual overrides.
The humanlayer/skills repository contains a sophisticated design-control-loop skill that manages autonomous agent workflows through GitHub Actions. Phase G of this loop implements the open-PR bound pattern, a critical flow-control mechanism that limits work-in-progress by ensuring only one pull request remains open per agent task at any time.
Core Concept of the Open-PR Bound Pattern
Bound Definition and Configuration
The default configuration restricts each agent to at most one open PR. This prevents the loop from creating new pull requests faster than human reviewers can inspect and merge them. The bound is documented in plugins/design-control-loop/skills/design-control-loop/SKILL.md under Phase G — Flow control.
Label-Based Identification
Each loop instance tags its pull requests with a unique label defined by the AGENT_LABEL environment variable (format: agent-<task-slug>). This label serves as the primary filter for identifying existing work-in-progress items belonging to specific agent tasks across the repository.
How the Workflow Detects Existing PRs
The GitHub CLI Query
At the start of every scheduled execution, the workflow runs the "Check iterate marker to bound work-in-progress" step in plugins/design-control-loop/skills/design-control-loop/references/workflow-template.yml (lines 55-63). This step uses the GitHub CLI to query for open PRs filtered by the agent's unique label:
EXISTING_PR=$(gh pr list --repo "$GITHUB_REPOSITORY" \
--state open --label "$AGENT_LABEL" \
--json number,url --limit 1)
Early Exit Logic
The workflow parses the JSON output to determine if any open PRs exist. If the query returns results (array length > 0), the workflow sets run_agent=false and exits immediately, effectively no-op'ing the run:
if [ "$(echo "$EXISTING_PR" | jq 'length')" -gt 0 ]; then
echo "run_agent=false" >> "$GITHUB_OUTPUT"
echo "Open PR already exists for $AGENT_LABEL; no-op."
exit 0
fi
This check ensures that scheduled runs respect the bound and do not spawn additional pull requests while one remains open.
Manual Trigger Bypass Mechanism
Manual workflow_dispatch triggers bypass the open-PR bound entirely. The workflow detects non-scheduled events via the EVENT_NAME environment variable and immediately sets run_agent=true for events that are not issue_comment, allowing users to force execution when needed:
if [ "$EVENT_NAME" != "issue_comment" ]; then
echo "run_agent=true" >> "$GITHUB_OUTPUT"
exit 0
fi
This bypass ensures that human-initiated runs always proceed regardless of existing open PRs, providing an escape hatch for urgent updates.
Complete Implementation in workflow-template.yml
The following excerpt from plugins/design-control-loop/skills/design-control-loop/references/workflow-template.yml demonstrates the full bound enforcement logic:
- name: Check iterate marker to bound work-in-progress
id: agent_gate
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
EVENT_NAME: ${{ github.event_name }}
GITHUB_REPOSITORY: ${{ github.repository }}
AGENT_LABEL: agent-<task-slug>
run: |
# Scheduled runs no-op when an open PR already exists for this agent
if [ "$EVENT_NAME" = "schedule" ] || [ "$EVENT_NAME" = "workflow_call" ]; then
EXISTING_PR=$(gh pr list --repo "$GITHUB_REPOSITORY" \
--state open --label "$AGENT_LABEL" \
--json number,url --limit 1)
if [ "$(echo "$EXISTING_PR" | jq 'length')" -gt 0 ]; then
echo "run_agent=false" >> "$GITHUB_OUTPUT"
echo "Open PR already exists for $AGENT_LABEL; no-op."
exit 0
fi
fi
# Manual runs continue regardless of existing PRs
if [ "$EVENT_NAME" != "issue_comment" ]; then
echo "run_agent=true" >> "$GITHUB_OUTPUT"
exit 0
fi
When creating new pull requests, the workflow applies the same label to maintain consistency for future bound checks:
- name: Create PR (if not existing)
if: steps.agent_gate.outputs.run_agent == 'true'
uses: peter-evans/create-pull-request@v5
with:
token: ${{ secrets.GITHUB_TOKEN }}
title: "[agent-<task-slug>] Automated update"
branch: ${{ env.BRANCH }}
labels: ${{ env.AGENT_LABEL }}
Summary
- The open-PR bound pattern limits each agent to one open pull request at a time, preventing reviewer overload in the
humanlayer/skillsdesign-control-loop. - The workflow checks for existing PRs by querying GitHub for open issues labeled with the unique
AGENT_LABELassigned to each loop instance. - If an open PR exists during a scheduled run, the workflow exits early with a no-op status, while manual triggers bypass this restriction entirely.
- The implementation relies on the GitHub CLI (
gh pr list) with JSON output parsing to detect existing work-in-progress items.
Frequently Asked Questions
How does the open-PR bound pattern prevent multiple simultaneous PRs from the same agent?
The pattern enforces a single-PR limit by querying GitHub for existing open pull requests tagged with the agent's unique label before executing the main loop logic. If the query in workflow-template.yml returns any results, the workflow terminates early with run_agent=false, ensuring only one PR remains active until it is merged or closed.
What happens if I manually trigger the workflow while a PR is already open?
Manual workflow_dispatch triggers bypass the open-PR bound check entirely. The workflow detects non-scheduled events via the EVENT_NAME environment variable and automatically sets run_agent=true for events that are not issue_comment, allowing you to force execution even when an open PR already exists for that agent label.
Where is the AGENT_LABEL defined in the workflow configuration?
The AGENT_LABEL environment variable is defined in the "Check iterate marker to bound work-in-progress" step within plugins/design-control-loop/skills/design-control-loop/references/workflow-template.yml, typically set to agent-<task-slug> to match the specific agent task identifier. This label is applied to newly created PRs and used as the filter criteria for existence checks.
Can the bound limit be configured to allow more than one open PR?
The current implementation in Phase G enforces a hard limit of one open PR per agent through the --limit 1 parameter in the GitHub CLI query and the JSON array length check. While the documentation describes this as the "default" bound, modifying the workflow would require adjusting the query logic and gate conditions in workflow-template.yml to change the threshold value.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →