Based on: A worked playbook on GitHub's issues webhook, written from the bundled github-issue-triage example skill.
The situation
An issue arrives. The first useful thing is a look at the code with the issue in hand: does it reproduce, where is it, is it one change or a decision. The bundled github-issue-triage example skill does that look and either fixes or triages. This playbook keeps it and adds the two things people ask for: a design question goes to a person before any code is written, with the readings as buttons, and the answer resumes the run; and nothing merges without a person.
How it runs
- GitHub. A repository webhook for the Issues event only, pointed at the skill's hosted URL on Skillhook Cloud, with a secret skillhook generated. GitHub's
pingarrives first and shows as skipped: the filter did its job. - The machine. On its next sync it collects the delivery, verifies
X-Hub-Signature-256with the secret in its.env, and applies the filters:X-GitHub-Eventisissues,actionisopenedorlabeled. GitHub's delivery id de-duplicates redeliveries. - The job. Should it run at all (the
agentlabel, the right checkout, an earlier comment of its own)? Then investigate in the local clone, reproduce where possible, and decide: fix, ask, or triage. A fix is a branch, a change with a test that fails without it, a pull request and a comment linking it; a triage is one comment with what was checked, the likely cause and at most five questions. - The inbox. The job under
#N: the title, its headlineFix: PR #M,Triage: comment postedor the question it is waiting on, with the issue, the pull request and the comment as links.
Set it up with your agent
Paste this into Claude Code or Codex with the skillhook plugin. It installs skillhook and the GitHub CLI, creates the skill, has you generate the webhook secret in your own terminal, turns on the hosted URL, and walks you through GitHub's webhook form and a test issue. Paste the SKILL.md from the next section as your second message.
The skill
The bundled example with three changes: a design question is asked with job_ask_human and ends the run with needs_human when nobody answers in time; the outcome goes into response.json with the links the inbox groups; and merging is never the skill's. Every frontmatter field is one skillhook validates.
Where a person comes in
- Design questions. When the expected behaviour has more than one reasonable reading, or the fix changes an interface, a default or a behaviour others rely on, the skill asks once: the question in a sentence, the readings as options (at most four, one recommended), what each would change as context. It waits up to thirty minutes with the job's timeout clock paused; a decision it cannot make ends the run with
needs_human, the same question and options. The inbox shows the buttons, theneeds_humanalert goes out, and the pick resumes the agent's session, which then opens the pull request. - Nothing merges without a person. The skill never merges, never turns on auto-merge, never pushes to the default branch. A pull request is the handover: a person reviews it, and nothing deploys to production without that yes.
- Another look. Adding the
agentlabel to an issue re-triggers the skill, for example after the reporter answered the triage questions.
What to check after
- Deliveries. The
pingas skipped; each issue event as accepted with its job; a rejected delivery names the reason (invalid_signatureafter a secret was changed on one side only). - The job. Its headline and links;
stdoutfor what the agent tried when a fix did not come. - Replay once a cause is fixed (the secret, a
ghlogin that expired, the clone on the wrong branch):replay_deliveryruns the issue again, and the skill's first step finds its own earlier comment or pull request and adds nothing twice.