Triggers
Triggers are the rules that decide when Mate spawns an agent job. Each trigger names one event type and one agent. Every trigger whose predicates match a given event fires — see How many jobs does one event create? below for the full model, including the one case where two matches collapse into a single job.
Overview
Section titled “Overview”triggers: - on: <event-type> # required agent: <agent-name> # required deny: [<authority>, ...] # optional, subtract from agent's effective permissions if: { ... } # optional, additional AND-combined conditions when: { ... } # optional, secondary filter (see Accepted but not yet enforced) # event-specific fields (see each event below)Both the tenant config and .mate.yml may define triggers. When a repository has a .mate.yml, its triggers are prepended to the tenant list — repo triggers are always evaluated first.
The six event types
Section titled “The six event types”issue_assigned
Section titled “issue_assigned”Fires when a registered Mate bot is newly added as an assignee on an issue.
- on: issue_assigned agent: my-agentThe acting bot is the one that was just assigned. If the bot was already an assignee and the issue is updated for another reason, this event does not fire.
mr_assigned
Section titled “mr_assigned”Fires when a registered Mate bot is newly added as an assignee on a merge request.
- on: mr_assigned agent: my-agentSame semantics as issue_assigned: fires only on the transition from not-assigned to assigned.
comment_mention
Section titled “comment_mention”Fires when a comment is posted containing @<bot-username> at a word boundary. The match is case-sensitive and must be an exact username match.
- on: comment_mention agent: my-agentThis event fires for comments on both issues and merge requests. The acting bot is the one whose username was mentioned.
Optional field: mention
Restrict the trigger to a specific bot username. Useful when multiple bots are registered and you want different triggers for each.
- on: comment_mention mention: mate-reviewer agent: reviewerlabel_applied
Section titled “label_applied”Fires when a label is newly applied to an issue or MR whose assignees include a registered Mate bot.
- on: label_applied label: "agent/review" # required glob pattern agent: my-agentThe label: field is required for this event. Its value is a shell-glob pattern matched against the label name. If the issue or MR has no Mate bot in its assignees, no trigger runs — a label alone is not enough.
mr_opened
Section titled “mr_opened”Fires when a merge request is opened, reopened, or transitions from draft to ready. The acting bot must be in the MR’s assignees.
- on: mr_opened agent: my-agentOptional fields:
| Field | Type | Description |
|---|---|---|
target_branch | glob | Fire only when the MR targets this branch pattern. |
draft | bool | When true, fire only for draft MRs. When false, fire only for non-draft (ready) MRs. When absent, fire for both. |
- on: mr_opened target_branch: main draft: false agent: my-agentpipeline_failed
Section titled “pipeline_failed”Fires when a pipeline finishes with a failed status on a branch that has an open MR. Mate resolves the open MR by source branch; no bot-assignee check is performed.
- on: pipeline_failed agent: my-agentTo fire only for pipelines on branches matching a glob, use the if: branch_pattern condition:
- on: pipeline_failed agent: ci-assistant if: branch_pattern: "feat/*"Evaluation order
Section titled “Evaluation order”When a webhook arrives, Mate evaluates triggers in this fixed order across event kinds:
mr_openedmr_assignedissue_assignedlabel_appliedcomment_mentionpipeline_failed
Within each event kind, triggers are evaluated in YAML order (repo triggers before tenant triggers).
This order only determines the sequence triggers are checked in — it does not determine how many of them fire. See the next section. If no trigger matches at all, no job is spawned.
How many jobs does one event create?
Section titled “How many jobs does one event create?”All matching triggers fire. Mate does not stop at the first match. Every trigger — repo and tenant, across every event kind present in the webhook — whose on:, if:, and other predicates all pass gets evaluated, and each match enqueues a job. There is no “one job per event” rule and no implicit first-match-and-stop.
Same-agent collapse is the one exception. Two matching triggers that name the same agent for the same event and context collapse into a single job. Mate’s dedup identity for this purpose is (event kind, agent name, context); when two triggers resolve to the same identity, only the first one evaluated gets a job — the rest are silently deduped. Because repo triggers are always evaluated before tenant triggers (see Evaluation order above), the repo trigger’s job wins that identity slot whenever both target the same agent.
A matching trigger that names a different agent does not collapse with anything — it produces an additional job alongside any others. Two triggers matching the same event with different agent: values both fire: you get two jobs, not one, each with its own model, prompt, and permissions.
What actually bounds job count:
policies.concurrencyandpolicies.cooldowncap how many jobs run and how often — they don’t change how many triggers matched, only how many of the resulting jobs run concurrently or how soon a repeat can start.- Webhook transport retries don’t multiply jobs: each match is deduped by an idempotency key, so a redelivered webhook collapses back onto the jobs it already created rather than creating new ones.
if: conditions
Section titled “if: conditions”The if: block specifies additional conditions that must all be true for the trigger to match. All conditions in one if: block are AND-ed together. For OR semantics, write two separate trigger entries.
- on: mr_opened agent: reviewer if: target_branch: main mr_draft: falseIdentity matchers
Section titled “Identity matchers”These perform exact string comparisons.
| Key | Description |
|---|---|
assignee | The GitLab username of the bot currently assigned to the issue or MR. |
mentioned_user | The GitLab username that was mentioned (for comment_mention events). |
author | The GitLab username of the issue, MR, or comment author. |
Pattern matchers
Section titled “Pattern matchers”These use shell-style glob patterns (Go path.Match semantics: * matches any sequence of characters within a single path segment and does not cross /; ** is not supported and behaves like *, not as a recursive glob).
| Key | Type | Description |
|---|---|---|
branch_pattern | glob | Source branch name of the MR or pipeline. |
target_branch | glob | Target branch name of the MR. |
label | glob | At least one label on the issue or MR matches this pattern. |
labels | list of globs | At least one label matches any pattern in the list. |
State matchers
Section titled “State matchers”| Key | Type | Description |
|---|---|---|
mr_state | string | MR state: opened, merged, or closed. |
mr_draft | bool | true requires the MR to be a draft; false requires it to be ready. |
Combining conditions
Section titled “Combining conditions”All conditions in one if: block must be satisfied for the trigger to fire. To express OR, write multiple triggers:
# OR: fire for either of two target branches- on: mr_opened agent: reviewer if: target_branch: main
- on: mr_opened agent: reviewer if: target_branch: release/*when: filter
Section titled “when: filter”The when: block is accepted for schema compatibility but currently has no enforced keys. See Accepted but not yet enforced below.
Unknown keys inside when: are a validation error.
deny: on triggers
Section titled “deny: on triggers”The deny: field subtracts one or more authorities from the agent’s effective permission set for this specific trigger. It does not affect the agent when reached by other triggers.
- on: pipeline_failed agent: contributor deny: [push_branch, open_mr] # comment only for this triggerSee Permissions for the full resolution model.
Concurrency and cooldown
Section titled “Concurrency and cooldown”Two policies control how many jobs a trigger can cause:
policies.concurrency— maximum simultaneous jobs for the tenant. When the cap is reached, new matching events are queued.policies.cooldown— minimum time between a job reaching a terminal state and a new job being enqueued on the same repository. A trigger that would fire within this window is silently suppressed.
Both are set in the policies: block.
Accepted but not yet enforced
Section titled “Accepted but not yet enforced”The following fields are accepted by YAML validation but currently have no effect at match time. Do not rely on them to filter which triggers fire.
Complete example
Section titled “Complete example”triggers: # label-routed: different agents for review vs. implementation - on: label_applied label: "agent/review" agent: reviewer
- on: label_applied label: "agent/fix" agent: fixer
# route by which bot was assigned (if: assignee is enforced) - on: issue_assigned agent: junior if: assignee: mate-junior
- on: issue_assigned agent: senior if: assignee: mate-senior
# review only non-draft MRs targeting main - on: mr_opened agent: security-reviewer if: target_branch: main mr_draft: false
# pipeline failures: comment only, no code push - on: pipeline_failed agent: ci-assistant deny: [push_branch, open_mr]
# mention fallback: catch-all for any bot mention - on: comment_mention agent: reviewer