config/routes.yaml
Rama main · réplica de lectura del repositorio original.
# Robot Dev Team Project
# File: config/routes.yaml
# Description: Routing configuration for GitLab webhook events.
# License: MIT
# SPDX-License-Identifier: MIT
# Copyright (c) 2025 MCKNLY LLC
# Sample routing configuration for webhook event handling.
# See docs/ROUTES.md for detailed schema and additional examples.
#
# IMPORTANT: Replace "your-username" with your GitLab username in each route's
# author field. The author field accepts either a single string or a list of
# usernames if you want one route to be triggerable by multiple operators,
# e.g. author: ["alice", "bob"]. Matching is case-insensitive in both forms.
# For persistent local overrides, copy this file to config/routes.local.yaml,
# customise it, and set ROUTE_CONFIG_PATH in .env:
# ROUTE_CONFIG_PATH=config/routes.local.yaml
#
# Access modes:
# - readonly: Agent runs in read-only project mount (default). The agent
# receives filesystem errors if it attempts to write files.
# - readwrite: Agent runs in read-write project mount. Use for routes
# that need to modify code.
#
# Timeout overrides (optional per-route, falls back to global env vars):
# max_wall_clock_seconds: Hard upper-bound run duration (default: 7200)
# max_inactivity_seconds: Watchdog resets on stdout output only (default: 900).
# Stderr is tracked for diagnostics but deliberately
# does not stay the timeout, so a retry loop (which
# produces only stderr) cannot hold the queue open.
# Raise this for a harness that goes quiet for long
# stretches, e.g. a local model during a long prefill.
#
# Agent dispatch order (optional per-route):
# randomize: true -> shuffle the agents list per matched event so the same
# agent does not always run first. Only meaningful on
# multi-agent routes (e.g. issue-triage). Defaults to
# false. See docs/ROUTES.md for details.
routes:
# Issue-assignment routes - triggered when an agent is assigned to an issue.
# GitLab's /assign quick action on an existing issue sends an Issue Hook with
# action=update; populating the assignee at issue-creation time sends an Issue
# Hook with action=open. Matching both (action: ["open", "update"]) means an
# issue created with an agent already assigned dispatches that agent's
# read-write assign_work route immediately, instead of first going through
# readonly triage/review. These routes detect agent usernames in the assignees
# list and grant read-write access for the agent to perform work.
#
# Placement matters: resolve_match returns the FIRST matching route, so these
# must sit ABOVE issue-triage (and any issue-update fallback). Otherwise a
# create-with-assignee event would fall through to the readonly issue-triage
# review. This is deliberately either/or -- an issue created with an agent
# assigned skips triage and goes straight to work.
#
# Assign-on-creation can be disabled with ENABLE_ASSIGN_ON_ISSUE_CREATION=false
# (default true), which reverts creation events to triage. The /assign-on-an-
# existing-issue path (action=update) is unaffected by that toggle.
- name: assign-issue-claude
access: readwrite
match:
event: "Issue Hook"
action: ["open", "update"]
author: "your-username"
assignees: ["claude"]
agents:
- agent: "claude"
task: "assign_work"
prompt: "assign_work.txt"
options:
command: "claude"
args: ["--model", "${CLAUDE_MODEL}", "--dangerously-skip-permissions", "-p"]
- name: assign-issue-gemini
access: readwrite
match:
event: "Issue Hook"
action: ["open", "update"]
author: "your-username"
assignees: ["gemini"]
agents:
- agent: "gemini"
task: "assign_work"
prompt: "assign_work.txt"
options:
command: "agy"
args: ["--model", "${GEMINI_MODEL}", "--dangerously-skip-permissions", "-p", "${PROMPT}"]
- name: assign-issue-codex
access: readwrite
match:
event: "Issue Hook"
action: ["open", "update"]
author: "your-username"
assignees: ["codex"]
agents:
- agent: "codex"
task: "assign_work"
prompt: "assign_work.txt"
options:
command: "codex"
args: ["--model", "${CODEX_MODEL}", "exec", "--yolo", "--skip-git-repo-check"]
# OpenCode issue-assignment route (optional, disabled by default). Read-write
# like the other assignment routes. Strip the leading `#` (column 0) to enable.
# - name: assign-issue-opencode-kimi
# access: readwrite
# match:
# event: "Issue Hook"
# action: ["open", "update"]
# author: "your-username"
# assignees: ["opencode-kimi"]
# agents:
# - agent: "opencode-kimi"
# task: "assign_work"
# prompt: "assign_work.txt"
# options:
# command: "opencode"
# args: ["run", "--model", "${OPENCODE_KIMI_MODEL}", "--format", "json", "--auto"]
# Goose issue-assignment route (optional, disabled by default). Read-write like
# the other assignment routes. Strip the leading `#` (column 0) to enable.
#
# Note the trigger and the agent are deliberately different strings: `assignees`
# matches the GitLab *username* from the webhook payload (`gemma`), while `agent`
# is the slug that resolves GOOSE_GEMMA_MODEL + GOOSE_GEMMA_AGENT_* (`goose-gemma`).
# Same split as the opencode-kimi / `kimi` pair -- the harness prefix stays out of
# the GitLab account name.
#
# A local model can go quiet for a long prefill, so the inactivity watchdog is
# raised above the 900s default here to keep a run from being killed mid-think.
# - name: assign-issue-goose-gemma
# access: readwrite
# max_inactivity_seconds: 1800
# match:
# event: "Issue Hook"
# action: ["open", "update"]
# author: "your-username"
# assignees: ["gemma"]
# agents:
# - agent: "goose-gemma"
# task: "assign_work"
# prompt: "assign_work.txt"
# options:
# command: "goose"
# args: ["run", "--no-session", "--model", "${GOOSE_GEMMA_MODEL}", "-i", "-"]
# Grok Build issue-assignment route (optional, disabled by default). Read-write
# like the other assignment routes. Strip the leading `#` (column 0) to enable.
#
# The inactivity watchdog is raised above the 900s default because Grok's plain
# output format prints the reply in one go at the end of the run: a long stretch
# of tool calls produces no stdout to reset the timer. Switch the route to
# `--output-format streaming-json` instead if you would rather have continuous
# token events (at the cost of JSON-shaped run-logs).
# - name: assign-issue-grok
# access: readwrite
# max_inactivity_seconds: 1800
# match:
# event: "Issue Hook"
# action: ["open", "update"]
# author: "your-username"
# assignees: ["grok"]
# agents:
# - agent: "grok"
# task: "assign_work"
# prompt: "assign_work.txt"
# options:
# command: "grok"
# args: ["--model", "${GROK_MODEL}", "--no-auto-update", "--always-approve", "-p", "${PROMPT}"]
- name: issue-triage
access: readonly
randomize: true
# Uncomment together with the goose or grok entries below -- both go quiet for
# long stretches (a local model during prefill; grok's `plain` format, which
# prints nothing until the run ends) and the watchdog only resets on stdout.
# Applies to every agent on this route, which is harmless: it only widens the
# silence they are allowed before being killed.
# max_inactivity_seconds: 1800
match:
event: "Issue Hook"
action: "open"
author: "your-username"
agents:
- agent: "claude"
task: "issue_review"
prompt: "issue_review.txt"
options:
command: "claude"
args: ["--model", "${CLAUDE_MODEL}", "--dangerously-skip-permissions", "-p"]
- agent: "gemini"
task: "issue_review"
prompt: "issue_review.txt"
options:
command: "agy"
args: ["--model", "${GEMINI_MODEL}", "--dangerously-skip-permissions", "-p", "${PROMPT}"]
- agent: "codex"
task: "issue_review"
prompt: "issue_review.txt"
options:
command: "codex"
args: ["--model", "${CODEX_MODEL}", "exec", "--yolo", "--skip-git-repo-check"]
# OpenCode issue-review entry (optional, disabled by default). The shared
# `opencode` binary backs each opencode-<model> agent. To enable, strip the
# leading `#` from the lines below (it sits at column 0 so removing it restores
# the correct YAML indentation). See docs/ROUTES.md.
# - agent: "opencode-kimi"
# task: "issue_review"
# prompt: "issue_review.txt"
# options:
# command: "opencode"
# args: ["run", "--model", "${OPENCODE_KIMI_MODEL}", "--format", "json", "--auto"]
# Goose issue-review entry (optional, disabled by default). Strip the leading
# `#` (column 0) from the lines below to enable. Like OpenCode, the single
# `goose` binary backs many logical agents, so each is named after its model
# (`goose-gemma` here) and resolves its own GOOSE_GEMMA_* env vars. Add another
# by cloning these blocks with a new suffix, e.g. `goose-qwen`.
#
# Goose takes the prompt on stdin (`-i -`) and `--no-session` keeps webhook runs
# from accumulating session state. Provider and extensions come from the host
# config dir mounted in docker-compose.yml -- do NOT add `--provider` here:
# routes only substitute ${VAR} in the argument right after `--model`, so any
# other placeholder would reach the CLI as a literal string.
# See docs/ADDING_AN_AGENT.md.
# - agent: "goose-gemma"
# task: "issue_review"
# prompt: "issue_review.txt"
# options:
# command: "goose"
# args: ["run", "--no-session", "--model", "${GOOSE_GEMMA_MODEL}", "-i", "-"]
# Grok Build issue-review entry (optional, disabled by default). Strip the
# leading `#` (column 0) from the lines below to enable. See docs/ROUTES.md.
#
# Grok takes the prompt as an argv value via the ${PROMPT} placeholder, the same
# way `agy` does -- it does NOT read stdin. Its `--prompt-file` flag accepts
# /dev/stdin and looks like the stdin answer (it even works under a shell
# redirect), but the dispatcher hands the child a pipe and closes the write end
# once the prompt is written; grok then re-opens fd 0 *by path*, and reopening a
# pipe with no writers left fails with ENXIO. Do not "fix" this back to
# --prompt-file. Auth comes from the host config dir mounted in
# docker-compose.yml (~/.grok/auth.json, written by `grok login`).
#
# `--no-auto-update` is not about pinning a version -- scripts/install-grok.sh
# still fetches latest at every container start. It stops the *running agent* from
# updating itself: grok's updater stages into ~/.grok/downloads and repoints
# ~/.grok/bin/{grok,agent}, and ~/.grok is bind-mounted from the host, so a
# container-side update would drop a ~150 MB binary in the operator's home and
# flip the symlink their host grok resolves through.
#
# Uncomment `max_inactivity_seconds` on the route above together with this entry:
# in the default `plain` format grok emits no stdout until the run ends, and the
# watchdog only resets on stdout. The route-level value applies to every agent on
# the route, which is harmless -- it only widens the silence they are allowed.
# - agent: "grok"
# task: "issue_review"
# prompt: "issue_review.txt"
# options:
# command: "grok"
# args: ["--model", "${GROK_MODEL}", "--no-auto-update", "--always-approve", "-p", "${PROMPT}"]
- name: default-merge-request
access: readonly
randomize: true
# Uncomment together with the goose or grok entries below; see the note on
# issue-triage above.
# max_inactivity_seconds: 1800
match:
event: "Merge Request Hook"
action: "open"
agents:
- agent: "claude"
task: "merge_request_review"
prompt: "merge_request_review.txt"
options:
command: "claude"
args: ["--model", "${CLAUDE_MODEL}", "--dangerously-skip-permissions", "-p"]
- agent: "gemini"
task: "merge_request_review"
prompt: "merge_request_review.txt"
options:
command: "agy"
args: ["--model", "${GEMINI_MODEL}", "--dangerously-skip-permissions", "-p", "${PROMPT}"]
- agent: "codex"
task: "merge_request_review"
prompt: "merge_request_review.txt"
options:
command: "codex"
args: ["--model", "${CODEX_MODEL}", "exec", "--yolo", "--skip-git-repo-check"]
# OpenCode MR-review entry (optional, disabled by default). Strip the leading
# `#` (column 0) from the lines below to enable.
# - agent: "opencode-kimi"
# task: "merge_request_review"
# prompt: "merge_request_review.txt"
# options:
# command: "opencode"
# args: ["run", "--model", "${OPENCODE_KIMI_MODEL}", "--format", "json", "--auto"]
# Goose MR-review entry (optional, disabled by default). Strip the leading `#`
# (column 0) from the lines below to enable.
# - agent: "goose-gemma"
# task: "merge_request_review"
# prompt: "merge_request_review.txt"
# options:
# command: "goose"
# args: ["run", "--no-session", "--model", "${GOOSE_GEMMA_MODEL}", "-i", "-"]
# Grok Build MR-review entry (optional, disabled by default). Strip the leading
# `#` (column 0) from the lines below to enable.
# - agent: "grok"
# task: "merge_request_review"
# prompt: "merge_request_review.txt"
# options:
# command: "grok"
# args: ["--model", "${GROK_MODEL}", "--no-auto-update", "--always-approve", "-p", "${PROMPT}"]
# MR assignment routes - same as issue assignments but for merge requests.
- name: assign-mr-claude
access: readwrite
match:
event: "Merge Request Hook"
action: "update"
author: "your-username"
assignees: ["claude"]
agents:
- agent: "claude"
task: "assign_work"
prompt: "assign_work.txt"
options:
command: "claude"
args: ["--model", "${CLAUDE_MODEL}", "--dangerously-skip-permissions", "-p"]
- name: assign-mr-gemini
access: readwrite
match:
event: "Merge Request Hook"
action: "update"
author: "your-username"
assignees: ["gemini"]
agents:
- agent: "gemini"
task: "assign_work"
prompt: "assign_work.txt"
options:
command: "agy"
args: ["--model", "${GEMINI_MODEL}", "--dangerously-skip-permissions", "-p", "${PROMPT}"]
- name: assign-mr-codex
access: readwrite
match:
event: "Merge Request Hook"
action: "update"
author: "your-username"
assignees: ["codex"]
agents:
- agent: "codex"
task: "assign_work"
prompt: "assign_work.txt"
options:
command: "codex"
args: ["--model", "${CODEX_MODEL}", "exec", "--yolo", "--skip-git-repo-check"]
# OpenCode MR-assignment route (optional, disabled by default). Strip the
# leading `#` (column 0) to enable.
# - name: assign-mr-opencode-kimi
# access: readwrite
# match:
# event: "Merge Request Hook"
# action: "update"
# author: "your-username"
# assignees: ["opencode-kimi"]
# agents:
# - agent: "opencode-kimi"
# task: "assign_work"
# prompt: "assign_work.txt"
# options:
# command: "opencode"
# args: ["run", "--model", "${OPENCODE_KIMI_MODEL}", "--format", "json", "--auto"]
# Goose MR-assignment route (optional, disabled by default). Strip the leading
# `#` (column 0) to enable.
# - name: assign-mr-goose-gemma
# access: readwrite
# max_inactivity_seconds: 1800
# match:
# event: "Merge Request Hook"
# action: "update"
# author: "your-username"
# assignees: ["gemma"]
# agents:
# - agent: "goose-gemma"
# task: "assign_work"
# prompt: "assign_work.txt"
# options:
# command: "goose"
# args: ["run", "--no-session", "--model", "${GOOSE_GEMMA_MODEL}", "-i", "-"]
# Grok Build MR-assignment route (optional, disabled by default). Strip the
# leading `#` (column 0) to enable.
# - name: assign-mr-grok
# access: readwrite
# max_inactivity_seconds: 1800
# match:
# event: "Merge Request Hook"
# action: "update"
# author: "your-username"
# assignees: ["grok"]
# agents:
# - agent: "grok"
# task: "assign_work"
# prompt: "assign_work.txt"
# options:
# command: "grok"
# args: ["--model", "${GROK_MODEL}", "--no-auto-update", "--always-approve", "-p", "${PROMPT}"]
# Regular mention routes - triggered by @agent mentions without /assign.
- name: mention-claude
access: readonly
match:
event: "Note Hook"
action: "create"
author: "your-username"
mentions: ["claude"]
agents:
- agent: "claude"
task: "note_followup"
prompt: "note_followup.txt"
options:
command: "claude"
args: ["--model", "${CLAUDE_MODEL}", "--dangerously-skip-permissions", "-p"]
- name: mention-gemini
access: readonly
match:
event: "Note Hook"
action: "create"
author: "your-username"
mentions: ["gemini"]
agents:
- agent: "gemini"
task: "note_followup"
prompt: "note_followup.txt"
options:
command: "agy"
args: ["--model", "${GEMINI_MODEL}", "--dangerously-skip-permissions", "-p", "${PROMPT}"]
- name: mention-codex
access: readonly
match:
event: "Note Hook"
action: "create"
author: "your-username"
mentions: ["codex"]
agents:
- agent: "codex"
task: "note_followup"
prompt: "note_followup.txt"
options:
command: "codex"
args: ["--model", "${CODEX_MODEL}", "exec", "--yolo", "--skip-git-repo-check"]
# OpenCode mention route (optional, disabled by default). Read-only like the
# other mention routes. Strip the leading `#` (column 0) to enable.
# - name: mention-opencode-kimi
# access: readonly
# match:
# event: "Note Hook"
# action: "create"
# author: "your-username"
# mentions: ["opencode-kimi"]
# agents:
# - agent: "opencode-kimi"
# task: "note_followup"
# prompt: "note_followup.txt"
# options:
# command: "opencode"
# args: ["run", "--model", "${OPENCODE_KIMI_MODEL}", "--format", "json", "--auto"]
# Goose mention route (optional, disabled by default). Read-only like the other
# mention routes. Strip the leading `#` (column 0) to enable.
# - name: mention-goose-gemma
# access: readonly
# max_inactivity_seconds: 1800
# match:
# event: "Note Hook"
# action: "create"
# author: "your-username"
# mentions: ["gemma"]
# agents:
# - agent: "goose-gemma"
# task: "note_followup"
# prompt: "note_followup.txt"
# options:
# command: "goose"
# args: ["run", "--no-session", "--model", "${GOOSE_GEMMA_MODEL}", "-i", "-"]
# Grok Build mention route (optional, disabled by default). Read-only like the
# other mention routes. Strip the leading `#` (column 0) to enable.
#
# Unlike opencode-* and goose-*, one `grok` binary backs exactly one logical
# agent, so the GitLab username and the agent slug are the same string (`grok`)
# and the env vars are the plain GROK_AGENT_* / GROK_MODEL forms.
# - name: mention-grok
# access: readonly
# max_inactivity_seconds: 1800
# match:
# event: "Note Hook"
# action: "create"
# author: "your-username"
# mentions: ["grok"]
# agents:
# - agent: "grok"
# task: "note_followup"
# prompt: "note_followup.txt"
# options:
# command: "grok"
# args: ["--model", "${GROK_MODEL}", "--no-auto-update", "--always-approve", "-p", "${PROMPT}"]
# Pi mention route (optional, disabled by default). Read-only like the other
# mention routes. Strip the leading `#` (column 0) to enable.
#
# Like goose-*, the GitLab username and the agent slug are deliberately different:
# `mentions` matches the GitLab *username* from the webhook payload (`nemotron`),
# while `agent` is the slug that resolves PI_NEMOTRON_MODEL + PI_NEMOTRON_AGENT_*
# (`pi-nemotron`). The harness prefix stays out of the GitLab account name.
#
# Pi takes the prompt on stdin: there is no ${PROMPT} token in args, so the
# dispatcher pipes the rendered prompt to the child (print mode `-p` merges piped
# stdin into the initial prompt). `--no-session` keeps webhook runs from writing
# session state into the bind-mounted ~/.pi/agent, and `--no-approve` stops an
# untrusted repo/branch from opting itself into executable Pi extensions. Provider
# auth (the OpenRouter key) comes from the host config dir mounted in
# docker-compose.yml (~/.pi/agent/auth.json), not from an env key. Only the arg
# right after `--model` is substituted, so keep ${PI_NEMOTRON_MODEL} in that slot.
# A 550B model can prefill silently, so the inactivity watchdog is raised above the
# 900s default (the watchdog resets on stdout only).
# - name: mention-pi-nemotron
# access: readonly
# max_inactivity_seconds: 1800
# match:
# event: "Note Hook"
# action: "create"
# author: "your-username"
# mentions: ["nemotron"]
# agents:
# - agent: "pi-nemotron"
# task: "note_followup"
# prompt: "note_followup.txt"
# options:
# command: "pi"
# args: ["-p", "--no-session", "--no-approve", "--model", "${PI_NEMOTRON_MODEL}"]