Memory compositionality
Shipped in v3-alpha (Beta). Third zero-LLM feature — pure graph traversal + rule application. Interfaces may still change before 3.0 stable.
The philosophy
If Fact A says “Service X calls Service Y” and Fact B says “Service Y has 5s timeout”, we can infer “Service X waits up to 5s for Y” without ever storing or generating that with an LLM. Pure pattern matching on the graph.
COMPOSITION ENGINE
Forward-chaining rule engine over knowledge graph.
Zero LLM calls. Deterministic. Auditable.
Input: Recalled facts + entity graph + relation verbs
Output: Inferred statements (confidence < 1.0) with provenance
ROI: Every inference saves 1 LLM reasoning stepDeclarative rules
interface CompositionRule {
id: string;
name: string;
pattern: {
facts: FactPattern[];
relations: RelationPattern[];
};
inference: {
template: string; // "{{A.subject}} depends on {{B.subject}}"
confidence: number;
type: "fact" | "warning";
};
}Built-in rules (excerpt)
const COMPOSITION_RULES: CompositionRule[] = [
{
id: "transitive_dependency",
name: "A depends on B, B depends on C → A transitively depends on C",
inference: {
template: "{{A}} transitively depends on {{C}} (via {{B}})",
confidence: 0.6,
type: "fact",
},
},
{
id: "timeout_conflict",
name: "Caller timeout < callee processing time → potential failure",
inference: {
template: "⚠️ {{A}} may timeout calling {{B}} ({{A.timeout}} < {{B.processing_time}})",
confidence: 0.8,
type: "warning",
},
},
{
id: "supersession_chain",
name: "A supersedes B, B supersedes C → only A is current",
inference: {
template: "{{C}} is doubly superseded — only {{A}} is current truth",
confidence: 0.95,
type: "fact",
},
},
{
id: "shared_dependency_risk",
name: "Multiple services depend on same entity → SPOF",
inference: {
template: "⚠️ {{X}} is a SPOF — {{A}}, {{B}}, {{C}} all depend on it",
confidence: 0.75,
type: "warning",
},
},
];Custom rules per workspace
await mnemo.createCompositionRule({
name: "team_on_call",
pattern: {
facts: [
{ subject: "?person", predicate: "is_on_call", value: "true" },
{ subject: "?service", predicate: "owned_by", value: "?person" },
],
},
inference: {
template: "{{person}} is on-call AND owns {{service}} — they handle incidents for it",
confidence: 0.9,
type: "fact",
},
});Execution (post-recall hook)
function composeInferences(hits: RecallHit[], graph: SubGraph): ComposedInference[] {
const inferences: ComposedInference[] = [];
for (const rule of COMPOSITION_RULES) {
for (const match of matchPattern(rule.pattern, hits, graph)) {
inferences.push({
content: interpolate(rule.inference.template, match.bindings),
confidence: rule.inference.confidence * avgConfidence(match.facts),
type: rule.inference.type,
provenance: match.facts.map(f => f.id),
ruleId: rule.id,
});
}
}
return inferences.filter(i => i.confidence > 0.5);
}ROI
Without composition:
Agent recalls "Service X timeout = 3s" + "Service Y processing = 5s"
→ reasoning tokens to figure out "X will timeout calling Y"
Cost: ~50–200 reasoning tokens per inference
With composition:
Engine appends "⚠️ Service X may timeout calling Y (3s < 5s)"
Agent reads it — no reasoning needed
Cost: 0 tokens
At scale: 10 inferences/session × 100 tokens saved each = 1000 tokens/sessionSee also
- Hypergraph relations — the substrate for n-ary rule matching
- Trust-anchor consensus — companion zero-LLM feature