misospace/Miso PR Review
Review pull requests with OpenAI- or Anthropic-compatible models and post an optional sticky comment.
View on GitHubTrust Signals
- Scorecard Score
- not yet scored
- Maintenance Recency
- Activelast commit Jul 9, 2026
- License
- MIT
Pinned Snippet
uses: misospace/pr-reviewer-action@a177c3478b52a6f8402ebbe9a0ba59c61cf028ed # v2.1.2tags can be moved; commit SHAs can't. why a SHA?
Inputs
| name | description | required | default |
|---|---|---|---|
| github_token | GitHub token for PR and API access | yes | — |
| repo | Repository in owner/name format. Defaults to the current workflow repository. | no | "" |
| pr_number | Pull request number. Defaults to the current pull_request event number. | no | "" |
| ai_base_url | Base URL of the primary AI API | yes | — |
| ai_api_format | API request/response format for the primary AI endpoint (openai or anthropic) | no | openai |
| ai_model | Model name for the primary analysis pass | yes | — |
| ai_api_key | Optional API key for the primary AI endpoint | no | "" |
| ai_max_tokens | Maximum completion tokens for the primary and fallback final review calls. Default 8192. Reasoning models that emit a thinking channel need this headroom — too low a cap is consumed by reasoning, leaving empty content with finish_reason=length, so the verdict JSON fails to parse and the review needlessly escalates or fails. Raise further (e.g. 16000) for verbose reasoning models. | no | 8192 |
| ai_temperature | Sampling temperature for the review model. Default "0.1". Set to an empty string to omit the field entirely (some newer cloud models reject any non-default temperature). | no | 0.1 |
| ai_response_format | Structured-output mode for OpenAI-compatible endpoints (including LiteLLM): off (default), json_object, or json_schema (enforces a verdict/review_markdown schema). Ignored for the anthropic format. Improves output reliability with smaller local models. Applies to both the primary and fallback review calls. | no | off |
| ai_tokens_param | Token-limit field name for OpenAI-compatible requests: max_tokens (default) or max_completion_tokens (required by newer OpenAI reasoning models). Ignored for anthropic. | no | max_tokens |
| anthropic_version | Anthropic API version header used when ai_api_format or ai_fallback_api_format is anthropic | no | 2023-06-01 |
| ai_fallback_base_url | Optional base URL of a fallback AI API | no | "" |
| ai_fallback_api_format | Fallback API request/response format; defaults to ai_api_format when blank | no | "" |
| ai_fallback_model | Optional model name for the fallback analysis pass | no | "" |
| ai_fallback_api_key | Optional API key for the fallback endpoint | no | "" |
| ai_primary_retries | Number of retries for the primary model | no | 8 |
| ai_primary_retry_delay_sec | Delay between primary retries in seconds | no | 15 |
| on_model_failure | Behavior when both primary and fallback models fail to return a usable review. 'fail' (default) fails the action step. 'notice' instead posts a visible request_changes notice explaining the review could not run (never auto-approves), so reviewers see an explanation instead of only a red check. | no | fail |
| verdict_policy | How the final verdict is decided. 'model' (default) uses the model's own verdict. 'findings_severity_gated' preserves request_changes from the model and escalates approve to request_changes when any blocker-severity finding exists. Non-blocker findings never weaken a model rejection. Enforcement settings (evidence blockers, tool failure) still apply afterwards and can force request_changes. | no | model |
| inline_findings | If true, structured findings that anchor to a line in the PR diff are attached as native line-anchored review comments when publishing with publish_mode=review_comment or review_verdict. Findings that cannot be anchored stay in the review body only. Default false — no inline comments. Ignored for publish_mode=comment. | no | false |
| inline_findings_max | Maximum inline review comments attached per review when inline_findings=true. | no | 20 |
| validate_required_checks | Whether to validate the final review against the classifier's must_check items. 'auto' (default) validates whenever must_check is non-empty; 'true' and 'false' force it on or off. Validation is deterministic keyword matching — it catches reviews that never discussed a required check, not incorrect discussion. | no | auto |
| required_check_validation_mode | What to do when required checks are unaddressed. 'warn' (default) appends an 'Unaddressed required checks' section to the published review. 'fail' also forces a request_changes verdict. 'metadata_only' records the result (required_checks output and metadata marker) without changing the published review. | no | warn |
| review_routing_mode | Route PR reviews between the primary and smart models based on the deterministic classification. 'off' (default) preserves existing primary/fallback behavior. 'auto' sends PRs whose pr_kind or risk_flags match escalate_on_risk_flags to the smart model (when one is configured) and keeps everything else on the primary model. | no | off |
| ai_primary_model | Model for the primary review route when review_routing_mode=auto. Defaults to ai_model. | no | "" |
| ai_primary_base_url | Base URL for the primary route model. Defaults to ai_base_url. | no | "" |
| ai_primary_api_format | API format for the primary route model (openai or anthropic). Defaults to ai_api_format. | no | "" |
| ai_primary_api_key | API key for the primary route model. Defaults to ai_api_key. | no | "" |
| ai_smart_model | Opt-in smarter model for high-risk reviews (review_routing_mode=auto). With no smart model set, auto-routing stays on the primary model and never escalates. The fallback model is NEVER an escalation target — it only catches a primary-availability failure. | no | "" |
| ai_smart_base_url | Base URL for the smart model. Defaults to ai_base_url. | no | "" |
| ai_smart_api_format | API format for the smart model (openai or anthropic). Defaults to ai_api_format. | no | "" |
| ai_smart_api_key | API key for the smart model. Defaults to ai_api_key. | no | "" |
| escalate_on_risk_flags | Comma-separated pr_kind / risk_flag names that route directly to the smart model when review_routing_mode=auto. Matched against route_signals — linked-issue flags and file-based signals backed by an actual changed filename — so a benign PR whose diff merely mentions a pattern (e.g. os.path) does not route. | no | linked_security_issue,linked_priority_p0,linked_priority_p1,auth_changes,public_route_changes,file_serving_changes,path_handling_changes,secret_handling_changes,db_or_migration_changes |
| escalate_on_incomplete_required_checks | Escalate a primary-route review to the smart model when required checks are unaddressed (review_routing_mode=auto only). | no | true |
| escalate_on_fast_request_changes | Escalate a primary-route review to the smart model when its verdict is request_changes (review_routing_mode=auto only). | no | true |
| escalate_on_fast_low_confidence | Escalate when the primary-route review is low-confidence — a stub review (below ~80 chars) or one carrying a populated Unknowns/Needs Verification section. A concise, confident review is NOT escalated regardless of diff size. review_routing_mode=auto only. | no | true |
| escalate_on_tool_or_evidence_blockers | Escalate when evidence providers report blocker severity or every executed tool request failed (review_routing_mode=auto only). | no | true |
| escalate_on_tool_planning_failure | Escalate when the tool harness planning call failed (review_routing_mode=auto only). Off by default: a planning failure means the review ran with less evidence — the same situation as tool_mode 'off' — not that the PR is risky. The failure is still recorded in tool-harness.json and the step summary. | no | false |
| escalate_on_dirty_baseline | Escalate incremental reviews whose baseline review found issues (review_routing_mode=auto only). Judging whether a delta resolves a previously-found blocker is exactly the judgment worth running on the smart model. | no | true |
| ai_stream | If true, use streaming responses to avoid timeouts behind proxies with short read timeouts (e.g. Cloudflare 100s edge timer) | no | true |
| ai_fallback_stream | If set, overrides ai_stream for the fallback model; defaults to ai_stream value when blank | no | "" |
| allowed_source_hosts | Comma-separated list of hosts allowed for linked source fetching | no | github.com,api.github.com,gitlab.com,registry.terraform.io,artifacthub.io |
| system_prompt | Optional system prompt override | no | "" |
| system_prompt_file | Optional file path in the reviewed repository to use as the full system prompt | no | "" |
| system_prompt_mode | How a supplied system_prompt / system_prompt_file combines with the bundled default. 'replace' (default) uses the supplied prompt verbatim. 'append' keeps the conditionally-assembled bundled default and appends the supplied prompt as a repo-specific addendum — so consumers add conventions without copying (and re-syncing) the whole default. | no | replace |
| standards_file | Repository standards file path for conventions and policy context | no | "" |
| standards_file_candidates | Candidate files to auto-discover when standards_file is not set. First found is used. | no | AGENTS.md,agents.md,CLAUDE.md,claude.md,.github/ai-review-rules.md,.github/ai-review-rules.txt |
| publish_review_comment | If true, publish or update a PR comment with the generated review | no | false |
| publish_mode | Publish mode for the review verdict. 'comment' publishes a sticky PR comment (default). 'review_comment' uses GitHub's native PR review API to submit a non-blocking review comment. 'review_verdict' uses GitHub's native PR review API to submit approve/request_changes. Requires permissions: pull-requests: write for review_comment and review_verdict modes. | no | comment |
| allow_approve | If true and publish_mode=review_verdict, the model's approve verdict can be submitted as a native approval. Defaults to false — approval is blocked unless explicitly enabled. WARNING: native approvals can affect branch protection rules and automerge pipelines. | no | false |
| approve_forks | If true and publish_mode=review_verdict with allow_approve=true, native approvals are also allowed for cross-repository (fork) PRs. Defaults to false — fork PRs are blocked from approval even when allow_approve is set. | no | false |
| cleanup_previous_native_reviews | Mark previous managed native PR reviews as outdated/superseded before publishing a new native review. Accepted values: `auto` (default, enables cleanup for review_comment and review_verdict modes), `true`, or `false`. Cleanup only targets reviews created by this action and carrying the managed marker. Dismissal of old approval/request-changes reviews is attempted when permissions allow but is secondary to visual cleanup. | no | auto |
| context_limit_mode | Context budget mode - normal (140k/70k/220k), low (80k/40k/120k), minimal (40k/20k/60k) | no | normal |
| model_context_tokens | The model's real context window in tokens (e.g. 8192, 32768). When set, corpus/diff/file byte budgets are derived from it (reserving ai_max_tokens for output) instead of context_limit_mode — recommended for local models whose windows are smaller than the named modes assume. Empty uses context_limit_mode. | no | "" |
| enrichment_budget_sec | Maximum seconds to spend on enrichment (linked source fetching, release metadata, ghcr.io lookups). Exceeding the budget stops further enrichment. Default 60. | no | 60 |
| image_digest_budget_sec | Maximum seconds to spend on image digest provenance lookups (registry tokens, manifests, revision compares). 0 disables the budget. Default 60. | no | 60 |
| evidence_providers_file | Optional JSON file in the reviewed repository that defines evidence providers to run before review | no | "" |
| evidence_provider_timeout_sec | Default timeout in seconds for each evidence provider command | no | 30 |
| evidence_provider_max_output_bytes | Maximum stdout or stderr bytes captured per evidence provider command | no | 20000 |
| evidence_provider_parallelism | Maximum evidence provider commands run concurrently. Set 1 to force serial execution when providers contend on shared files. Default 4. | no | 4 |
| evidence_blocker_enforcement | If true, force request_changes when any evidence provider reports blocker severity | no | false |
| evidence_enable_for_forks | If true, allow evidence providers to run on cross-repository pull requests | no | false |
| tool_mode | Optional tool harness mode: "off" (no evidence tools) or "native_loop". With native_loop the model uses its native tool-calling API — it holds the tool schemas and decides each next read-only call from the previous result, enabling multi-hop evidence chains. A model that never emits a tool call degrades to a corpus-only review (the verdict is still produced). Loop turns stream by default (controlled by ai_stream) so long turns don't time out behind a short-idle proxy; a stream that can't be reassembled is retried non-streamed for that turn. Budgets: tool_max_requests, tool_max_rounds, and tool_loop_wall_clock_sec. (The legacy plan_execute_once / plan_execute_loop planner modes were removed in 2.0; a stale value is treated as "off".) | no | off |
| tool_loop_wall_clock_sec | Wall-clock ceiling in seconds for the whole tool_mode=native_loop exchange (all model round-trips plus tool execution). Ignored for other modes. | no | 120 |
| tool_loop_summarize | When "true", tool_mode=native_loop folds the oldest tool results into a model-generated evidence digest once the conversation outgrows its context budget, instead of blunt-truncating them — preserving salient facts (versions, paths, URLs, findings) in fewer tokens at the cost of one extra model call per compaction. Off by default (truncation). Ignored for other modes. | no | false |
| tool_loop_summarize_max_tokens | Maximum completion tokens for each result-summarization call when tool_loop_summarize is enabled. Keep it small — the digest should be terse. | no | 512 |
| tool_evidence_memory | Carry the evidence a tool_mode=native_loop review gathers across incremental reviews of the same PR. The review stores a compact digest of what it read/fetched in its metadata marker; the next incremental review reuses it (re-verifying only what the delta touched) instead of re-gathering from scratch. On by default; set "false" to disable. No effect on full reviews or non-native modes. | no | true |
| tool_max_requests | Maximum number of tool requests the harness executes when tool_mode is enabled | no | 4 |
| tool_max_rounds | Round budget for tool_mode=native_loop, where a round is a single model turn: the loop allows up to twice this value (capped at 8) to leave room for one-call-per-turn chains and repair turns. Ignored when tool_mode=off. | no | 3 |
| tool_planning_timeout_sec | Timeout in seconds for the model planning call used by tool harness. Set generously for local models with slow prompt eval; native_loop streams turns by default (ai_stream) to avoid short-idle-proxy timeouts. | no | 60 |
| tool_planning_max_context_bytes | Maximum corpus bytes passed to the planning model | no | 50000 |
| tool_planning_max_tokens | Maximum completion tokens for tool harness planning model call | no | 400 |
| tool_max_response_bytes | Maximum bytes captured from each tool execution result | no | 12000 |
| tool_allowed_gh_api_repos | Comma-separated owner/repo list allowed for gh_api tool requests; use * to allow any repo still permitted by the path allowlist (empty means current repo only) | no | "" |
| tool_request_timeout_sec | Timeout in seconds for each tool request execution | no | 20 |
| search_url | Search-engine endpoint (e.g. a SearXNG instance's /search URL) that enables the read-only web_search tool in the native tool loop. When set, the model can search for a page (release notes, a support/compatibility matrix) and then web_fetch the best result — useful when it doesn't know the exact URL. Empty (default) leaves web_search un-advertised. The model supplies only the query; the host is fixed by this setting. Subject to the same fork gating as the rest of the tool harness. | no | "" |
| tool_max_search_results | Maximum results returned per web_search call | no | 5 |
| tool_failure_enforcement | If true, force request_changes when tool harness planning fails | no | false |
| tool_min_successful_requests | Minimum number of successful tool requests required when tool failure enforcement is enabled | no | 0 |
| tool_enable_for_forks | If true, allow the tool harness to run on cross-repository pull requests | no | false |
| tool_mcp_servers | Optional allowlist of read-only MCP servers for tool_mode=native_loop, as a newline/comma list of name=url (e.g. konflate=https://konflate.example/mcp). Their read-verb tools (list/get/read/…) are advertised as mcp__<name>__<tool> (double underscores); write-verb tools are refused. Empty = off (default). Fork-gated like the rest of the harness (tool_enable_for_forks). Only host-bearing http(s) URLs are accepted (HTTPS recommended); other schemes are dropped. | no | "" |
| tool_mcp_token | Optional bearer token sent to every configured MCP server (tool_mcp_servers) | no | "" |
| tool_mcp_name_prefixes | Comma-separated list of tool name prefixes to strip before the read-only verb check (e.g. toolhive workload prefixes from `prefixFormat: "{workload}_"`). Empty preserves the default-deny boundary. | no | "" |
| ai_request_timeout_sec | Timeout in seconds for the primary model API request (curl --max-time) | no | 300 |
| ai_connect_timeout_sec | Timeout in seconds for the primary model API connection (curl --connect-timeout) | no | 30 |
| ai_fallback_request_timeout_sec | Timeout in seconds for the fallback model API request (curl --max-time). Defaults to ai_request_timeout_sec when blank. | no | "" |
| ai_fallback_connect_timeout_sec | Timeout in seconds for the fallback model API connection (curl --connect-timeout). Defaults to ai_connect_timeout_sec when blank. | no | "" |
| platform | Target hosting platform for API capability gating and backend selection. 'auto' (default) detects from GITHUB_SERVER_URL and FORGEJO_API_URL: non-github.com hosts or FORGEJO_API_URL set resolves to 'forgejo'; otherwise 'github'. Set 'forgejo' or 'github' explicitly to override auto-detection. On Forgejo, features requiring GitHub GraphQL (thread resolution, review minimization) degrade gracefully with a log line; the REST backend handles core PR operations. Linked-source enrichment always targets github.com regardless of this setting. | no | auto |
| forgejo_api_url | Base URL for the Forgejo instance API backend (for example, https://forgejo.example.com). Optional on Forgejo Actions runners when GITHUB_SERVER_URL is set; set it when running from GitHub Actions or any runner that does not export the Forgejo server URL. | no | "" |
| forgejo_token | Optional Forgejo API token. Defaults to github_token when blank. Use this when the token used for GitHub-compatible operations is not also valid for the Forgejo REST API. | no | "" |
| skip_if_diff_unchanged | If true, skip the LLM review when the effective PR diff matches the last managed review comment fingerprint | no | true |
| force_review | If true, bypass the diff-unchanged guard and run a full PR review, even when the fingerprint matches the last managed review. Set automatically when the rereview_label is added; callers can also pass it from a workflow_dispatch or repository_dispatch. Default false. | no | false |
| rereview_label | Label that, when added to a PR, forces a fresh review even if nothing changed — the easy re-review trigger (only users with write/triage can label, so it is self-authorizing). On a `labeled` event the action reviews iff the added label matches this, then removes the label so re-adding re-triggers; any other label add is ignored. To enable, add `labeled` to the workflow's pull_request types. Default "ai-review". | no | ai-review |
| comment_marker | HTML marker for the managed PR comment | no | <!-- ai-pr-reviewer --> |
| ci_status_check | If true, wait for all CI checks to reach a terminal state before starting the AI review, then fold the per-check outcomes into the review corpus as evidence (so the model cites real test/lint results instead of "not verifiable"). Polls the Checks API for the PR head SHA. Default false — immediate review (original behavior). | no | false |
| ci_timeout_sec | Maximum seconds to wait for CI checks to complete when ci_status_check=true. Default 300. | no | 300 |
| ci_interval_sec | Seconds between CI status polls when ci_status_check=true. Default 15. | no | 15 |
| ci_skip_on_timeout | If true, proceed with review after timeout instead of failing. If false, abort the action on timeout. Default true. | no | true |
| review_scope | Controls whether the action reviews the full PR or only changes since the last managed review. auto performs a full review first, then incremental reviews on later PR synchronize events when safe. Accepted values: auto, full, incremental. | no | auto |
Outputs
| name | description |
|---|---|
| verdict | AI verdict, approve or request_changes |
| verdict_source | Where the final verdict came from ('model' or 'findings' per verdict_policy, or 'carry_forward' when a carried-forward blocker survived an incremental review) |
| required_checks | Required-check validation status ('complete', 'incomplete', or 'none' when validation did not run) |
| review_route | Model route used for this review ('legacy', 'primary', 'smart', or 'escalated') |
| escalation_reason | Comma-separated escalation trigger names when review_route is 'escalated' (empty otherwise) |
| findings | Normalized structured findings as a JSON array (empty array when the model produced none) |
| review_markdown | Human-readable markdown review body |
| analysis_engine | Model and endpoint that produced the final result |
| should_review | Whether the action determined a new LLM review is needed |
| skip_reason | Reason the LLM review was skipped |
| diff_fingerprint | Stable fingerprint of the current pull request patch |
| ci_status_skipped | Whether CI status check was skipped (true) or completed (false) |
| ci_status_final | Final CI state (success/failure) when ci_status_check completed |
| effective_review_scope | Effective review scope used (full or incremental) |
| previous_head_sha | Previous head SHA when effective scope is incremental |
| baseline_clean | Whether the full-review baseline was clean (for verdict safety) |
| cache_hit_ratio | Prompt-cache hit ratio for this review (0.0-1.0, from the tool harness in native_loop mode; empty when unavailable) |