Documentation

Everything you need to give your AI agents persistent memory.

Install

Python

pip install sulcus

# With async support:
pip install sulcus[async]
bash

Python 3.9+ · Zero dependencies · Async via optional httpx

Node.js

npm install sulcus
bash

Node 18+ · Zero dependencies · Full TypeScript support

Quick Start

Python

from sulcus import Sulcus

client = Sulcus(api_key="sk-...")

# Store memories with full lifecycle control
client.remember("User prefers dark mode", memory_type="preference",
    decay_class="slow",       # slow decay — preferences persist
    is_pinned=True,           # pinned — never decays
    min_heat=0.3,             # floor heat — never goes below 0.3
    key_points=["dark mode", "UI preference"])

client.remember("API rate limit is 1000/min", memory_type="semantic")

# Search
results = client.search("dark mode")
for m in results:
    print(f"[{m.memory_type}] {m.pointer_summary} (heat: {m.current_heat:.2f}")

# Recall feedback — reinforces good memories, penalizes bad ones
client.feedback(results[0].id, "relevant")    # boosts heat + stability
client.feedback(results[1].id, "outdated")    # marks as superseded

# List with filters
memories = client.list(page=1, page_size=10, memory_type="preference")

# Pin / unpin
client.pin(memories[0].id)
client.unpin(memories[0].id)

# Bulk operations
client.bulk_update(["id-1", "id-2"], is_pinned=True, heat=0.9)
client.bulk_delete(memory_type="episodic", namespace="old-session")

# Analytics
analytics = client.recall_analytics()
print(analytics["suggestions"])  # tuning recommendations based on feedback patterns
python

Node.js / TypeScript

import { Sulcus } from "sulcus";

const client = new Sulcus({ apiKey: "sk-..." });

// Store memories with full lifecycle control
await client.remember("User prefers dark mode", {
  memoryType: "preference",
  decayClass: "slow",       // slow decay — preferences persist
  isPinned: true,           // pinned — never decays
  minHeat: 0.3,             // floor heat — never goes below 0.3
  keyPoints: ["dark mode", "UI preference"],
});

await client.remember("API rate limit is 1000/min", { memoryType: "semantic" });

// Search
const results = await client.search("dark mode");
for (const m of results) {
  console.log(`[${m.memory_type}] ${m.pointer_summary} (heat: ${m.current_heat.toFixed(2)})`);
}

// Recall feedback — reinforces good memories, penalizes bad ones
await client.feedback(results[0].id, "relevant");    // boosts heat + stability
await client.feedback(results[1].id, "outdated");    // marks as superseded

// List with filters
const memories = await client.list({ page: 1, pageSize: 10, memoryType: "preference" });

// Bulk operations
await client.bulkUpdate(["id-1", "id-2"], { isPinned: true, heat: 0.9 });
await client.bulkDelete({ memoryType: "episodic", namespace: "old-session" });

// Analytics & tuning suggestions
const analytics = await client.recallAnalytics();
console.log(analytics.suggestions);
typescript

Python Async

import asyncio
from sulcus import AsyncSulcus

async def main():
    async with AsyncSulcus(api_key="sk-...") as client:
        await client.remember("async memory", memory_type="semantic")
        results = await client.search("async")
        print(results)

asyncio.run(main())
python

Memory Types

episodicDecay: Fast

Events, conversations, time-bound experiences

"Met with design team, decided on blue theme"

semanticDecay: Slow

Facts, knowledge, definitions

"Python 3.12 requires typing_extensions >= 4.0"

preferenceDecay: Medium

User preferences, settings, opinions

"User prefers dark mode and monospace fonts"

proceduralDecay: Slow

How-to knowledge, workflows, recipes

"To deploy: git push, then az acr build, then update app"

momentDecay: Glacial

Personality-defining interactions, relationship dynamics

"User laughed and said 'that's why I trust you'"

Memory Lifecycle Control

Every memory has a heat value that decays over time. You control the speed, the floor, and the permanence.

Decay Classes

fastHalf-life: ~2 hours

Ephemeral context, short-lived tasks

normalHalf-life: ~24 hours

Standard memories (default)

slowHalf-life: ~7 days

Important facts, preferences

glacialHalf-life: ~30 days

Core identity, relationships, moments

Lifecycle Parameters

is_pinned

Prevents ALL heat decay. Memory stays hot forever. Use for core identity, rules, permanent preferences.

min_heat

Floor value (0.0–1.0). Memory decays but never drops below this. Ensures minimum recall priority.

decay_class

Override the default decay speed for this memory type. Options: fast, normal, slow, glacial.

key_points

Structured metadata — list of key takeaways. Improves search relevance and context building.

MCP Integration

Sulcus speaks MCP (Model Context Protocol) natively. Connect any MCP-compatible client — Claude Desktop, OpenAI agents, custom hosts — directly to your memory graph.

# Claude Desktop — add to claude_desktop_config.json:
{
  "mcpServers": {
    "sulcus": {
      "url": "https://api.sulcus.ca/mcp",
      "transport": "streamable-http",
      "headers": {
        "Authorization": "Bearer sk-your-api-key"
      }
    }
  }
}
json

29 MCP tools available: search_memory, commit_memory, record_memory, build_context, list_hot_nodes, tick, prune_cold_memories, forget_memory, page_in, compact_wal, sync_now, create_trigger, list_triggers, update_trigger, delete_trigger, trigger_history, and more.

Reactive Triggers

Set rules on your memory graph. When events happen — a memory is stored, recalled, boosted, or decays — Sulcus fires actions automatically. No competitor has this. Triggers run server-side and locally, fire during MCP tool calls, and surface notifications inline.

