← Back to Plugins
Tools

Plugin Graph

CoderofTheWest By CoderofTheWest 👁 108 views ▲ 0 votes

Knowledge graph plugin for OpenClaw โ€” entity extraction, triple storage, and graph-based retrieval

GitHub

Install

npm install
```

Configuration Example

{
  "plugins": {
    "load": {
      "paths": [
        "/path/to/openclaw-plugin-graph"
      ]
    },
    "entries": {
      "openclaw-plugin-graph": {
        "enabled": true,
        "config": {}
      }
    }
  }
}

README

# openclaw-plugin-graph

**Memory Graph** โ€” a knowledge graph that learns the relationships in your conversations.

Extracts entities and relationships from every conversation, stores them as triples in a graph database, and uses that graph to surface contextually relevant connections the agent wouldn't otherwise recall. When a user mentions "Chris," the agent doesn't just search for exchanges containing that name โ€” it traverses the graph to find what Chris created, who Chris knows, and what those people work on.

## What it does

- **Entity extraction**: Pulls people, places, organizations, dates, URLs, and concepts from conversation text using compromise.js NLP + regex patterns. Builds a gazetteer of known entities that improves extraction over time.
- **Relationship triples**: Stores `subject โ†’ predicate โ†’ object` triples with confidence scores, exchange provenance, and mention counts. 12 canonical predicates: `knows`, `created`, `uses`, `works_on`, `interested_in`, `located_in`, `part_of`, `prefers`, `related_to`, `has_property`, `occurred_at`, `causes`.
- **Multi-hop traversal**: Recursive CTE walks the graph up to N hops (default 2), finding indirect connections with score decay per hop. "Chris knows Dan, Dan created the analytics dashboard" surfaces in a query about Chris even though Chris never mentioned that dashboard.
- **Meta-path patterns**: Predicate-sequence patterns like `[knows, works_on]` or `[created, part_of]` find structurally meaningful paths. Ships with 5 static defaults; more are discovered automatically.
- **Pattern discovery**: During nightshift, the plugin evaluates candidate predicate sequences against the actual graph data. Filters by fanout cap, structural viability (minimum yield), and novelty (overlap with single-hop results). Only patterns that surface genuinely new connections survive.
- **Graph-aware context injection**: Before each conversation, injects a `[GRAPH CONTEXT]` block with natural-language relationship summaries โ€” "Chris created the analytics dashboard, uses React, and knows Dan" โ€” so the agent has relational awareness without being told.
- **LLM enrichment**: Queues exchanges for deeper extraction via LLM during nightshift. Produces cleaner, more nuanced triples than the fast-path NLP extractor.
- **Conversational entity resolution**: When the graph encounters ambiguous entities ("is this the same Bob?"), it uses a 3-tier approach โ€” high confidence matches are assumed, low confidence ones prompt the agent to ask the user naturally, medium confidence ones are deferred for later resolution.
- **Archive backfill**: On first run, scans existing continuity archives and builds the graph retroactively. No conversations are lost just because the plugin was installed later.
- **RRF fusion with continuity**: Graph search results feed into continuity's Reciprocal Rank Fusion as a third ranked list alongside semantic and keyword search. Exchanges connected by graph relationships get boosted in recall.

## How it works

### Data flow

```
User message arrives
        โ”‚
        โ–ผ
before_agent_start (priority 8)
        โ”‚
        โ”œโ”€โ”€ Extract entities from user message
        โ”‚     โ””โ”€โ”€ compromise.js NER + gazetteer matching
        โ”‚
        โ”œโ”€โ”€ Graph search (multi-hop + meta-path)
        โ”‚     โ”œโ”€โ”€ Recursive CTE traversal (bidirectional, N hops)
        โ”‚     โ”œโ”€โ”€ Meta-path pattern matching (static + discovered)
        โ”‚     โ””โ”€โ”€ Merge: max(hopScore, metaScore) per exchange
        โ”‚
        โ”œโ”€โ”€ Build [GRAPH CONTEXT] block
        โ”‚     โ””โ”€โ”€ Predicate-to-language templates โ†’ compound sentences
        โ”‚
        โ”œโ”€โ”€ Build [GRAPH NOTE] (entity resolution hints)
        โ”‚
        โ””โ”€โ”€ Publish results to global bus โ†’ continuity RRF
              โ””โ”€โ”€ global.__ocGraph.lastResults[agentId]

Model processes message + generates response

agent_end
        โ”‚
        โ”œโ”€โ”€ Fast-path extraction (compromise.js)
        โ”‚     โ”œโ”€โ”€ Entity extraction + triple generation
        โ”‚     โ””โ”€โ”€ Co-occurrence detection
        โ”‚
        โ”œโ”€โ”€ Queue for LLM enrichment (if enabled)
        โ”‚     โ””โ”€โ”€ Nightshift picks up queue โ†’ deeper extraction
        โ”‚
        โ””โ”€โ”€ Entity resolution (3-tier)
              โ”œโ”€โ”€ Assume (confidence > 0.8)
              โ”œโ”€โ”€ Ask (confidence < 0.4) โ†’ [GRAPH NOTE] next turn
              โ””โ”€โ”€ Defer (0.4โ€“0.8) โ†’ pending_resolution

nightshift (graph-enrichment task, priority 35)
        โ”‚
        โ”œโ”€โ”€ LLM extraction on queued exchanges
        โ”œโ”€โ”€ Entity resolution on pending merges
        โ”œโ”€โ”€ Pattern discovery (every 24h)
        โ”‚     โ””โ”€โ”€ Candidate generation โ†’ fanout filter โ†’ viability โ†’ novelty
        โ””โ”€โ”€ Gap detection (under-connected entities)
