Skip to content

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.

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.

Fires when a registered Mate bot is newly added as an assignee on an issue.

- on: issue_assigned
agent: my-agent

The 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.

Fires when a registered Mate bot is newly added as an assignee on a merge request.

- on: mr_assigned
agent: my-agent

Same semantics as issue_assigned: fires only on the transition from not-assigned to assigned.

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-agent

This 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: reviewer

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-agent

The 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.

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-agent

Optional fields:

FieldTypeDescription
target_branchglobFire only when the MR targets this branch pattern.
draftboolWhen 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-agent

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-agent

To 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/*"

When a webhook arrives, Mate evaluates triggers in this fixed order across event kinds:

  1. mr_opened
  2. mr_assigned
  3. issue_assigned
  4. label_applied
  5. comment_mention
  6. pipeline_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.

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.concurrency and policies.cooldown cap 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.

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: false

These perform exact string comparisons.

KeyDescription
assigneeThe GitLab username of the bot currently assigned to the issue or MR.
mentioned_userThe GitLab username that was mentioned (for comment_mention events).
authorThe GitLab username of the issue, MR, or comment author.

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).

KeyTypeDescription
branch_patternglobSource branch name of the MR or pipeline.
target_branchglobTarget branch name of the MR.
labelglobAt least one label on the issue or MR matches this pattern.
labelslist of globsAt least one label matches any pattern in the list.
KeyTypeDescription
mr_statestringMR state: opened, merged, or closed.
mr_draftbooltrue requires the MR to be a draft; false requires it to be ready.

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/*

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.

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 trigger

See Permissions for the full resolution model.

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.

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.

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