Docs

Reactive Triggers

Triggers are rules that fire automatically when something happens in your memory graph — a memory is stored, recalled, boosted, linked, or its heat crosses a boundary. No polling. No cron jobs. Your memory governs itself.

Sulcus · Memory Triggers Reference · 2026

What are Triggers?

Reactive rules that run server-side whenever a memory event fires

Every other memory system is passive. You store. You retrieve. The memory sits there, decaying silently, waiting to be queried.

Sulcus triggers make memory active. When a new preference is stored, it can pin itself automatically. When a memory is recalled repeatedly, it reinforces its own heat — spaced repetition with zero configuration. When a critical procedure starts cooling, your agent knows before it slips out of context.

No competitor offers this. Triggers run server-side, fire during MCP tool calls, and surface inline as trigger_notifications. The result: a memory graph that manages its own lifecycle, without any orchestration code on your side.

Event-driven

Fires on memory events — not on a timer, not by polling.

Server-side

Runs inside the Sulcus engine. No extra infrastructure required.

Inline notifications

Results surface directly in your agent's tool responses.

Trigger Events

Six event types span the full memory lifecycle

on_storeA new memory node is created

Fires immediately after memory_store or record_memory. Auto-tag, auto-pin, or webhook new content the moment it enters the graph.

Auto-pin by typeTag on creationWebhook external systems
on_recallA memory is returned by search

Fires for each node returned during memory_recall or search_memory. Ideal for spaced repetition — recalled memories stay hot.

Spaced repetitionNotify on critical recallTrack what surfaces
on_decayMemory heat drops during the decay tick

Fires per-node during the thermodynamic tick. Catch important memories before they cool — re-pin, alert, or webhook before expiry.

Cold memory alertRe-pin before expiryWebhook cooling procedures
on_boostMemory heat is explicitly increased

Fires when memory_boost or feedback("relevant") increases heat. Chain actions, log escalations, relay to external systems.

Chain boost actionsLog escalationsNotify on priority shift
on_relateTwo memory nodes are linked by an edge

Fires when memory_relate creates a relationship. Propagate tags, boost related nodes, or log graph-level events.

Propagate tagsBoost related nodesGraph event logging
on_thresholdHeat crosses a configured boundary

Fires when heat crosses filter_heat_above or filter_heat_below. More precise than on_decay — targets exact heat windows.

Alert at heat=0.3Boost at heat=0.9Webhook on crossings

Trigger Actions

Seven actions control what happens when a trigger fires

notifysurfaces inline

Surfaces a message in the agent's tool response as a trigger_notification. Seen in real time. Supports template interpolation with memory metadata.

// Template variables: {node_id} {label} {namespace} {heat} {event}
{
  "action": "notify",
  "action_config": {
    "template": "Memory stored: '{label}' in {namespace} (heat: {heat:.2f})"
  }
}
json
boostconfigurable strength

Increases heat by action_config.strength (default 0.1, range 0–1, capped at 1.0). Combine with on_recall for automatic spaced repetition.

pinprevents all decay

Sets is_pinned=true. Memory never decays below min_heat. Combine with on_store + filter_memory_type=preference to make every user preference permanent automatically.

taglabel mutation

Appends action_config.tagto the memory's tag list. Use with on_store to automatically mark new episodic memories for downstream pipelines.

deprecateaccelerates decay

Reduces heat and marks the memory as superseded. Automatically deprecate stale procedures when a new one arrives under the same label pattern. Pairs with filter_label_pattern.

webhookHMAC-SHA256 signed

HTTP POST to an external URL — signed, 5s timeout, 1 retry. Notify Slack, trigger CI/CD, or sync with external systems when important memories change.

// HTTP POST — HMAC-SHA256 signed
// Headers: X-Sulcus-Signature: sha256=<hmac>  |  X-Sulcus-Event: on_store
{
  "event": "on_store",
  "trigger_name": "deploy-webhook",
  "fired_at": "2026-03-19T10:00:00Z",
  "node": {
    "id": "node_01J...",
    "label": "Deploy: push to ACR then az containerapp update",
    "memory_type": "procedural",
    "namespace": "icarus",
    "heat": 0.95,
    "tags": ["deploy", "azure"]
  }
}
json
chaincoming v2

Compose trigger pipelines — chain one trigger into another. Planned for v2.

Trigger Filters

Scope triggers precisely — only fire when the memory matches your criteria

FilterTypeBehaviour
filter_memory_typestringOnly fire for a specific memory type: episodic, semantic, preference, procedural, fact, moment.
filter_namespacestringScope to a single namespace (agent ID). Trigger only fires for memories in this namespace.
filter_label_patternstringCase-insensitive substring match on the memory label. "deploy" matches any label containing "deploy".
filter_heat_abovenumber 0–1Only fire when the memory heat is strictly above this value at event time.
filter_heat_belownumber 0–1Only fire when heat is strictly below this value. Combine with on_decay or on_threshold for cooling alerts.