```

### Storage

| Component | Location | Format |
|-----------|----------|--------|
| Graph database | `data/agents/{agentId}/graph.db` | SQLite (entities, triples, co-occurrences, meta-patterns) |
| Entity gazetteer | In-memory, built from DB | Maps normalized names โ†’ entity records |

Each agent gets its own isolated graph database. The plugin supports multiple agents on the same gateway without data mixing.

## Installation

### Prerequisites

- OpenClaw installed and running (gateway active)
- Node.js >= 18

### Install dependencies

```bash
cd /path/to/openclaw-plugin-graph
npm install
```

This installs:
- `better-sqlite3` โ€” synchronous SQLite driver
- `compromise` โ€” NLP library for entity extraction

### Configure OpenClaw

Add the plugin to your `~/.openclaw/openclaw.json`:

```json
{
  "plugins": {
    "load": {
      "paths": [
        "/path/to/openclaw-plugin-graph"
      ]
    },
    "entries": {
      "openclaw-plugin-graph": {
        "enabled": true,
        "config": {}
      }
    }
  }
}
```

### Restart the gateway

```bash
openclaw gateway restart
```

Verify the plugin loaded:

```bash
openclaw logs | grep "Graph plugin"
```

You should see:
```
Graph plugin registered โ€” Phases 1-5: extraction + multi-hop traversal + meta-paths + context injection active
```

## Architecture

### Modules

```
index.js                     Main plugin โ€” hook registration, orchestration
โ”œโ”€โ”€ lib/
โ”‚   โ”œโ”€โ”€ extractor.js         compromise.js NER + regex + heuristic relationships
โ”‚   โ”œโ”€โ”€ graph-store.js       SQLite schema, prepared statements, CRUD
โ”‚   โ”œโ”€โ”€ graph-searcher.js    Single-hop, multi-hop CTE, meta-path queries
โ”‚   โ”œโ”€โ”€ context-builder.js   [GRAPH CONTEXT] natural-language generation
โ”‚   โ”œโ”€โ”€ pattern-discovery.js Nightshift pattern candidate evaluation
โ”‚   โ”œโ”€โ”€ entity-resolver.js   3-tier conversational resolution + merge
โ”‚   โ”œโ”€โ”€ llm-extractor.js     Ollama LLM extraction for deeper triples
โ”‚   โ””โ”€โ”€ backfill.js          Retroactive extraction from continuity archives
โ””โ”€โ”€ config.default.json      Default configuration
```

### Hooks registered

| Hook | Priority | Purpose |
|------|----------|---------|
| `before_agent_start` | 8 | Entity extraction, graph search, context injection, RRF publishing |
| `agent_end` | โ€” | Fast-path extraction, enrichment queuing, entity resolution |
| `session_end` | โ€” | Log session graph stats |

### Gateway methods

| Method | Purpose |
|--------|---------|
| `graph.getState` | Entity count, triple count, active patterns, last backfill |
| `graph.search` | Execute graph search (params: text, limit) |
| `graph.getEntity` | Look up a specific entity by name |
| `graph.getTriples` | Get triples for a subject or object |
| `graph.listAgents` | List all agents with graph data |
| `graph.detectGaps` | Find under-connected or stale entities |
| `graph.resolveEntity` | Manually resolve a pending entity |
| `graph.mergeEntities` | Merge two entities into one |
| `graph.backfillStatus` | Check archive backfill progress |
| `graph.rebuild` | Rebuild graph from scratch (destructive) |
| `graph.getPatterns` | List all active meta-path patterns (static + discovered) |
| `graph.discoverPatterns` | Trigger pattern discovery manually |

### Integration with other plugins

The graph plugin communicates with sibling plugins via the global bus pattern โ€” no npm dependencies, just runtime wiring through `global` objects:

- **โ†’ continuity**: Publishes search results to `global.__ocGraph.lastResults[agentId]`. Continuity's searcher picks these up for 3-way RRF fusion (semantic + keyword + graph).
- **โ†’ nightshift**: Registers a `graph-enrichment` task runner and queues enrichment tasks for off-hours processing.
- **โ†’ metabolism**: Subscribes to `global.__ocMetabolism.gapListeners` to receive knowledge gaps for enrichment, and fires discovered gaps back to metabolism listeners.

All integrations degrade gracefully โ€” if a sibling plugin isn't loaded, the graph plugin continues without it.

## Configuration

All configuration is optional. The plugin ships with sensible defaults in `config.default.json`.

```json
{
  "extraction": {
    "minExchangeLength": 20,
    "skipHeartbeats": true,
    "maxEntitiesPerExchange": 15,
    "confidenceThreshold": 0.5,
    "canonicalPredicates": [
      "knows", "created", "uses", "located_in", "part_of",
      "interested_in", "prefers", "works_on", "related_to",
      "has_property", "occurred_at", "causes"
    ]
  },

  "retrieval": {
    "maxHops": 2,
    "maxResults": 20,
    "hopDecay": 0.7,
    "minTraversalConfidence": 0.6,
    "metaPathWeight": 0.8
  },

  "metaPaths": {
    "static": [
      { "predicates": ["interested_in", "interested_in"], "weight": 0.8 },
      { "predicates": ["created", "part_of"], "weight": 0.9 },
      { "predicates": ["knows", "works_on"], "weight": 0.85 },
      { "predicates": ["uses", "created"], "weight": 0.7 },
      { "predicates": ["works_on", "part_of"], "weight": 0.75 }
    ]
  },

  "patternDiscovery": {
    "enabled": true,
    "maxActivePatterns": 12,
    "minYield": 3,
    "maxOverlapRatio": 0.9,
    "maxFanoutPerStep": 50

... (truncated)
tools

Comments

Sign in to leave a comment

Loading comments...