Tools
Plugin Graph
Knowledge graph plugin for OpenClaw โ entity extraction, triple storage, and graph-based retrieval
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