All filters are optional and combinable. Multiple filters are AND-ed together — all conditions must match for the trigger to fire.

Trigger Configuration

Common fields that control a trigger's behaviour and lifecycle

FieldTypeDefaultDescription
namestringHuman-readable identifier shown in logs and notifications.
eventstringRequired. One of the six event types.
actionstringRequired. One of the seven action types.
action_configobject{}Action-specific options: strength (boost), tag (tag), url/headers (webhook), template (notify).
cooldown_secondsnumber0Minimum seconds between consecutive firings of this trigger.
max_firesnumber?nullMaximum total firings allowed (null = unlimited).
enabledbooleantrueToggle the trigger on/off without deleting it.

MCP Tools

Five MCP tools give your agent full trigger CRUD from within any conversation

create_trigger — Create a new trigger.

// MCP tool — create_trigger
{
  "name": "auto-pin-preferences",
  "event": "on_store",
  "action": "pin",
  "filter_memory_type": "preference",
  "cooldown_seconds": 0,
  "max_fires": null,
  "enabled": true
}
json

list_triggers — List all triggers, with optional event filter.

// MCP tool — list_triggers  (event filter optional)
{ "event": "on_store" }

// Response
[{
  "id": "trig_01J...", "name": "auto-pin-preferences",
  "event": "on_store", "action": "pin",
  "filter_memory_type": "preference",
  "fire_count": 4, "enabled": true,
  "created_at": "2026-03-16T18:23:11Z"
}]
json

update_trigger — Modify config, enable/disable, reset fire count.

// MCP tool — update_trigger
{
  "trigger_id": "trig_01J...",
  "enabled": false,           // pause the trigger
  "cooldown_seconds": 300,    // add 5-minute cooldown
  "reset_fire_count": true    // reset counter to 0
}
json

delete_trigger — Remove a trigger and its full history. Takes "trigger_id": "trig_01J...".

trigger_history — View the firing log (filterable by trigger).

// MCP tool — trigger_history
{ "trigger_id": "trig_01J...", "limit": 10 }

// Response
[{
  "id": "fire_01J...",
  "trigger_name": "auto-pin-preferences",
  "event": "on_store", "action": "pin",
  "node_id": "node_01J...",
  "node_label": "User prefers dark mode",
  "fired_at": "2026-03-19T09:45:01Z"
}]
json

REST API

Full CRUD over HTTP — integrate with any language or toolchain

GET/api/v1/triggers
POST/api/v1/triggers
PATCH/api/v1/triggers/:id
DELETE/api/v1/triggers/:id
GET/api/v1/triggers/history
# List all triggers
curl https://api.sulcus.ca/api/v1/triggers \
  -H "Authorization: Bearer sk-..."

# Create
curl -X POST https://api.sulcus.ca/api/v1/triggers \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"name":"boost-on-recall","event":"on_recall","action":"boost","action_config":{"strength":0.15}}'

# Update (pause)
curl -X PATCH https://api.sulcus.ca/api/v1/triggers/trig_01J... \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"enabled": false}'

# Delete
curl -X DELETE https://api.sulcus.ca/api/v1/triggers/trig_01J... \
  -H "Authorization: Bearer sk-..."

# History
curl "https://api.sulcus.ca/api/v1/triggers/history?limit=20" \
  -H "Authorization: Bearer sk-..."
bash

Practical Examples

Real-world trigger patterns that make your agents smarter

1. Auto-pin preferences on store

Every preference memory is pinned the moment it is created — no manual pinning required. User preferences never decay out of context.

on_storepin|filter_memory_type: preference

2. Spaced repetition (boost on recall)

Each time a memory surfaces in search results, its heat is bumped up. The more an agent uses a memory, the hotter it stays. Mimics human spaced repetition.

on_recallboost|action_config.strength: 0.15

3. Cold memory alert

When a procedural memory (how-to, deploy instructions, runbooks) cools below heat 0.3, your agent gets an inline notification before the context is lost.

on_decaynotify|filter_memory_type: procedural + filter_heat_below: 0.3

4. Webhook to Slack on deploy changes

When any memory containing "deploy" in its label is stored, fire a signed webhook to Slack. Your team is notified the moment an agent updates deployment knowledge.

on_storewebhook|filter_label_pattern: deploy

5. Tag new episodic memories for review

All episodic memories (events, conversations) are tagged "needs-review" on creation. A downstream workflow can then process, summarise, or escalate them.

on_storetag|filter_memory_type: episodic

SDK Reference

Python and Node.js code for complete trigger CRUD

Python

from sulcus import Sulcus
client = Sulcus(api_key="sk-...")

# 1. Auto-pin preferences on store
client.create_trigger(event="on_store", action="pin",
    name="auto-pin-preferences", filter_memory_type="preference")

# 2. Spaced-repetition boost on every recall
client.create_trigger(event="on_recall", action="boost",
    name="reinforce-on-recall", action_config={"strength": 0.15})

