# Graphiti Memory

> Query and record knowledge in the Graphiti MCP knowledge graph. Use for semantic search of platform knowledge, recording verified solutions, and building institutional memory. Complements file-based memory (docs/project_notes/) with semantic search capabilities.

- Skill: `shakudo-io/graphiti-memory` (Agent Skill)
- Install (CLI): `npx skillmds@latest add shakudo-io/graphiti-memory`
- Raw SKILL.md: https://api.skillmd.com/api/skills/shakudo-io/graphiti-memory/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- License: MIT
- Author: Shakudo-io (https://skillmd.com/u/shakudo-io)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/shakudo-io/graphiti-memory

---


# Graphiti Memory Skill

This skill teaches you how to use the Graphiti MCP for persistent knowledge graph memory. Graphiti provides semantic search across institutional knowledge, complementing the file-based memory system in `docs/project_notes/`.

## Prerequisites

- Graphiti MCP tools available (`search_nodes`, `search_memory_facts`, `add_memory`, `get_episodes`)
- FalkorDB backend running with vector indexes configured

## When to Search Graphiti (MANDATORY)

**You MUST search Graphiti BEFORE attempting to solve problems.**

| Trigger | Action |
|---------|--------|
| ANY error message or exception | Search first |
| Build or test failure | Search first |
| Configuration lookup needed | Search first |
| Architectural decision required | Search first |
| Debugging unexpected behavior | Search first |
| Questions about Shakudo platform | Search first |
| Questions about customers | Search first |
| Questions about infrastructure | Search first |

## How to Search

### CRITICAL: Always Pass 2+ group_ids

There is a confirmed upstream bug where searching with a single `group_ids` parameter returns empty results. **Always pass at least 2 group_ids.**

```python
# WRONG - Returns empty results (bug)
search_nodes(query="kubernetes", group_ids=["shakudo-platform-knowledge"])

# CORRECT - Add a dummy second group_id
search_nodes(query="kubernetes", group_ids=["shakudo-platform-knowledge", "dummy"])
```

The second group_id can be any string (even non-existent) - it just triggers the correct code path.

### Search Tools

| Tool | Purpose | When to Use |
|------|---------|-------------|
| `search_nodes` | Find entities by semantic similarity | Looking for concepts, topics, services |
| `search_memory_facts` | Find relationships between entities | Looking for connections, dependencies |
| `get_episodes` | List recent knowledge entries | Checking what was recently added |

### Search Examples

```python
# Search for error-related knowledge
search_nodes(
    query="401 authentication error iOS Mattermost",
    group_ids=["shakudo-platform-knowledge", "dummy"],
    max_nodes=5
)

# Search for architectural decisions
search_nodes(
    query="database schema design patterns",
    group_ids=["shakudo-platform-knowledge", "dummy"],
    max_nodes=5
)

# Search for customer information
search_nodes(
    query="Acme Corp deployment requirements",
    group_ids=["shakudo-platform-knowledge", "dummy"],
    max_nodes=5
)

# Search for relationships/facts
search_memory_facts(
    query="keycloak authentication configuration",
    group_ids=["shakudo-platform-knowledge", "dummy"]
)

# List recent episodes
get_episodes(
    group_ids=["shakudo-platform-knowledge", "dummy"],
    max_episodes=10
)
```

## Available Graphs

| Graph Name | Content |
|------------|---------|
| `shakudo-platform-knowledge` | Platform docs, AGENTS.md, operational knowledge, bugs, decisions |
| `monorepo-project-memory` | Monorepo codebase knowledge |
| `business-automation-project-memory` | Business automation project context |
| `{project}-project-memory` | Per-project memory graphs |

**Default**: Use `shakudo-platform-knowledge` for most queries unless working on a specific project.

## When to Record Knowledge (MANDATORY)

**You MUST record verified solutions to Graphiti after solving problems.**

### Record When ALL Conditions Met:
1. Problem was **SOLVED** (not just attempted)
2. Solution was **VERIFIED** working (tests pass, build succeeds, functionality confirmed)
3. Knowledge has **reuse value** (not a one-off typo fix)

### What to Record

| Category | Record When |
|----------|-------------|
| Bug fixes | Bug/error fixed with root cause identified |
| Architectural decisions | Technology/design choice made with rationale |
| Configuration | Configuration values discovered or changed |
| Workarounds | External system workarounds found |
| Customer knowledge | Customer info, use cases, requirements learned |
| Product knowledge | Feature capabilities, limitations discovered |
| System knowledge | Services, endpoints, dependencies documented |

### What NOT to Record

- Untested fixes ("this should work")
- Speculative solutions ("try X or maybe Y")
- One-off fixes (typo in one file)
- Duplicates (search first!)
- Sensitive credentials
- Temporary debugging details

## How to Record

### add_memory Tool

```python
add_memory(
    name="Brief descriptive title",
    group_id="shakudo-platform-knowledge",  # Single group_id for writes
    episode_body="Detailed description with context, cause, solution, verification",
    source_description="Source of this knowledge (e.g., bugs.md, conversation)"
)
```

### Recording Examples

#### Bug Fix
```python
add_memory(
    name="Bug: iOS Mattermost 401 After OIDC Login",
    group_id="shakudo-platform-knowledge",
    episode_body="2026-01-26 Issue: iOS Mattermost app gets 401 Unauthorized after successful OIDC login. Root Cause: istio-ingress-jwt RequestAuthentication in istio-system validates JWT on all requests. iOS app sends Authorization header with Mattermost token, which fails Keycloak validation. Solution: kubectl delete requestauthentication istio-ingress-jwt -n istio-system. Verified: Yiran tested on test3, iOS login works.",
    source_description="bugs.md"
)
```

#### Architectural Decision
```python
add_memory(
    name="Decision: Use Supabase Metaflow for App Databases",
    group_id="shakudo-platform-knowledge",
    episode_body="2026-01-29 Decision: All application development MUST use the Metaflow Supabase instance with dedicated schemas per application. Rationale: Prevents apps from accidentally modifying shared platform databases. Each app gets its own schema (e.g., ai_bdr_dialer). Connection: supabase-metaflow-postgresql.hyperplane-supabase-metaflow.svc.cluster.local:5432/postgres?schema={app_schema}. Alternative considered: Separate PostgreSQL instances (rejected - operational overhead).",
    source_description="decisions.md"
)
```

#### Customer Knowledge
```python
add_memory(
    name="Customer: Acme Corp",
    group_id="shakudo-platform-knowledge",
    episode_body="Acme Corp is a Shakudo customer in the fintech industry. They use Shakudo for ML pipeline orchestration and model serving. Primary contact: John Smith (john@acmecorp.com). Deployed on GCP us-central1. Key requirements: SOC2 compliance, sub-100ms inference latency. Current usage: 50+ pipelines, 10 deployed models.",
    source_description="conversation with user"
)
```

#### Configuration Fact
```python
add_memory(
    name="Config: Keycloak Realms",
    group_id="shakudo-platform-knowledge",
    episode_body="Shakudo Keycloak configuration: Production realm is 'hyperplane-dev' (not 'shakudo' or 'master'). Issuer URL: https://keycloak.dev.hyperplane.dev/realms/hyperplane-dev. Client IDs vary by app - check individual service configs. SKIP_AUTH=true bypasses Keycloak entirely for development.",
    source_description="key_facts.md"
)
```

#### System Knowledge
```python
add_memory(
    name="System: FalkorDB Vector Index Requirements",
    group_id="shakudo-platform-knowledge",
    episode_body="FalkorDB requires explicit vector index creation for similarity search. If Graphiti searches return empty despite data existing, check if vector index exists. Create with: kubectl exec -n hyperplane-falkordb <pod> -- redis-cli GRAPH.QUERY <graph-name> \"CREATE VECTOR INDEX FOR (n:Entity) ON (n.name_embedding) OPTIONS {dimension: 1024, similarityFunction: 'cosine'}\". Dimension must match embedding model (1024 for text-embedding-3-small).",
    source_description="troubleshooting notes"
)
```

### Recording Best Practices

1. **Name Format**: Use prefix to indicate type
   - `Bug: [Brief description]`
   - `Decision: [What was decided]`
   - `Config: [Configuration area]`
   - `Customer: [Company name]`
   - `System: [Service/component]`

2. **Episode Body Structure**:
   - Start with date (YYYY-MM-DD)
   - Include context/trigger
   - Explain root cause (for bugs)
   - Document solution with specifics (commands, code)
   - Note verification evidence
   - Mention alternatives considered (for decisions)

3. **Source Description**: Always cite where knowledge came from
   - `bugs.md`, `decisions.md`, `key_facts.md`
   - `conversation with user`
   - `deployment logs`
   - `troubleshooting session`

## Dual Recording: Files + Graphiti

**Record to BOTH file-based memory AND Graphiti.**

| System | Purpose | Strength |
|--------|---------|----------|
| Files (`docs/project_notes/`) | Human-readable, version-controlled, detailed | Exact error strings, full context |
| Graphiti | Semantic search, concept matching | Finds related issues with different wording |

### Workflow
1. Fix and verify the problem
2. Record to appropriate file (`bugs.md`, `decisions.md`, etc.)
3. Record to Graphiti with `add_memory()`

Both sources are searched during mandatory lookup (grep for files, search_nodes for Graphiti).

## Troubleshooting

### Empty Results Despite Data Existing

1. **Check group_ids**: Are you passing 2+ group_ids? (See bug workaround above)
2. **Check vector index**: FalkorDB may be missing the vector index

```bash
# Check if vector index exists
kubectl exec -n hyperplane-falkordb <pod> -- redis-cli GRAPH.QUERY <graph-name> "CALL db.indexes()" | grep -i vector

# Create vector index if missing
kubectl exec -n hyperplane-falkordb <pod> -- redis-cli GRAPH.QUERY <graph-name> \
  "CREATE VECTOR INDEX FOR (n:Entity) ON (n.name_embedding) OPTIONS {dimension: 1024, similarityFunction: 'cosine'}"
```

### Debug Commands

```bash
# List all graphs in FalkorDB
kubectl exec -n hyperplane-falkordb <pod> -- redis-cli GRAPH.LIST

# Count entities in a graph
kubectl exec -n hyperplane-falkordb <pod> -- redis-cli GRAPH.QUERY <graph-name> "MATCH (n:Entity) RETURN count(n)"

# List recent entities
kubectl exec -n hyperplane-falkordb <pod> -- redis-cli GRAPH.QUERY <graph-name> "MATCH (n:Entity) RETURN n.name LIMIT 10"
```

### FalkorDB Pod Name

```bash
kubectl get pods -n hyperplane-falkordb -l app.kubernetes.io/name=falkordb -o name
```

## Integration with AGENTS.md

This skill complements the mandatory memory protocols in AGENTS.md:

1. **Before problem-solving**: Search BOTH Graphiti AND files
2. **After verified solution**: Record to BOTH Graphiti AND files
3. **Cite sources**: "Found in Graphiti: [entity name]" or "Found in bugs.md: [entry]"

## Quick Reference

```python
# ALWAYS use 2+ group_ids for searches
SEARCH_GROUP_IDS = ["shakudo-platform-knowledge", "dummy"]

# Search for knowledge
search_nodes(query="your query", group_ids=SEARCH_GROUP_IDS, max_nodes=5)

# Record new knowledge (single group_id OK for writes)
add_memory(
    name="Type: Brief title",
    group_id="shakudo-platform-knowledge",
    episode_body="Date. Context. Details. Solution. Verified: evidence.",
    source_description="source"
)
```

