Copyright (c) 2026 MindMesh Academy. All rights reserved. This content is proprietary and may not be reproduced or distributed without permission.

2.1.2. Manual Triggers: workflow_dispatch Inputs

💡 First Principle: workflow_dispatch turns a workflow into a form — a button with typed, validated parameters — which is how you get deliberate, auditable human-in-the-loop operations like "deploy version X to staging" without giving anyone shell access to production.

The inputs are declared in the trigger itself, and their types are what make the form useful rather than a free-text footgun:

Input typeRenders asNotes
stringFree text boxDefault type if type: is omitted
numberFree text boxParsed as a number in the inputs context
booleanCheckboxArrives as a real boolean in the inputs context
choiceDropdownRequires an options: list — the way to constrain environments
environmentDropdown of repo environmentsAuto-populated from configured environments

A dispatch trigger looks like this, and note the 25-input maximum GitHub enforces:

on:
  workflow_dispatch:
    inputs:
      target:
        description: 'Deployment target'
        type: choice
        options: [staging, production]
        required: true
      version:
        description: 'Release tag to deploy'
        type: string
        required: true
      dry_run:
        description: 'Log actions without applying them'
        type: boolean
        default: true

Inside the workflow, read them with the inputs context: ${{ inputs.target }}. (The older github.event.inputs.* form still works but always yields strings — with inputs.dry_run a boolean input is genuinely boolean, which matters for if: conditions.) You can dispatch from the Actions UI, the REST API, or gh workflow run; either way the run records who triggered it, which is exactly the audit trail a manual-deploy scenario is asking about.

One structural requirement trips people up: like scheduled workflows, a workflow_dispatch workflow must exist on the default branch for the "Run workflow" button to appear at all — though once it does, you may select any branch to run against.

⚠️ Exam Trap: required: true does not mean "GitHub will reject an empty submission" in every path — when a default: is supplied, the field is prefilled, and API dispatches that omit an input receive the default. If a question hinges on a workflow behaving unexpectedly after an API-triggered run, check for a default silently supplying a value nobody chose.

Reflection Question: Why is a choice input with options: [staging, production] meaningfully safer than a string input the operator types the environment into — beyond just convenience?

See how it connects
Alvin Varughese
Written byAlvin Varughese
Founder18 professional certifications