# 3. Cold memory alert — notify when procedure cools below 0.3
client.create_trigger(event="on_decay", action="notify",
    name="cold-memory-alert", filter_memory_type="procedural",
    filter_heat_below=0.3,
    action_config={"template": "Warning: '{label}' cooling (heat: {heat:.2f})"})

# 4. Webhook to Slack when deployment procedures change
client.create_trigger(event="on_store", action="webhook",
    name="deploy-webhook", filter_memory_type="procedural",
    filter_label_pattern="deploy",
    action_config={"url": "https://hooks.slack.com/services/T000/B000/xxxx"})

# 5. Tag new episodic memories for review
client.create_trigger(event="on_store", action="tag",
    name="tag-new-episodic", filter_memory_type="episodic",
    action_config={"tag": "needs-review"})

# List
for t in client.list_triggers():
    print(f"[{'on' if t['enabled'] else 'off'}] {t['name']}  fired {t['fire_count']}x")

# History
for h in client.trigger_history(limit=10):
    print(f"  {h['fired_at']}  {h['trigger_name']}")

# Update
client.update_trigger("trig_01J...", cooldown_seconds=300, enabled=False)

# Delete
client.delete_trigger("trig_01J...")
python

Node.js / TypeScript

import { Sulcus } from "@digitalforgestudios/sulcus";
const client = new Sulcus({ apiKey: "sk-..." });

// 1. Auto-pin preferences on store
await client.createTrigger("on_store", "pin", {
  name: "auto-pin-preferences", filterMemoryType: "preference" });

// 2. Spaced-repetition boost on every recall
await client.createTrigger("on_recall", "boost", {
  name: "reinforce-on-recall", actionConfig: { strength: 0.15 } });

// 3. Cold memory alert
await client.createTrigger("on_decay", "notify", {
  name: "cold-memory-alert", filterMemoryType: "procedural",
  filterHeatBelow: 0.3,
  actionConfig: { template: "Warning: '{label}' cooling (heat: {heat})" } });

// 4. Webhook to Slack on deploy procedure changes
await client.createTrigger("on_store", "webhook", {
  name: "deploy-webhook", filterMemoryType: "procedural",
  filterLabelPattern: "deploy",
  actionConfig: { url: "https://hooks.slack.com/services/T000/B000/xxxx" } });

// 5. Tag new episodic memories
await client.createTrigger("on_store", "tag", {
  name: "tag-new-episodic", filterMemoryType: "episodic",
  actionConfig: { tag: "needs-review" } });

// List
const triggers = await client.listTriggers();
triggers.forEach(t =>
  console.log(`[${t.enabled ? "on" : "off"}] ${t.name}  fired ${t.fire_count}x`));

// Update, delete, history
await client.updateTrigger("trig_01J...", { cooldownSeconds: 300, enabled: false });
await client.deleteTrigger("trig_01J...");
const history = await client.triggerHistory({ limit: 10 });
typescript

How Triggers Appear in Context

Active triggers and recent firings are injected into the LLM system prompt

When Sulcus builds the system prompt context block for your agent, it includes two trigger sections: active_triggers (all enabled triggers with their fire counts) and recent_trigger_fires (the last N firings). This gives the model situational awareness about what rules are active and what has recently happened — without the agent needing to call list_triggers.

The agent can read this context to make smarter decisions: it knows a cold memory alert just fired, knows which memories were just boosted, and knows which namespaces are being monitored.

<active_triggers>
  <trigger name="auto-pin-preferences" event="on_store" action="pin" fires="4" filter="preference" />
  <trigger name="notify-on-recall" event="on_recall" action="notify" fires="246" />
  <trigger name="cold-memory-alert" event="on_decay" action="notify" fires="0" />
  <trigger name="strategy-boost" event="on_threshold" action="boost" fires="299" filter="@icarus" />
  <trigger name="tag-new-episodic" event="on_store" action="tag" fires="54" filter="episodic@icarus" />
</active_triggers>

<recent_trigger_fires>
  <fire event="on_threshold" action="boost" node="Strategy: growth"  at="2026-03-19T09:56:32Z" />
  <fire event="on_recall"    action="notify" node="Deploy procedure" at="2026-03-19T09:50:10Z" />
  <fire event="on_recall"    action="notify" node="User preferences" at="2026-03-19T09:50:09Z" />
  <fire event="on_threshold" action="boost" node="Architecture"     at="2026-03-19T09:50:03Z" />
</recent_trigger_fires>
xml

Why this matters: The model can see that notify-on-recall has fired 246 times — meaning this agent has been actively recalling memories and reinforcing them. The cold-memory-alert trigger has never fired, meaning no procedural memories have cooled below threshold. This is memory system telemetry, inline, for free.

Your memory, reactive.

Triggers are available in the Sulcus SDK, MCP server, and REST API today. Start with the auto-pin-preferences pattern — one trigger, three lines of code, and your agent's preference recall becomes permanent.