🧭 How toProject ManagementIntermediate✨ AI-assisted

How to Write Issue Templates That Coding Agents Can Finish

WittyTech Daily··5 min read
#github#issue-forms#coding-agents

Give a coding agent the ticket "fix the flaky export" and it will fix something. Whether it is your export is a coin flip, and you find out in code review. This guide builds a GitHub issue form, one of the issue templates for coding agents that forces the answers an agent cannot guess: scope, files in play, the command that proves the work, acceptance criteria and what is off limits. At the end you will have a working .github/ISSUE_TEMPLATE/agent-task.yml and a config.yml that stops people from skipping it.

What issue templates for coding agents have to capture

A human colleague fills the gaps in a ticket by walking over to your desk. An agent fills them with guesses. Each field in the form closes one gap:

  • Scope stops the "while I was in there" refactor.
  • Files in play point the agent at the right module instead of a plausible wrong one.
  • Test command gives it a pass or fail signal it can run itself.
  • Acceptance criteria define done in lines a command or a reviewer can check.
  • Out of scope names what to leave alone.

GitHub issue forms are YAML files in .github/ISSUE_TEMPLATE that turn the new-issue page into a form with required fields. The full syntax is in GitHub's docs on issue forms and the form schema.

1. Create the issue form and ask for scope

Create .github/ISSUE_TEMPLATE/agent-task.yml on your default branch. name, description and body are required top-level keys.

# .github/ISSUE_TEMPLATE/agent-task.yml
name: Agent-ready task
description: A small, checkable change a coding agent can finish without asking questions.
title: '[Agent task]: '
labels: ['needs-triage']
body:
  - type: markdown
    attributes:
      value: |
        Write this for a reader who cannot ask follow-up questions and has never seen the Slack thread.
        If you cannot fill in the test command, the task is not ready for an agent.
  - type: textarea
    id: scope
    attributes:
      label: Scope
      description: One or two sentences. What should be true after this change that is not true now?
      placeholder: The CSV export includes the currency column for EUR invoices.
    validations:
      required: true
      min_length: 40
  - type: dropdown
    id: change-type
    attributes:
      label: Type of change
      description: Tells the agent which tests it may change.
      options:
        - Bug fix
        - Small feature
        - Refactor with no behaviour change
        - Tests or docs only
    validations:
      required: true

The markdown element is shown in the form but not submitted, so it is the place for instructions. min_length is documented for textarea and input and rejects one-word answers.

2. Add the files in play and the test command

Append these two elements under body:.

  - type: textarea
    id: files-in-play
    attributes:
      label: Files in play
      description: Paths the agent should start from, one per line. Include the test file.
      placeholder: |
        src/export/csv.py
        tests/export/test_csv.py
    validations:
      required: true
  - type: textarea
    id: test-command
    attributes:
      label: Command that proves it works
      description: The exact command, run from the repo root. For a bug it must fail today and pass after the fix.
      placeholder: pytest tests/export/test_csv.py -k currency
      render: shell
    validations:
      required: true
      min_length: 5

Setting render: shell formats the submitted text as a code block, so the agent reads a command instead of prose. Repo-wide commands such as build and lint belong in your AGENTS.md. This field carries the one command that is specific to the task.

3. Write acceptance criteria and an out-of-scope list

  - type: textarea
    id: acceptance-criteria
    attributes:
      label: Acceptance criteria
      description: A checklist. Each line must be verifiable by a command or a reviewer in about a minute.
      placeholder: |
        - [ ] EUR invoices export a currency column with the ISO code
        - [ ] Existing export tests pass unchanged
        - [ ] New test covers EUR and USD rows
    validations:
      required: true
      min_length: 30
  - type: textarea
    id: out-of-scope
    attributes:
      label: Out of scope
      description: What the agent must leave alone. Name files, dependencies, schema changes and public APIs.
      placeholder: |
        - Do not change the invoice model or add dependencies.
        - Do not reformat files outside the paths above.
    validations:
      required: true

"Works correctly" is not an acceptance criterion. "Existing export tests pass unchanged" is, because the agent can run it and you can check it.

4. Add a ready check for the person filing the issue

  - type: checkboxes
    id: ready-check
    attributes:
      label: Ready check
      options:
        - label: I ran the test command myself and know whether it passes on the default branch today.
          required: true
        - label: Every acceptance criterion can be checked without asking me.
          required: true

Each checkbox takes its own required flag. The first one forces the author to run the command once, which catches typos and broken test setups before an agent burns a run on them.

5. Turn off blank issues

A form nobody has to use gets skipped. Add .github/ISSUE_TEMPLATE/config.yml:

blank_issues_enabled: false

This hides the blank issue option from people with Read or Triage roles. Per GitHub's template chooser docs, people with Write, Maintain or Admin roles still see it, labeled "Maintainers only".

6. Open a test issue and read it like an agent

GitHub converts each response to markdown and adds it to the issue body. File one real issue, then read only the body. If you could not do the work from that text alone, neither can the agent. Fix the form, then try again.

Gotchas

  • required only applies to public repositories. The schema docs say so for every required validation. In a private repo the form renders, but nothing stops an empty submission. Keep the needs-triage label and have a human swap it for agent-ready after reading the issue.
  • Create your labels first. A label that does not exist in the repository is not added to the issue.
  • A test that already passes proves nothing for a bug fix. Run the command before filing. It should fail.
  • The form takes effect from the default branch and only for new issues. Existing issues keep their old text.
  • The form shapes the request and nothing else. It does not assign an agent. How the issue reaches your agent depends on your tooling.

Fixing the request is the cheapest reliability work in an agent rollout: a checkable ticket gives the agent, and your reviewers, something concrete to measure the pull request against.

← More in Project Management