inference-gateway/Infer Agent Action
Run Infer CLI agent on GitHub issues with support for multiple AI providers, automatic pull request creation, and progress tracking
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jul 10, 2026
- License
- Apache 2.0
Pinned Snippet
uses: inference-gateway/infer-action@da40fb918f287d5e8a7d688e782e7ae069cf1a50 # v0.31.2tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| github-token | GitHub token for posting comments and accessing API | yes | — |
| github-app-slug | Slug of the GitHub App whose bot identity should author the agent's commits (e.g. "infer-bot"). When set, commits are attributed to "<slug>[bot]" and the numeric id is resolved via GET /users/{slug}[bot] (which works with an App installation token, unlike GET /user). Falls back to github-actions[bot] when empty or if the lookup fails. | no | "" |
| trigger-phrase | Phrase to trigger the agent (e.g., @infer) | no | @infer |
| direct-prompt | Free-text task to run directly, bypassing issue/comment trigger detection. When non-empty, the agent runs against this text instead of an issue or comment body, so the action works under `workflow_dispatch` (or any event) with no issue/PR thread required. In this mode the agent commits to a new branch and opens a PR (honoring `enable-git-operations`), and the result plus PR link are written to the job summary. A `/model` override embedded in the text is honored, as in event-driven mode. Leave empty (the default) for normal issue/comment-triggered behavior. | no | "" |
| model | Model to use (e.g., anthropic/claude-opus-4-8, openai/gpt-5, google/gemini-3-pro). | yes | — |
| version | Infer CLI version to install (default: v0.152.0) | no | v0.152.0 |
| ollama-cloud-api-key | Ollama Cloud API key (required if using Ollama Cloud models) | no | — |
| groq-api-key | Groq API key (required if using Groq models) | no | — |
| openai-api-key | OpenAI API key (required if using OpenAI models) | no | — |
| cloudflare-api-key | Cloudflare API key (required if using Cloudflare models) | no | — |
| cohere-api-key | Cohere API key (required if using Cohere models) | no | — |
| anthropic-api-key | Anthropic API key (required if using Anthropic models) | no | — |
| deepseek-api-key | DeepSeek API key (required if using DeepSeek models) | no | — |
| google-api-key | Google API key (required if using Google/Gemini models) | no | — |
| mistral-api-key | Mistral API key (required if using Mistral models) | no | — |
| minimax-api-key | MiniMax API key (required if using MiniMax models) | no | — |
| moonshot-api-key | Moonshot API key (required if using Moonshot models) | no | — |
| nvidia-api-key | Nvidia API key (required if using Nvidia models) | no | — |
| zai-api-key | Zai API key (required if using Zai models) | no | — |
| llamacpp-api-url | llama.cpp API URL (required if using llama.cpp models) | no | — |
| ollama-api-url | Ollama API URL (required if using Ollama models) | no | — |
| max-turns | Maximum number of agent iterations (default: 150) | no | 150 |
| custom-instructions | Custom instructions to append to the default agent instructions (which include plan creation, progress tracking, file changes, and PR workflow) | no | "" |
| system-prompt-issue | Override the bundled system prompt for issue triggers (issue opened/edited or comments on real issues). Substitutes `{{issueNumber}}`. Leave empty to use the default at src/prompts/system-issue.md in the action repo. This REPLACES (not merges with) the action's bundled default prompt. Whichever prompt results (override or bundled) replaces the CLI's own base system prompt text, while the CLI still appends its dynamic context block (skills, memory, tools, sandbox and bash allow-list info) because the action pins `INFER_AGENT_SYSTEM_PROMPT_WITH_DEFAULTS=true`. The bundled default carries the branch-first / commit-per-todo / push / draft-PR / finish-checklist git-safety block. If your override omits those instructions the action emits a `::warning::` in the run log so the lost-work guard isn't dropped silently. Prefer `custom-instructions` to layer extras on top of the default unless you need a full replacement. | no | "" |
| system-prompt-pr | Override the bundled system prompt for PR-comment triggers on same-repo PRs. Substitutes `{{prNumber}}`, `{{headRef}}`. Leave empty to use the default at src/prompts/system-pr.md in the action repo. This REPLACES (not merges with) the action's bundled default prompt. Whichever prompt results (override or bundled) replaces the CLI's own base system prompt text, while the CLI still appends its dynamic context block (skills, memory, tools, sandbox and bash allow-list info) because the action pins `INFER_AGENT_SYSTEM_PROMPT_WITH_DEFAULTS=true`. The bundled default carries the commit/push discipline and the "no [ahead" finish check. If your override omits those instructions the action emits a `::warning::` in the run log. Prefer `custom-instructions` to layer extras on top of the default. | no | "" |
| system-prompt-pr-fork | Override the bundled system prompt for PR-comment triggers on fork PRs (view-only). Substitutes `{{prNumber}}`, `{{headRef}}`, `{{headRepoFullName}}`, `{{baseRef}}`. Leave empty to use the default. This REPLACES (not merges with) the action's bundled default prompt. Whichever prompt results (override or bundled) replaces the CLI's own base system prompt text, while the CLI still appends its dynamic context block (skills, memory, tools, sandbox and bash allow-list info) because the action pins `INFER_AGENT_SYSTEM_PROMPT_WITH_DEFAULTS=true`. The bundled default's git-safety guard is the explicit do-not-commit / do-not-push prohibition. If your override omits those instructions the action emits a `::warning::` in the run log. Prefer `custom-instructions` to layer extras on top of the default. | no | "" |
| system-prompt-direct | Override the bundled system prompt for direct-prompt (`workflow_dispatch`) runs. No variables. Leave empty to use the default at src/prompts/system-direct.md in the action repo. This REPLACES (not merges with) the action's bundled default prompt. Whichever prompt results (override or bundled) replaces the CLI's own base system prompt text, while the CLI still appends its dynamic context block (skills, memory, tools, sandbox and bash allow-list info) because the action pins `INFER_AGENT_SYSTEM_PROMPT_WITH_DEFAULTS=true`. The bundled default carries the branch-first / commit-per-todo / push / draft-PR / finish-checklist git-safety block. If your override omits those instructions the action emits a `::warning::` in the run log so the lost-work guard isn't dropped silently. Prefer `custom-instructions` to layer extras on top of the default unless you need a full replacement. | no | "" |
| reminders-config | Verbatim reminders YAML passed to the CLI via INFER_REMINDERS_CONFIG, REPLACING the action's composed default. Use this to take full control of the CLI's native reminders system (hooks, triggers, cadences, custom nudges) for power-user scenarios the composed default doesn't cover. The composed default sets `merge: true`, layering a per-context reminder (pre_stream, interval), a `turns_before_max` wrap-up near the turn limit, and a post_tool `on_failure` nudge (fires only after a failed tool call on writable runs) onto the CLI's built-in defaults - so the built-in todo-hygiene and memory reminders stay intact. A non-empty reminders-config replaces the composed default entirely; add `merge: true` to your own config to keep the CLI built-ins, or omit it to replace them. See the Infer CLI `config/reminders.go` for the schema: top-level `enabled:` + optional `merge:` + a `reminders:` list of `{name, hook, trigger, interval?, threshold?, text}` entries. Hook points: pre_session, pre_stream, post_stream, pre_tool, post_tool, pre_queue_drain, post_queue_drain, post_session. Triggers: always, interval, turns_before_max, once, on_failure (on_failure requires hook: post_tool). Needs CLI >= v0.130.0. Leave empty to use the composed default. | no | "" |
| task-issue | Override the bundled task template for issue triggers. Substitutes `{{issueNumber}}`, `{{issueTitle}}`, `{{issueBody}}`, `{{triggeringCommentSection}}`. Leave empty to use the default. | no | "" |
| task-pr | Override the bundled task template for PR-comment triggers. Substitutes `{{prNumber}}`, `{{prTitle}}`, `{{headRef}}`, `{{baseRef}}`, `{{forkNotice}}`, `{{prBody}}`, `{{triggerSection}}`, `{{otherCommentsSection}}`, `{{diffStatSection}}`. Leave empty to use the default. | no | "" |
| task-direct | Override the bundled task template for direct-prompt runs. Substitutes `{{prompt}}`. Leave empty to use the default. | no | "" |
| bash-allow-append | Comma/newline-separated Go regex entries appended to the Infer CLI's read-only bash allow-list in every agent mode (maps to INFER_TOOLS_BASH_ALLOW_APPEND). The CLI owns the read-only baseline - file reads, read-only git/gh, and `gh project` (list/view/item-list/ field-list) - so you no longer pass those. When git operations are enabled the action additionally appends the writes its PR workflow needs (git add/commit/push/checkout/ switch/fetch and `gh pr create`; never `gh pr merge`/`close`/`edit`/`review`). Use this input to add project tooling. Each entry is anchored to the WHOLE command, so include arguments explicitly, e.g. "npm( .*)?,pnpm( .*)?,go test( .*)?". To *replace* the baseline (rather than append) configure the CLI's .infer/config.yaml directly. | no | "" |
| web-fetch-domains | Comma-separated list of domains the WebFetch tool may fetch from. The action passes this to the CLI as the INFER_TOOLS_WEB_FETCH_ALLOWED_DOMAINS env var (which maps to tools.web_fetch.allowed_domains and takes precedence over the config file), REPLACING the CLI default. Leave empty to use the action default "github.com,raw.githubusercontent.com,api.github.com". | no | "" |
| memory-repo | Git remote URL backing the agent's persistent cross-run memory (ssh or https, e.g. "git@github.com:my-org/agent-memory.git" or "https://github.com/my-org/agent-memory"). When set, the action enables the Infer CLI's memory git backend (maps to INFER_MEMORY_ENABLED=true, INFER_MEMORY_BACKEND_TYPE=git and INFER_MEMORY_BACKEND_GIT_REPO): the CLI pulls memory on run start and commits + pushes when a fact changes. Leave empty (the default) to keep the feature off entirely - no memory env vars are set, so a consumer's own .infer/memory.yaml is untouched. Requires Infer CLI >= v0.127.0. See also memory-deploy-key / memory-token for auth. | no | "" |
| memory-branch | Branch of memory-repo to sync (maps to INFER_MEMORY_BACKEND_GIT_BRANCH). Leave empty to use the CLI default ("main"). Only used when memory-repo is set. | no | "" |
| memory-sync-on-start | Whether the CLI pulls the memory repo at run start: "pull" or "off" (maps to INFER_MEMORY_BACKEND_GIT_SYNC_ON_START). Leave empty to use the CLI default ("pull"). Only used when memory-repo is set. | no | "" |
| memory-sync-on-finish | Whether the CLI pushes memory changes at run finish: "push" or "off" (maps to INFER_MEMORY_BACKEND_GIT_SYNC_ON_FINISH). Leave empty to use the CLI default ("push"). Only used when memory-repo is set. | no | "" |
| memory-deploy-key | SSH private key (e.g. a GitHub deploy key with write access) used to authenticate the memory-repo remote when it is an ssh URL. Written to ~/.ssh/infer-memory-deploy-key and wired via core.sshCommand before the agent runs; removed again in cleanup. Only used when memory-repo is an ssh URL. | no | "" |
| memory-token | Token used to authenticate the memory-repo remote when it is an https URL (applied as a git insteadOf rewrite scoped to that repo; removed again in cleanup). When memory-repo is an https URL on this GitHub instance and neither memory-token nor memory-deploy-key is set, the action falls back to github-token - which only works for repos that token can write, e.g. a memory branch of the workflow repo itself. | no | "" |
| enable-git-operations | Enable git operations (checkout, add, commit, push). Default: true. Set to false if you want the agent to only post comments without creating PRs. | no | true |
| enable-heuristic-redaction | Apply regex heuristics to redact unknown token shapes (ghp_*, github_pat_*, sk-*, AIza*, xox[bpoa]-*, and JWTs) from the cooking comment and step summary, on top of the known-value redaction that always runs. May false-positive on legitimate strings. Default: false. | no | false |
| mirror-agent-logs | Mirror the agent's verbose stdout transcript to this step's workflow log. When true, every line the agent emits on stdout - tool inputs, outputs, file contents, web-fetch payloads - appears in the Actions run log. Defaults to false (suppressed); set to true to mirror it. The agent's stderr (crashes, panics, stack-traces) is always mirrored so failures stay visible, and the /tmp/agent-output.txt file that post-results reads for the cooking comment footer is always written - both regardless of this setting. A minimal heartbeat (ticker updates, exit code) still prints so the step isn't entirely silent. Default: false. | no | false |
| no-color | Disable colored output from Infer CLI commands (traces, stats, etc.). Passes --no-colors to the CLI and sets NO_COLOR=1 in the environment. Useful when the agent's result comment contains raw ANSI escape sequences (mojibake) from piped command output. Default: false. | no | false |
| skills | Newline-separated list of Infer skills to install before the agent runs. Each entry is passed to `infer skills install`. Lines starting with `#` are treated as comments. When non-empty, skills are auto-enabled for the agent (INFER_AGENT_SKILLS_ENABLED=true). Accepted entry forms (per `infer skills install --help`): - Bare skill name: maintainer -> https://github.com/inference-gateway/skills/tree/main/skills/maintainer - <org>/<skill> pair: acme/internal-comms -> https://github.com/acme/skills/tree/main/skills/internal-comms - Full GitHub URL: https://github.com/anthropics/skills/tree/main/skills/pdf Examples: skills: maintainer skills: | maintainer acme/internal-comms skills: | # first-party maintainer # custom layout / pinned branch https://github.com/my-org/agent-bundles/tree/v1.2/skills/triage | no | "" |
| plugins | Newline-separated list of Infer plugins to install before the agent runs. Each entry is passed to `infer plugins install`. Lines starting with `#` are treated as comments. Blank lines are ignored. Accepted entry forms (per `infer plugins install --help`): - owner/repo: DietrichGebert/ponytail - owner/repo@ref: DietrichGebert/ponytail@v1.0.0 - Full GitHub URL: https://github.com/DietrichGebert/ponytail or https://github.com/DietrichGebert/ponytail/tree/v1.0.0 Each entry is installed with `--yes` (non-interactive). A failing install fails the step with a log line naming the entry. Security model: plugins are content-only mapping (skills + instructions). Plugin code (hooks/, commands/, agents/) is detected but never executed or installed by the CLI. See the Infer CLI documentation for details. Examples: plugins: DietrichGebert/ponytail plugins: | DietrichGebert/ponytail my-org/my-plugin@v2.1.0 plugins: | # community plugin DietrichGebert/ponytail # pinned ref https://github.com/my-org/agent-plugins/tree/v1.0 | no | "" |
| agents | Comma/newline-separated list of A2A (Agent-to-Agent) agents to spin up as local Docker containers when the agent runs. Each entry is either: - A first-party agent name the CLI already knows - `browser-agent`, `mock-agent`, `google-calendar-agent`, `documentation-agent`, or `n8n-agent`. The CLI fills in the OCI image and localhost URL itself. - A `name=oci-image` pair to register a custom image, e.g. `my-agent=ghcr.io/my-org/my-agent:latest`. Lines starting with `#` are treated as comments. For each entry the action runs `infer agents add ... --run --model <model>` (writing the local `.infer/agents.yaml`, which is hidden from git), enables it, and turns on A2A (`INFER_A2A_ENABLED=true`) so `infer agent` starts the containers and exposes them to the model via the A2A tools. Agents default to the same `model` as the main run; configure `.infer/agents.yaml` directly for per-agent models. Registration is best-effort: an unknown name or a failed add logs a warning and is skipped rather than failing the run. Docker must be available on the runner (the default `ubuntu-24.04` runner has it pre-installed). This is an advanced, experimental feature. Examples: agents: browser-agent agents: | browser-agent documentation-agent agents: | # first-party agent browser-agent # custom image my-agent=ghcr.io/my-org/my-agent:latest | no | "" |
| debug | Enable debug-level logging in the Infer CLI and emit diagnostic stream events (system reminder injections, conversation compaction triggers) on the agent's stdout - visible in this step's workflow log. Hidden by default. Turn on when investigating why the agent ignored its system prompt or whether reminders are firing. | no | false |
| compact-auto-at | Auto-compaction threshold as a percentage of the model's context window. When the conversation's input tokens cross this percent, the CLI runs an LLM-summarised compaction that drops older turns while preserving the first messages. Default 50. Lower to compact earlier (preserves headroom at the cost of summarised context), raise to delay summarisation. Accepted range 20-100. | no | 50 |
| mock-agent-scenario | Which mock scenario the bundled mock agent runs when dry-run is true. One of: - happy Three TodoWrite passes + Read + a commit on a fix/ branch (exercises PR-link) - failures Happy path with interspersed envelope and inner tool-call failures - no-todos Agent does work but never calls TodoWrite - empty Agent exits immediately with no tool calls - incomplete Agent is cut off mid-plan (stopped-early signal) - no-git Agent edits files but never commits/pushes (salvage from a dirty tree) - commit-no-push Agent commits on the fix branch but never pushes, exits 0 (salvage of unpushed commits) - hang Agent wedges inside compaction and never exits (timeout/cancel path) | no | happy |
| dry-run | Plan-only mode for local testing (e.g. with `act`). Forces the bundled mock agent (no real CLI install, no provider tokens), and SIMULATES every GitHub mutation - comments, the eyes reaction, the cooking comment, comment zone updates, spinner clear - printing a `[dry-run] would ...` line instead of calling the API. The runner also prints a "DRY RUN" banner with the exact SYSTEM/TASK/REMINDER prompts and tool whitelists the agent would receive. GitHub READ calls still execute (so you see the real target issue/PR), and degrade gracefully when no token is available. | no | false |
| otel-exporter-otlp-endpoint | OpenTelemetry OTLP HTTP endpoint for telemetry export (e.g. http://localhost:4318). When empty (the default), no OTel env vars are set and the CLI does not export telemetry. Passed through to the `infer` CLI subprocess as the OTEL_EXPORTER_OTLP_ENDPOINT env var - the CLI emits metrics, traces, and logs natively from real internal signals. | no | "" |
| otel-exporter-otlp-headers | Comma-separated key=value headers for the OTLP HTTP requests (e.g. "Authorization=Bearer my-token"). These are secret and auto-masked. Passed through to the `infer` CLI subprocess as the OTEL_EXPORTER_OTLP_HEADERS env var. | no | "" |
| otel-service-name | Value for the service.name resource attribute on exported telemetry. Defaults to "infer-action". Passed through to the `infer` CLI subprocess as the OTEL_SERVICE_NAME env var. | no | infer-action |
| otel-resource-attributes | Extra resource attributes in key=val,key2=val2 format, appended to the standard set the CLI emits. Passed through to the `infer` CLI subprocess as the OTEL_RESOURCE_ATTRIBUTES env var. The CLI also adds GitHub Actions context (actor, repo, run id, workflow url) automatically. | no | "" |
Outputs
| name | description |
|---|---|
| result | Result of the agent execution |
| exit-code | Exit code from agent command (normalised to 0 on a job-timeout stop, where the work is recovered into a draft PR) |
| pr-url | URL of the pull request the agent opened on its branch, or the draft PR the salvage step opened when an interrupted run left work unpushed (empty if none) |
| run-duration-ms | Wall-clock duration of the agent run in milliseconds (0 if unavailable) |
| stopped-early | true if the agent stopped before finishing its plan (unfinished todos, uncommitted work left behind, or a job-timeout stop) |
| timed-out | true if the agent was stopped because the job hit its timeout-minutes before it finished (work is recovered into a draft PR; reported as ⚠️ stopped early, not a failure) |
| failed-tool-calls-count | Number of failed tool calls detected in agent output |
| total-tool-calls-count | Total number of tool calls made by the agent |