Rules (kardbrd.yml)¶
Directly addressed comments use the separate optional comment_execution scope. Rule and schedule model fields do not set comment defaults.
The rule engine is the core of kardbrd-agent's automation. Define rules in kardbrd.yml to match WebSocket events and trigger AI agent sessions or built-in actions.
File format¶
board_id: 0gl5MlBZ # required — your board ID
agent: MyBot # required — agent name for @mentions
api_url: http://app.kardbrd.com # optional — API base URL
executor: goose # optional — "claude" (default), "goose", or "codex"
rules:
- name: Rule name # required
event: card_created # required — event type(s)
# ... conditions ...
model: sonnet # optional — model selection
action: /ke # required — what to do
Rules¶
Each rule has a name, one or more events, optional conditions, and an action.
Events¶
Events can be a single string or a YAML list:
Available events¶
| Category | Events |
|---|---|
| Card | card_created, card_moved, card_archived, card_unarchived, card_deleted |
| Comment | comment_created, comment_deleted |
| Reaction | reaction_added |
| Checklist | checklist_created, checklist_deleted |
| Todo item | todo_item_created, todo_item_completed, todo_item_reopened, todo_item_deleted, todo_item_assigned, todo_item_unassigned |
| Attachment | attachment_created, attachment_deleted |
| Link | card_link_created, card_link_deleted |
| Label | label_added, label_removed |
| List | list_created, list_deleted |
Conditions¶
All conditions use AND logic — every condition on a rule must match for the rule to fire.
| Condition | Type | Description |
|---|---|---|
list |
string | Card is in this list (case-insensitive) |
title |
string | Card title matches exactly (case-insensitive) |
label |
string | Card has this label (case-insensitive) |
emoji |
string | Reaction emoji matches (for reaction_added) |
require_label |
string | Card must have this label (triggers API enrichment) |
exclude_label |
string | Card must NOT have this label (triggers API enrichment) |
require_user |
string | Event must be from this user ID |
content_contains |
string | Comment or card content contains this text |
comment_author |
string | Comment must be by this user (supports __self__ for the bot) |
assignee |
list | Card must be assigned to one of these user IDs (supports __self__). Must be a YAML list |
Label enrichment
require_label and exclude_label trigger an API call to fetch the card's current labels. Other label conditions use data from the WebSocket event.
Actions¶
Actions define what happens when a rule matches. Three types:
Skill commands — invoke a predefined workflow:
action: /ke # explore codebase
action: /kp # create implementation plan
action: /ki # execute implementation plan
action: /kr # code review
Inline prompts — send a custom prompt to the executor:
action: |
Review this PR and check for security vulnerabilities.
Focus on SQL injection and XSS risks.
Built-in actions — special system actions:
Direct Done cleanup commands¶
cleanup_command is an opt-in maintenance rule for retiring resources that
belong to a card after it reaches Done. Unlike action, it runs a configured
command directly: it does not create, initialize, or remove a worktree, run a
worktree setup hook, fetch card markdown, or start an executor session.
The command must be a non-empty YAML argv list. It is intentionally restricted
to one card_moved event and list: Done, and cannot be combined with
action. The first argv value cannot be a privilege (sudo, doas, su, or
pkexec), environment, or shell wrapper; invoke a dedicated script directly.
rules:
- name: Retire preview when Done
event: card_moved
list: Done
cleanup_command:
- /srv/cba/bin/retire-preview
- --quiet
The agent appends the exact canonical card ID as the final argv value, so the
example command receives /srv/cba/bin/retire-preview --quiet CARD_ID. It also
sets KARDBRD_CARD_ID to that same value. The command receives a minimal
runtime environment (PATH, home/temp/locale settings, and
KARDBRD_CARD_ID), not KARDBRD_TOKEN, KARDBRD_API_URL, or executor
credentials. Do not use YAML interpolation for card titles, comments, or card
IDs; the direct argv and environment contract keeps those values out of a
shell.
The process working directory is the agent's configured base checkout
(KARDBRD_AGENT_CWD), never a card worktree. Cleanup scripts must treat that
directory as read-only; the cleanup contract prevents agent worktree lifecycle
operations but cannot prevent an operator-provided script from editing files.
For example, CBA's /srv/cba/bin/retire-preview can read the card ID from its
final argument (or KARDBRD_CARD_ID) and make its preview deletion idempotent:
an already-absent preview exits zero. The agent runs it as its existing
unprivileged account and applies the agent execution timeout. Nonzero exits and
timeouts are reported on the card with bounded, redacted diagnostics.
Before invoking a queued cleanup command, the agent reads the authoritative card state again. If the card has been moved out of Done, it skips the command. Matching cleanup owns the Done event, so normal Done rules and the default worktree removal lifecycle are suppressed for that event. Replayed events may invoke the command again after a prior run completes; make the resource command idempotent.
Exact card commands¶
The optional comment_command field creates an exact normal-card route. Its
rule must use only comment_created, must have an action, and command names
are unique per local agent configuration. execution defaults to prepare;
use existing_or_base for a read-only stop action that must not initialize a
worktree. See Portable worktree lifecycle for the full
ownership, queue, and deployment contract.
Model selection¶
Override the default model per-rule:
For Goose, use provider-specific model names or the short aliases above.
Rules and schedules can also set reasoning: high (accepted values: low, medium, high, xhigh, max). Claude receives --effort; Codex receives --config model_reasoning_effort=.... Goose and Pi reject a configured effort with an actionable error. If either setting is omitted, that value follows the executor's own configuration. A matched rule's model and effort remain attached to its queued command and publication continuation.
executor: codex
rules:
- name: Review
event: card_moved
list: Review
model: gpt-6.1-sol
reasoning: high
action: /kr
The bundled MBPBot rules in kardbrd.yml keep their existing models and set reasoning: high. Migration warning: this feature makes previously ignored reasoning settings effective. Before upgrading a live MBPBot daemon, inspect the configuration file it actually loads and change the applicable MBPBot rules from xhigh to the requested high. The bundled file does not update a separate deployed copy. Preserve intentionally configured efforts for other agents and workflows. See the operator checklist before release.
An exact configured slash command is handled by its command rule first; other addressed comments take precedence over matching ordinary comment_created rules. For direct comment selection, see Addressed Comment Dispatch.
Examples¶
Auto-explore new cards¶
rules:
- name: Explore new ideas
event:
- card_created
- card_moved
list: Ideas
model: sonnet
action: /ke
Stop agent on reaction¶
Code review on approval¶
rules:
- name: Review on checkmark
event: reaction_added
emoji: "✅"
require_user: E21K9jmv
require_label: Agent
model: sonnet
action: /kr
Multi-agent board¶
Use require_label and exclude_label to scope rules per agent:
# Agent A handles "Agent"-labeled cards
rules:
- name: Handle agent cards
event: comment_created
require_label: Agent
action: /ki
# Agent B handles everything else
rules:
- name: Handle other cards
event: comment_created
exclude_label: Agent
action: /ke
Per-user workflows¶
rules:
- name: Auto-assign senior review
event: card_moved
list: Review
assignee:
- E21K9jmv
model: opus
action: |
Perform a thorough code review of this PR.
Validation¶
Validate your rules file before deploying:
Hot-reload¶
The rule engine watches kardbrd.yml for changes and reloads ordinary rules and
schedules automatically every 60 seconds. worktree and complete
comment_command policy changes are restart-only; an incompatible reload keeps
the current configuration active.