Skip to content

Reference

The commands of issue_assistant.py, the inputs and outputs of the action that runs them, the AI engines that it supports, and how to try a prompt on your own computer.

Commands

The action runs issue_assistant.py with one command:

Command Job What
event event handles the event and the slash command of a comment, sets labels and names the AI's next task, within the limits of the AI runs
engine analyze names the engine of config.toml and whether its secret exists, and the model, turns, dollars and effort of the task
context analyze writes what the task reads into .issue-assistant/: the issue; for an analysis or a follow-up the other issues, the discussions and the labels; for a reply or a question the comment of its event; then the rules, the task and the schema
usage analyze writes the turns, time, cost and tokens of the engine's run into the summary of the job, numbers only, and a warning when the run stopped at its turns or its dollars
apply apply checks the AI's answer and posts it
sweep lifecycle reminds, closes unanswered issues and duplicates, marks fixed issues and closes them with the release
sync-labels labels creates and updates the labels, and renames those that the repository has in another case
findings findings dismisses the accepted findings of code scanning and fails while others are open; needs no other settings
check your CI checks labels, issue forms, workflows, firewall, settings, the description of the project and the notice to reporters, and names every key it doesn't know

install runs from a git checkout of a release, as Set up a repository shows, and pins its commit and tag; --ref and --version name them for another checkout. install --setup also creates the environment issue-assistant for the default branch and has the GitHub CLI ask for the engine's secret. install, check, engine and usage read only the checkout, and install --setup the environment too; the other commands call GitHub, for the repository that GH_REPO names as owner/name, or else the workflow's GITHUB_REPOSITORY. Every command but install and check takes dry-run: true to only report what it would write; runs by hand under Actions → Issue assistant → Run workflow start as dry runs, and their summary shows the comment, as the last step of the set-up shows.

Inputs and outputs of the action

The workflows of the templates set the inputs of the action; a workflow of your own, such as the check in the CI, sets command, and for a command that writes maybe dry-run. The tables come from action.yml of this version.

Inputs

Input Required Default What it is
command yes none event, engine, context, apply, usage, sweep, sync-labels, findings or check
issue no none Number of the issue, for context, apply and usage
mode no none Task of the engine (triage, follow-up, maintainer-reply, release-reply or maintainer-question), for engine, context, apply and usage
answer no none The engine's JSON answer, for apply
engine no none The engine that wrote the answer, for apply
ready-engines no none Engines whose secret exists, separated by commas, for engine
execution-file no none The execution file of the engine's action, whose numbers usage reports
dry-run no false Only report what would be written
github-token no ${{ github.token }} Token for the GitHub API; the job's permissions limit it

Outputs

The commands event, engine and context set the outputs for the steps and jobs after them.

Output What it is
issue The issue of the event
mode The engine's next task, or none
engine The engine of the repository's config.toml
ready Whether the engine's secret exists
model The engine's model for the task
turns The most turns of the engine for the task
budget The most dollars that the engine's run may cost
effort The engine's effort, or empty for its default
task The task for the engine, which the rules in .issue-assistant/rules.md precede as its system prompt
prompt The rules and the task in one prompt, for templates before the rules became a system prompt
schema The JSON schema of the engine's answer

Engines

Everything except one step of the analyze job is independent of the AI: the context, the prompts in prompts/, the checks and every write. An engine gets the read-only checkout with the context in .issue-assistant/, the rules as its system prompt, the task and the JSON schema of its answer (as files and as outputs of the context step), and the model, turns, dollars and effort of the task from the step engine, and returns the JSON answer. apply validates it whether or not the engine could enforce the schema, and also accepts it in a code fence.

Engine Step Secret Restrictions
claude (default) anthropics/claude-code-action CLAUDE_CODE_OAUTH_TOKEN or ANTHROPIC_API_KEY --restricted --tools "Read,Grep,Glob", the rules with --append-system-prompt-file, --max-turns and --max-budget-usd, schema with --json-schema

To add one, for example OpenAI Codex with openai/codex-action (prompt-file, output-schema-file and a read-only sandbox) or the GitHub Copilot CLI in programmatic mode (only reading tools, the JSON asked for in the prompt): add it to ENGINES in issue_assistant.py with its secrets, the one that install --setup asks for first, give it a step with its key as id in templates/.github/workflows/issue-assistant.yml with the same condition as the Claude step, add its secret to ready-engines and its answer to the job output answer, pass it the rules, the turns and the dollars of the task, give usage the numbers of its run, add its hosts to templates/.github/egress-firewall.yaml in a block of its own, and its rules to ENGINE_RULES in tests/test_templates.py, which keeps it read-only.

Try a prompt locally

export GH_REPO=OWNER/REPO DRY_RUN=true
python3 issue_assistant.py context --issue 12 --mode triage    # in the repository's checkout
claude -p "$(cat .issue-assistant/prompt.md)" --restricted --tools "Read,Grep,Glob" \
  --append-system-prompt-file .issue-assistant/rules.md --max-turns 40 --max-budget-usd 1 \
  --json-schema "$(cat .issue-assistant/schema.json)" --output-format json > answer.json
RESULT="$(jq -c .structured_output answer.json)" python3 issue_assistant.py apply --issue 12 --mode triage

To try it on an issue that exists nowhere, write the issue and its comments into a JSON file, as GitHub's REST API gives them, and name the file in ISSUE_ASSISTANT_FIXTURE, relative to the checkout. context and apply then read that issue instead of one on GitHub, take its number, and write nothing, as in a dry run; the other issues, the discussions and the labels still come from GitHub. The issue of the project's own canary, tests/fixtures/canary-issue.json, is an example:

gh api repos/OWNER/REPO/issues/12 | jq '{issue: ., comments: []}' > issue.json    # then change it
export ISSUE_ASSISTANT_FIXTURE=issue.json
python3 issue_assistant.py context --mode triage