Skip to content

Causal Queries

advanced

Ask 'what if?' and 'why did this happen?' to your memory. A hands-on guide to intervention and counterfactual queries.

What you'll build

A system that answers causal questions — "What happens if we do X?", "What caused Y?", "Would Z have happened if we hadn't done W?" — using memories you've stored.

Prerequisites

RequirementDetails
AccountStarter tier or above
API keyFrom your dashboard
SDKPython or JavaScript
KnowledgeFamiliarity with Causal Reasoning concepts
Time~15 minutes

The three levels of causal queries

LevelQuestion typeExample
Association"What is related to X?""What's related to deployment failures?"
Intervention"What happens if I do X?""What happens if we increase memory?"
Counterfactual"Would Y have happened without X?""Would we have crashed without the spike?"

Steps

1

Store causal facts

Store facts that describe cause-and-effect relationships. The engine detects causal language automatically.
2

Query at Level 1 (Association)

Start with simple similarity queries to see what's related.
3

Query at Level 2 (Intervention)

Ask 'what if?' questions. The engine traces causal chains forward.
4

Query at Level 3 (Counterfactual)

Ask 'would X have happened?' questions. The engine reasons backwards through the causal graph.
5

Explore causal neighbors

Use the causal_neighbors endpoint to map upstream causes and downstream effects.

Complete code

import os
from engramma_cloud import EngrammaClient

client = EngrammaClient(api_key=os.environ["ENGRAMMA_API_KEY"])

# Store facts with causal relationships
# (The engine detects causal language automatically)
causal_facts = [
    "High traffic spikes cause increased API latency",
    "Increased API latency triggers auto-scaling",
    "Auto-scaling adds new pods within 30 seconds",
    "New pods restore normal latency levels",
    "Cache misses increase database load",
    "Database load above 80% causes query timeouts",
    "Query timeouts trigger circuit breaker activation",
    "Circuit breaker reduces traffic to the database",
    "Reduced traffic allows database recovery",
]

for fact in causal_facts:
    client.store(fact, metadata={"domain": "infrastructure"})

print("Stored 9 causal facts\n")

# --- Level 1: Association ---
print("=== Level 1: Association ===")
results = client.retrieve("API latency problems")
for r in results[:3]:
    print(f"  [{r.confidence:.2f}] {r.text}")

# --- Level 2: Intervention ---
print("\n=== Level 2: Intervention ===")
results = client.retrieve(
    "What happens if we get a traffic spike?",
    causal=True
)
print(f"  Direct effect: {results[0].text}")
if results[0].causal_chain:
    print(f"  Causal chain:")
    for step in results[0].causal_chain:
        print(f"    → {step}")

# --- Level 3: Counterfactual ---
print("\n=== Level 3: Counterfactual ===")
results = client.retrieve(
    "Would we have had query timeouts if caching was working?",
    causal=True
)
print(f"  Analysis: {results[0].text}")
if results[0].counterfactual:
    print(f"  Counterfactual: {results[0].counterfactual}")

# --- Explore causal neighbors ---
print("\n=== Causal Neighbors ===")
neighbors = client.causal_neighbors(
    query="database load",
    direction="both",
    depth=2
)
for n in neighbors:
    print(f"  {n.direction}: {n.text} (strength: {n.strength:.2f})")

Expected output

Stored 9 causal facts

=== Level 1: Association ===
  [0.91] High traffic spikes cause increased API latency
  [0.85] Increased API latency triggers auto-scaling
  [0.72] New pods restore normal latency levels

=== Level 2: Intervention ===
  Direct effect: High traffic spikes cause increased API latency
  Causal chain:
    → Increased API latency triggers auto-scaling
    → Auto-scaling adds new pods within 30 seconds
    → New pods restore normal latency levels

=== Level 3: Counterfactual ===
  Analysis: Cache misses increase database load
  Counterfactual: If caching was working, cache misses would not occur,
    breaking the chain to database overload and query timeouts.

=== Causal Neighbors ===
  upstream: Cache misses increase database load (strength: 0.87)
  downstream: Database load above 80% causes query timeouts (strength: 0.91)
  downstream: Query timeouts trigger circuit breaker activation (strength: 0.83)

Causal links aren't static. They strengthen or weaken based on evidence:

# Store reinforcing evidence — strengthens the causal link
client.store("Traffic spike at 2pm caused 500ms latency increase")
client.store("Yesterday's spike triggered auto-scaling within 25s")

# Store contradicting evidence — weakens the link
client.store("Traffic spike at 3pm did NOT cause latency increase (cache was warm)")

# After consolidation, link strengths update:
# traffic → latency: strength drops from 0.91 to 0.78 (sometimes doesn't happen)
# traffic → auto-scaling: strength stays high (still triggered)

# Check current link strength
explanation = client.explain(
    query="Does traffic always cause latency issues?",
    level="technical"
)
print(explanation.routing_factors)

Real-world patterns

Incident post-mortem

# After an incident, store the chain of events
client.store("DNS provider had a 10-minute outage at 14:00")
client.store("DNS outage caused service discovery failures")
client.store("Service discovery failures caused 503 errors for users")
client.store("503 errors triggered PagerDuty incident INC-1234")

# Later, ask causal questions
results = client.retrieve(
    "What was the root cause of INC-1234?",
    causal=True
)
# Engine traces back: PagerDuty ← 503s ← service discovery ← DNS outage

Impact analysis

# Before making a change, check downstream effects
neighbors = client.causal_neighbors(
    query="deprecate the v1 API",
    direction="downstream",
    depth=3
)

print("Deprecating v1 API may affect:")
for n in neighbors:
    print(f"  → {n.text} (strength: {n.strength:.2f})")
Warning

Causal reasoning requires evidence. Store at least 2-3 related facts before expecting reliable causal chains. The more evidence the engine has, the more accurate its causal reasoning becomes.

Next steps