GitHub Agentic Workflows

Rate Limiting Controls

GitHub Agentic Workflows uses defense-in-depth to prevent runaway workflows: bot non-triggering, concurrency controls, timeouts, rate limiting, read-only agents, safe output limits, built-in delays, and manual review gates.

The github-actions[bot] account does not trigger workflow events. When a workflow creates an issue or posts a comment via safe outputs, it won’t trigger other workflows - preventing infinite loops.

on:
issues:
types: [opened]

This workflow won’t be triggered by issues created by safe outputs.

Workflows use dual concurrency control: per-workflow (based on context) and per-engine (one agent job at a time per AI engine).

concurrency:
group: gh-aw-${{ github.workflow }}
jobs:
agent:
concurrency:
group: gh-aw-copilot

This prevents parallel execution explosions and AI resource exhaustion. See Concurrency Control for trigger-specific patterns.

The agent execution step has a default timeout of 20 minutes, controlled by the top-level timeout-minutes field. Other jobs (custom jobs, safe-output jobs) use the GitHub Actions platform default of 360 minutes unless explicitly set. Custom runners support longer timeouts beyond the GitHub-hosted runner limit:

timeout-minutes: 120 # Apply 120-minute timeout to the agent execution step

The stop-after field provides additional control for when workflows should stop running:

stop-after: +48h # Stop after 48 hours from trigger

This evaluates in the agent job’s if: condition, preventing execution if the time limit is exceeded. Supports absolute dates and relative time deltas (minimum unit is hours).

Agents run with read-only permissions. All write operations (creating issues, posting comments, triggering workflows) go through the safe outputs system, which provides validation, auditing, and rate limiting.

permissions:
contents: read
issues: read
pull-requests: read

High-risk operations have default max limits to prevent exponential growth:

OperationDefault MaxPurpose
assign-to-agent1Prevent agent cascades
assign-to-bot1Prevent bot loops
dispatch-workflow1Prevent workflow explosions
safe-outputs:
assign-to-agent:
max: 3 # Override default if needed

Without limits, one workflow could spawn three agents, each spawning three more, creating exponential growth. The default max of 1 ensures linear progression.

Critical operations have hardcoded, non-disableable delays:

  • Agent assignments: 10-second delay between each assignment
  • Workflow dispatches: 5-second delay between each dispatch
// Agent assignment delay
await sleep(10000); // 10 seconds
// Workflow dispatch delay
await new Promise(resolve => setTimeout(resolve, 5000)); // 5 seconds

These prevent burst patterns and spread load over time.

Require manual approval for sensitive operations using GitHub Environments:

safe-outputs:
dispatch-workflow:
environment: production # Requires approval

Configure environments in repository Settings → Environments, add reviewers, then reference the environment name. Use for production dispatches, cross-repo operations, or security-sensitive actions.

The user-rate-limit frontmatter field prevents users from triggering workflows too frequently:

user-rate-limit:
max-runs-per-window: 5 # Required: Maximum runs per window (1-10)
window: 60 # Optional: Time window in minutes (default: 60, max: 180)
events: [workflow_dispatch, issue_comment] # Optional: Specific events (auto-inferred if omitted)
ignored-roles: [admin, maintain] # Optional: Roles exempt from rate limiting (default: [admin, maintain, write])

The pre-activation job checks recent runs and cancels the current run if the limit is exceeded.

Role exemptions: By default, users with admin, maintain, or write roles are exempt from rate limiting. To apply rate limiting to all users including admins, set ignored-roles: [].

The max-daily-ai-credits frontmatter field caps the total AI Credits a workflow can consume across all runs in a rolling 24-hour window:

max-daily-ai-credits: 5000 # Block new runs once this workflow
# exceeds 5000 AIC in the last 24 hours

When a run starts and the workflow has already consumed more than the threshold in the last 24 hours, the run fails before the agent executes. The default threshold is 5000 AIC (approximately $50 USD). Set the value to -1 to disable the guardrail for a specific workflow.

Bypass exceptions: The daily guardrail is automatically skipped for user-initiated and command-driven runs. This ensures the guardrail never blocks intentional user actions:

  • Manual triggers: A human-initiated workflow_dispatch from the GitHub UI or CLI always bypasses the guardrail.
  • Slash commands: Runs triggered by slash commands — whether routed through the centralized dispatcher or compiled directly into the workflow — bypass the guardrail.
  • Label commands: Runs triggered by label commands bypass the guardrail in the same way.
  • Centralized invocations: workflow_call and repository_dispatch events always bypass the guardrail; the calling workflow manages its own budget.
---
name: Safe Agent Workflow
engine:
id: copilot
timeout-minutes: 60 # Job timeout
on:
issues:
types: [opened]
user-rate-limit:
max-runs-per-window: 5
window: 60
stop-after: +2h # Workflow time limit
safe-outputs:
assign-to-agent:
max: 1
environment: production
---

This workflow combines: rate limiting (5/hour per user), concurrency control (one at a time), timeouts (60 min job, 2h workflow), manual approval (environment), and safe output limits (max 1 agent). The bot non-triggering and built-in delays provide additional protection.

Start with conservative limits and increase as needed. Use environments for high-risk operations (workflow dispatches, cross-repo operations, production systems). Layer multiple controls: rate limiting with concurrency, timeouts with stop-after, safe output limits with environments. Monitor workflow runs, safe output logs, and rate limit cancellations to identify needed adjustments.

Workflow immediately cancelled: Check rate limit in pre-activation logs, verify concurrency queue, or confirm stop-after hasn’t exceeded.

Agent assignments slow: Built-in 10-second delays are intentional. Five agents = ~40 seconds total.

Workflow dispatch not triggering: Verify max dispatch limit (default: 1), check 5-second delay, confirm target workflow has on: workflow_dispatch, or check pending environment approvals.