How to Write Issue Templates That Coding Agents Can Finish
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
requiredonly 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 theneeds-triagelabel and have a human swap it foragent-readyafter 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.