on_store

New memory created

on_recall

Memory searched/recalled

on_boost

Memory heat increased

on_relate

Edge created between memories

on_decay

Heat dropped during tick

on_threshold

Heat crosses boundary

pin
boost
tag
deprecate
notify
webhook
chain (v2)

Python

# Reactive Triggers — automate memory lifecycle
from sulcus import Sulcus

client = Sulcus(api_key="sk-...")

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

# Boost memories every time they're recalled (spaced repetition)
client.create_trigger(
    event="on_recall",
    action="boost",
    name="reinforce-on-recall",
    action_config={"strength": 0.15}
)

# Webhook when critical memory starts cooling
client.create_trigger(
    event="on_threshold",
    action="webhook",
    name="alert-cold-procedures",
    filter_memory_type="procedural",
    filter_heat_below=0.3,
    action_config={"url": "https://hooks.slack.com/your-webhook"}
)

# List active triggers
triggers = client.list_triggers()
for t in triggers:
    print(f"{t['name']}: {t['event']} → {t['action']} (fired {t['fire_count']}x)")
python

Node.js

import { Sulcus } from "sulcus";

const client = new Sulcus({ apiKey: "sk-..." });

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

// Boost memories every time they're recalled
await client.createTrigger("on_recall", "boost", {
  name: "reinforce-on-recall",
  actionConfig: { strength: 0.15 },
});

// Webhook when critical memory starts cooling
await client.createTrigger("on_threshold", "webhook", {
  name: "alert-cold-procedures",
  filterMemoryType: "procedural",
  filterHeatBelow: 0.3,
  actionConfig: { url: "https://hooks.slack.com/your-webhook" },
});

// Check trigger history
const history = await client.triggerHistory();
for (const h of history) {
  console.log(`${h.event} → ${h.action} at ${h.fired_at}`);
}
typescript

REST API

# Create a trigger
curl -X POST https://api.sulcus.ca/api/v1/triggers \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "auto-pin-preferences",
    "event": "on_store",
    "action": "pin",
    "filter_memory_type": "preference"
  }'

# List triggers
curl https://api.sulcus.ca/api/v1/triggers \
  -H "Authorization: Bearer sk-..."

# Delete a trigger
curl -X DELETE https://api.sulcus.ca/api/v1/triggers/{id} \
  -H "Authorization: Bearer sk-..."
bash

REST API

Base URL: https://api.sulcus.ca
Authentication: Authorization: Bearer <api-key>

POST/api/v1/agent/nodesCreate a memory node
GET/api/v1/agent/nodesList memories (paginated)
GET/api/v1/agent/nodes/:idGet a single memory
PATCH/api/v1/agent/nodes/:idUpdate a memory
DELETE/api/v1/agent/nodes/:idDelete a memory
POST/api/v1/agent/searchText search memories
GET/api/v1/agent/hot_nodesList hottest memories
POST/api/v1/agent/nodes/bulk-patchBulk update memories (shared patch or per-node)
POST/api/v1/agent/nodes/bulkBulk delete by IDs, type, or namespace
POST/api/v1/agent/syncCRDT sync (push/pull ops)
GET/api/v1/metricsStorage & health metrics
GET/api/v1/orgTenant/org info & limits
GET/api/v1/keysList API keys
POST/api/v1/keysGenerate new API key
GET/api/v1/settings/thermoGet thermodynamic engine config
PATCH/api/v1/settings/thermoUpdate thermodynamic engine config
POST/api/v1/feedbackRecall quality feedback (relevant/irrelevant/outdated)
GET/api/v1/analytics/recallRecall analytics with tuning suggestions
GET/api/v1/activityActivity log (paginated, cursor-based)
GET/api/v1/gamification/profileXP, level, badges, streaks
GET/api/v1/triggersList active triggers
POST/api/v1/triggersCreate a reactive trigger
PATCH/api/v1/triggers/:idUpdate a trigger
DELETE/api/v1/triggers/:idDelete a trigger
GET/api/v1/triggers/historyTrigger firing history
POST/mcpMCP Streamable HTTP (JSON-RPC)
GET/mcpMCP SSE notification stream

Examples

# Create a memory
curl -X POST https://api.sulcus.ca/api/v1/agent/nodes \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"label": "User prefers dark mode", "memory_type": "preference"}'

# Search memories
curl -X POST https://api.sulcus.ca/api/v1/agent/search \
  -H "Authorization: Bearer sk-..." \
  -H "Content-Type: application/json" \
  -d '{"query": "dark mode", "limit": 10}'

# List memories
curl https://api.sulcus.ca/api/v1/agent/nodes?page=1&page_size=10 \
  -H "Authorization: Bearer sk-..."
bash

Self-Hosted

Point any SDK at your own server. The entire stack — server, database, sync — runs on your infrastructure.

# Python
client = Sulcus(api_key="your-key", base_url="http://localhost:4200")

# Node.js
const client = new Sulcus({ apiKey: "your-key", baseUrl: "http://localhost:4200" });
python

Framework Integrations

Dedicated packages for popular LLM frameworks. Each wraps the Sulcus API with framework-native abstractions.

LangChainpip install sulcus-langchain
LlamaIndexpip install sulcus-llamaindex
Vercel AI SDKnpm install sulcus-vercel-ai
OpenAI ToolsCopy tools.json
Anthropic ToolsCopy tools.json
CrewAIpip install sulcus-crewai
Deep Agentspip install sulcus-deepagents
CLInpm install -g sulcus-cli
OpenClawopenclaw plugins install
VS CodeMarketplace (coming)

Integration packages available on GitHub and npm.

Resources