Memory rules
Rules are if-this-then-that for project broadcasts. When an event of on_kind fires and the optional where predicate matches, one or more actions run server-side with template substitution from the event payload. No client glue, no polling.
Three actions are available: set_broadcast, pin_memory, and record_turn. Rule actions can’t install other rules; the recursion guard suppresses rule re-dispatch from inside an action so set_broadcast → broadcast_set → rule loops don’t run away.
Bundled defaults
Section titled “Bundled defaults”list_default_rules returns three ready-to-install rules. The dashboard’s Rules page renders them with one-click install buttons, but the same data is available over MCP for agent-driven setup.
| name | fires on | does |
|---|---|---|
error-pin | turn_recorded where metadata.kind == "error" | Auto-pins a memory referencing the turn so errors survive consolidation. |
claim-watchdog | claim_expired | Sets the last_abandoned_claim broadcast so downstream agents can detect orphaned work. |
review-router | turn_recorded where metadata.tag == "needs_review" | Publishes a review_queue:latest broadcast carrying the actor + content preview. |
Install one in two calls:
const { defaults } = await mt.listDefaultRules();const errorPin = defaults.find((d) => d.name === "error-pin")!;await mt.installRule(errorPin);Custom rules
Section titled “Custom rules”Install your own with install_rule. Example: pin every TS2345 compile error.
await mt.installRule({ name: "ts2345-watchdog", description: "Pin every TS2345 'argument of type' error", on_kind: "turn_recorded", where: { "payload.metadata.kind": "error", "payload.content_preview": { "$matches": "TS2345" }, }, actions: [ { tool: "pin_memory", args: { content: "TS2345 hit: ${payload.content_preview}", tags: ["error", "ts2345"], }, }, ],});Predicate grammar
Section titled “Predicate grammar”The where predicate is JSON-shaped, Mongo-flavored:
- Plain values are
$eqshorthand:{ "payload.role": "tool" } - Operator forms:
$eq,$ne,$in,$nin,$matches(regex),$exists,$gt,$gte,$lt,$lte - Multiple keys at any level AND together
- Top-level
$orflips to disjunction:{ "$or": [{ "payload.role": "tool" }, { "payload.role": "system" }] } - Field paths use the same convention as action template substitution:
payload.X/event.X
Bad predicates evaluate to false (rule doesn’t fire) rather than throwing. Typos can’t crash dispatch.
Event kinds
Section titled “Event kinds”Rules can listen to: turn_recorded, memory_pinned, memory_forgotten, broadcast_set, consolidation_completed, claim_acquired, claim_released, claim_expired.
presence_updated is intentionally excluded; a rule action that emits a turn would trigger the next user heartbeat, which would run the rule again.
See also
Section titled “See also”- Tool reference:
install_rule,list_rules,forget_rule,list_default_rules - Team coordination: the broadcasts rules listen to