Skip to content

Output Channels and Routing

After a review finishes, AICodeReviewer dispatches the result to one or more output channels — PR line comments, IM bots, managed issues — based on routing rules. The outputs namespace defines the channels, the routes, the template engine, and the zero-problem policy that decides whether a clean review should notify anyone.

outputs:
template_engine: handlebars
no_problems: { action: suppress }
channels:
- name: gitea-pr-review
kind: gitea_pr_review
trigger: gitea
routes:
default:
line_comments: [gitea-pr-review]
summary: [gitea-pr-review]
Value Description
handlebars (default) Handlebars templates (*.hbs). Built-ins live in templates/builtin/*.hbs.
eta Reserved — accepted by the schema, but only Handlebars is implemented; setting it has no effect.

Override templates per workspace by placing files under workspaces/<workspace_id>/templates/. Candidate file names are checked in order: <channel_name>.<kind>.md.hbs → <channel_name>.<kind>.hbs → <channel_kind>.<kind>.md.hbs → <channel_kind>.<kind>.hbs → <kind>.md.hbs → <kind>.hbs.

outputs.no_problems — zero-problem policy

Section titled “outputs.no_problems — zero-problem policy”

Decides whether a successful review with no actionable problems should notify each channel.

action Behavior
suppress Do not notify when there are no problems.
publish Always notify, even with zero problems.
publish_if_summary Notify only if a non-empty summary was produced.

When nothing is configured, the default depends on the channel kind: managed problem-issue channels (*_problem_issue) default to publish — publishing is what drives stale issues to close; IM bots default to publish_if_summary; everything else defaults to suppress.

The policy is set at three levels, each more specific:

  1. outputs.no_problems (global default for all channels)
  2. per-channel no_problems inside outputs.channels[]
  3. per-workspace + per-channel via workspaces.instances.<id>.outputs.channel_overrides.<channel>.no_problems
outputs:
no_problems: { action: suppress }
channels:
- name: feishu-code-review
kind: feishu_bot
no_problems: { action: suppress }
workspaces:
instances:
critical-service:
outputs:
channel_overrides:
feishu-code-review:
no_problems: { action: publish } # this repo wants an audit trail

If all selected summary channels suppress a zero-problem result, the run is recorded as skipped with skipReason="no_problems_suppressed". The policy only gates visible summaries: managed problem-issue channels still reconcile stored findings on every genuine zero-problem review so confirmed fixes can close (resolved_action: none opts out).

Every channel has a name (referenced by routes and workspace output lists) and a kind. The common fields below apply to most kinds; kind-specific fields are listed under each kind.

Field Type Description
name string Unique channel id.
kind string Channel kind (see list below). gitea_finding_issue is removed — use gitea_problem_issue.
trigger string Trigger name this channel binds to (for VCS-backed kinds).
mention_author bool @-mention the commit author in the message. Defaults to true for VCS PR/issue kinds and false for IM bots.
mention_fallback enum all (mention everyone) or skip (no mention if author not found).
no_problems object Per-channel zero-problem policy (see above).
commit_url_template string Override commit link for push/commit targets.
revision_url_template string Override revision link (P4/SVN).
change_url_template string Override change link.
marker_prefix string Title prefix for managed issues (e.g. [AICR]).
marker_label string Hidden label identifying managed issues (e.g. aicr-managed).
labels string[] Labels to attach.
label_ids int[] Numeric label ids (some VCS APIs).
issue_mode enum per_problem, consolidated (default), or per_commit.
resolved_action enum none, close, mark_resolved, or delete. Action when a problem is fixed.
assign_committer bool Add the resolved review author to newly created managed issues (default true); see assignment rules below.
owners_file string Path to OWNERS file (default OWNERS).
add_owners_as_assignees bool Add matched OWNERS as assignees.
severity_label_prefix string Auto-created label prefix (e.g. aicr:problem:).
severity_label_colors map Custom label colors (hex without #).
review_mode enum auto (default), review, or comment.
review_event enum COMMENT (default) or REQUEST_CHANGES.
review_update_strategy enum always_new or update_existing (default).
notify_feishu object Optional Feishu notify-on-issue-creation (webhook_url_env, secret_env).

GitHub/Gitea managed issues resolve the event login, then outputs.author_resolution.email_mappings, then the linked head-commit author, and finally the retained push pusher. Pushes with head-commit metadata use that author’s identity; PR events prefer the PR author over the delivery sender. Git display names are not platform logins. GitHub queries /repos/{owner}/{repo}/commits/{sha}; Gitea/Forgejo queries /repos/{owner}/{repo}/git/commits/{sha}. Queries use the output repository and credentials and are cached per review.

email_blacklist and assign_committer: false block author lookup and fallback. OWNERS assignments remain independent. Missing identities or failed lookups leave the author unassigned. Only explicit HTTP 422 assignee validation errors trigger one creation retry without assignees; other failures propagate. Existing issue assignees are retained.

The publishing account needs assignment permission, and the target user must be eligible. GitHub/Gitea can silently ignore assignment when the publisher lacks the required repository access; check the created issue’s assignees. Private GitHub commit lookup needs Contents read permission. GitLab currently supports MR discussions/notes only; issue creation and assignment are unimplemented.

Kind Description
gitea_pr_review Inline line comments on Gitea/Forgejo pull requests.
github_pr_review Inline line comments on GitHub pull requests.
gitlab_mr_review Inline line comments on GitLab merge requests.
gitea_problem_issue Managed Gitea issues created/closed per problem fingerprint.
github_problem_issue Managed GitHub issues per problem fingerprint (no delete — GitHub does not support it).
gitlab_problem_issue Managed GitLab issues per problem fingerprint (assignees must be project members; CE effectively supports one assignee; delete requires owner/admin).
gitea_issue Post the aggregated review as a comment on an existing Gitea issue.
github_issue Post the aggregated review as a comment on an existing GitHub issue.
feishu_bot Push aggregated problems to a Feishu (飞书) group via custom bot.
feishu_app Send the shared Feishu report card through a custom application’s bot; see setup and member matching.
wecom_bot Push aggregated problems to a WeCom (企业微信) group via webhook.
wecom_app Send the aggregated report through a WeCom self-built application to explicit members or one appchat group; see IM bots.

For *_pr_review / *_mr_review kinds:

Value Behavior
auto (default) Try the PR review API first; fall back to issue comment on 403/422.
review Always use the PR review API, no fallback.
comment Always post a plain issue comment, never the review API.

The companion review_event field controls the event type used with the review API: COMMENT (default) or REQUEST_CHANGES.

review_update_strategy controls how the PR summary behaves across pushes:

Value Behavior
always_new Create a new review/comment on every push (original behavior).
update_existing (default) Find and update the previous AICR summary comment on the PR. Open issues are kept; resolved issues are marked with ✅; new issues are tagged with the introducing commit.

AICR identifies its own managed comments via stable managed comment markers derived from marker_prefix/marker_label, so only AICR-owned summary comments are updated and other comments are left untouched.

outputs.routes — send results to the right channels

Section titled “outputs.routes — send results to the right channels”

Routes map review outputs (line_comments and summary) to channel lists. A default route applies to every event; rules[] override for specific triggers or target kinds.

outputs:
routes:
default:
line_comments: [gitea-pr-review]
summary: [gitea-pr-review]
rules:
- match:
trigger: p4-main
target_kind: commit
summary: [feishu-code-review]
- match:
trigger: github
target_kind: push
summary: [feishu-code-review, github-problem-issues]
Field Type Description
default.line_comments string[] Channels for inline line comments.
default.summary string[] Channels for the aggregated summary.
rules[].match.trigger string Match events from this trigger name.
rules[].match.target_kind string Match a target kind (e.g. commit, push, pull_request). pr is normalized to pull_request.
rules[].line_comments string[] Override line-comment channels for matched events.
rules[].summary string[] Override summary channels for matched events.

Per-workspace output lists (workspaces.instances.<id>.outputs.line_comments and .summary) take precedence over the global routes for that workspace.

AICodeReviewer can skip reviews based on labels and auto-tag PRs/MRs/issues. This lives under review (not outputs) but is closely related to output dispatch.

review:
labels:
ignore: ["aicr:ignore", "aicr-ignore"] # skip review if any label matches
auto_tag: "aicr" # tag added when AICR starts
reviewed_tag: "aicr:reviewed" # tag added when review completes
Field Behavior
ignore Checked at the webhook layer. If a PR/MR/issue carries any listed label, AICR returns immediately without scheduling a review.
auto_tag Fixed tag applied by output dispatchers (gitea_pr_review, github_pr_review, gitlab_mr_review, gitea_issue, gitea_problem_issue, github_problem_issue, gitlab_problem_issue) when publishing. Created automatically if missing.
reviewed_tag Tag applied when a review completes.

All fields support the global → workspace-level override layering.

gitea_problem_issue, github_problem_issue, and gitlab_problem_issue reconcile stale managed issues by listing only the most recent open issues. The cap lives under review.problem_issue and can be tightened per workspace.

review:
problem_issue:
max_recent_issues: 30 # default; valid range is 1..200
workspaces:
instances:
latency-sensitive-service:
review:
problem_issue:
max_recent_issues: 10

If a repository has more open managed issues than the limit, fingerprints outside the recent window are not deduplicated or closed in that run. Later runs — or a temporarily raised cap — handle large cleanup runs.

If one configured output channel cannot publish, AICR logs the channel failure and continues trying the remaining routed channels. A run where every dispatch attempt fails is reported as skipped with skipReason: output_dispatch_failed (instead of review_orchestration_failed), so the review result and failure cause stay visible without poisoning the trigger queue.

Built-in templates render target.markdownLink / target.displayText instead of assuming every review is a PR. Gitea, Forgejo, GitHub, and GitLab commit links are derived from trigger base_url, repo, and revision. P4/SVN/internal systems provide explicit URL templates via the trigger’s change_url_template or revision_url_template (variables are URL-encoded before substitution):

triggers:
- name: p4-main
kind: p4
change_url_template: "https://swarm.example.com/changes/{{revision}}"
- name: svn-main
kind: svn
revision_url_template: "https://svn.example.com/viewvc/project?view=revision&revision={{revision}}"
  • The full per-channel field contract, including the MCP tool contract that agents use to fetch more context, is in Output channels.
  • For trigger-side URL templates and file filters, see VCS providers.