Skip to content
Alpha — private preview. Expect rough edges and breaking changes between releases.

GitHub issue automation

Write an issue, label it, and an agent picks it up: the manager watches the repositories it knows for issues carrying the right labels and starts sessions for the ones that are properly authorised. No webhook, no inbound port — the manager polls GitHub through gh, so it works from behind any router.

Label (default) Meaning
agent-task This issue is work an agent could do. Categorisation.
agent:ready Go. An execution authorisation.

They are separate on purpose: writing down what an agent could do is not the same act as telling it to run code on your machine, and the two are often done by different people at different times. Both names are configurable (github.issueTaskLabel, github.issueReadyLabel) because they are conventions in your repository, not facts about the manager.

Off by default, deliberately — this is the only loop in the system that starts an agent with nobody present:

github:
issueWatch:
enabled: true
intervalSeconds: 60
allowedActors:
- your-github-login
  • A label is not an authorisation until a named person applies it. Anyone with triage access can add agent:ready; the manager checks who did against allowedActors using the issue’s timeline. The allowlist is empty by default, and empty means nobody — omitting the config cannot silently enable anything.
  • The latest application wins. A label removed and re-applied by someone else is that person’s authorisation.
  • One session per authorisation. A failed session leaves the label in place, and the manager will not start another for the same, stale authorisation — otherwise a labelled issue with a failing session would spawn a fresh agent every minute. Re-applying the label is how a person asks for another attempt, and the only way.
  • The issue body is untrusted input, even after authorisation. It is delimited in the agent’s prompt and never interpolated into commands, paths or branch names.

Issues the watcher refuses are refused visibly: the app’s Issues tab shows “not authorised” with the manager’s reason under it. A paired phone can still start that work explicitly — the person holding it has already authenticated, and a missing label should not punish them for something somebody else did or did not click.

Sessions get better inputs from structured issues. Use an issue form that collects a goal, acceptance criteria, technical context, testing expectations and constraints; the app’s create issue screen produces the same structure, so an issue written on a phone and one written in a browser reach the agent in the same shape.

The watcher polls once per intervalSeconds per registered repository, filtered server-side by both labels — about a minute of latency against GitHub’s 5000 requests/hour budget. That is the price of needing no open port.