Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

,_,
(O,O)
( )
" "

/-/-/-/-/-/-/-\
\-\-\-\-\-\-\-/
/-/-/-/-/-/-/-\

WEAV

weav

An in-memory graph + vector database for AI retrieval.

Quickstart · Examples · Architecture · Query Language · Auth · API Reference · MCP · SDKs · Benchmarks

LicenseRustProtocolsWorkspace


What is Weav?

Weav is an in-memory graph + vector database for AI systems that need more than chunk similarity. It stores entities, relationships, embeddings, provenance, and temporal validity in one process, then returns token-budgeted context over HTTP, RESP3, gRPC, or MCP.

Instead of stitching together a vector store, a graph database, and retrieval glue, Weav gives you one query engine for structure-aware context retrieval.

Why Weav

  • More than vector search: start from embeddings, then traverse relationships and score context through the graph
  • Grounded retrieval: provenance, confidence, and bi-temporal validity stay attached to the data
  • Built for LLM windows: token-budget-aware packing returns context that fits the model budget
  • Fast local deployment: single-process, in-memory architecture with optional WAL and snapshots
  • Multiple ways in: HTTP, RESP3, gRPC, CLI, and MCP all target the same engine

Good Fit

  • Agent memory and conversation state
  • Knowledge graphs with embeddings
  • Timeline-aware or provenance-sensitive retrieval
  • Low-latency, single-node AI infrastructure

Core Capabilities

AreaWhat you get
RetrievalHNSW vector search, graph traversal, flow scoring, BM25 text search, rerank hooks
Context assemblyToken budgets, provenance-aware chunks, temporal filters, optional subgraph output, LLM-ready formatting
OperationsWAL + snapshots, CDC event streams, schema constraints, export/import, graph algorithms
InterfacesHTTP REST, RESP3, gRPC, CLI, MCP, plus Python and Node SDKs

Quickstart

Build & Run

Rust 1.85+ is required.

# Clone
git clone https://github.com/SiluPanda/weav.git
cd weav
# Build the server and CLI used below
cargo build --release -p weav-server -p weav-cli
# Start the server
./target/release/weav-server
# Default ports:# RESP3 → :6380# gRPC → :6381# HTTP → :6382

If you only want the server binary, cargo build --release is enough. The workspace default member is weav-server, so weav-cli must be built explicitly.

Feature-Gated Builds

Common build targets:

# Default server build
cargo build --release
# Server + CLI (used in the quickstart above)
cargo build --release -p weav-server -p weav-cli
# Full build — including optional LLM providers
cargo build --release -p weav-server --features full
# Minimal — HTTP-only server
cargo build --release -p weav-server --no-default-features

Run with Docker Compose

If you want a prewired local deployment with persistence enabled:

docker compose up --build

This exposes 6380 (RESP3), 6381 (gRPC), and 6382 (HTTP), and persists WAL/snapshots in the weav-data Docker volume.

Smoke Test over HTTP

# Health check
curl -s http://localhost:6382/health
# Create a graph
curl -sX POST http://localhost:6382/v1/graphs \
-H 'content-type: application/json' \
-d '{"name":"knowledge"}'# Add a node
curl -sX POST http://localhost:6382/v1/graphs/knowledge/nodes \
-H 'content-type: application/json' \
-d '{"label":"concept","properties":{"name":"Transformers","content":"Self-attention architecture for sequence modeling"}}'# Retrieve context
curl -sX POST http://localhost:6382/v1/context \
-H 'content-type: application/json' \
-d '{"graph":"knowledge","query":"self attention","budget":1024}'

HTTP responses use the standard envelope { "success": bool, "data"?: ..., "error"?: ... }.

Connect with the CLI

# Interactive REPL
./target/release/weav-cli
# Single command
./target/release/weav-cli -c 'PING'# Connect with authentication
./target/release/weav-cli -u admin -a supersecret

Your First Context Graph

weav> GRAPH CREATE "knowledge"
OK
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "Transformers", "content": "Self-attention mechanism for sequence modeling"} EMBEDDING [0.1, 0.2, 0.3]
(integer) 0
weav> NODE ADD TO "knowledge" LABEL "concept" PROPERTIES {"name": "BERT", "content": "Bidirectional encoder from transformers"} EMBEDDING [0.12, 0.22, 0.28]
(integer) 1
weav> EDGE ADD TO "knowledge" FROM 1 TO 0 LABEL "derived_from" WEIGHT 0.95
(integer) 0
weav> CONTEXT "attention mechanisms" FROM "knowledge" BUDGET 4096 TOKENS

SDK Setup

python -m pip install -e ./sdk/python
cd sdk/node && npm install

See SDKs for full Python and TypeScript examples.


Examples

PathWhat it shows
examples/quickstart.pyEnd-to-end HTTP quickstart: graph creation, nodes, edges, search, algorithms, and health checks
examples/context_query.pyBudget-aware retrieval, subgraph output, explain mode, and LLM-oriented formatting
examples/quickstart.tsMinimal Node/TypeScript workflow against the HTTP API
docker-compose.ymlLocal deployment with persistence enabled
ARCHITECTURE.mdDeeper crate-by-crate architecture walkthrough

If you want a runnable example before reading the full API surface, start with examples/quickstart.py.


Architecture

For a crate-by-crate deep dive beyond this overview, see ARCHITECTURE.md.

 ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ HTTP REST │ │ RESP3 TCP │ │ gRPC │
│ :6382 │ │ :6380 │ │ :6381 │
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
│ │ │
└───────────────┼────────────────┘
│
┌──────────────────────────────────────────────┐
│ AUTH LAYER (opt-in) │
│ Bearer/Basic │ AUTH cmd │ gRPC metadata │
│ → ACL Store → Category + Graph ACL check → │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ ENGINE │
│ ┌────────────────────────────────────────┐ │
│ │ Query Pipeline │ │
│ │ Parse → Plan → Execute → Budget → Out│ │
│ └────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌─────────────┐ │
│ │ Graph 0 │ │ Graph 1 │ │ Graph N │ │
│ │┌────────┐│ │┌────────┐│ │┌───────────┐│ │
│ ││Adjacen.││ ││Adjacen.││ ││ Adjacency ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││Propert.││ ││Propert.││ ││Properties ││ │
│ │├────────┤│ │├────────┤│ │├───────────┤│ │
│ ││ Vector ││ ││ Vector ││ ││ Vector ││ │
│ ││ (HNSW) ││ ││ (HNSW) ││ ││ (HNSW) ││ │
│ │└────────┘│ │└────────┘│ │└───────────┘│ │
│ └──────────┘ └──────────┘ └─────────────┘ │
└──────────────────────┬───────────────────────┘
│
┌──────────────────────────────────────────────┐
│ PERSISTENCE │
│ ┌──────────────┐ ┌────────────────────┐ │
│ │ WAL │ │ Snapshots │ │
│ │ (CRC32) │ │ (bincode) │ │
│ └──────────────┘ └────────────────────┘ │
└──────────────────────────────────────────────┘

Crate Map

CratePurpose
weav-coreFoundation types, config, errors, shard infrastructure, message bus
weav-graphAdjacency store, property store, traversal (BFS, flow scoring, Dijkstra, PPR), entity dedup
weav-vectorHNSW vector index (usearch), token counting (tiktoken-rs)
weav-extractIngestion pipeline: document parsing (PDF/DOCX/CSV/text), chunking, LLM extraction (opt-in)
weav-queryQuery parser (38 commands), planner, executor, token budget enforcement
weav-authAuthentication (Argon2id), API keys (SHA-256), ACL store, command classification
weav-persistWrite-ahead log, snapshot engine, crash recovery
weav-protoRESP3 codec, gRPC protobuf definitions, command mapping
weav-mcpModel Context Protocol server exposing graph/context tools over stdio
weav-serverEngine coordinator, HTTP/RESP3/gRPC servers (axum, tonic)
weav-cliInteractive REPL client with history (rustyline)
benchmarksCriterion benchmarks at 100K scale

Design Decisions

  • Compact String Interning — Labels and property keys stored as u16 IDs, not heap strings
  • Column-Oriented Properties — Sparse property sets without wasting memory on nulls
  • SmallVec<8> Adjacency — Most nodes have few edges; avoid heap allocation for the common case
  • Roaring Bitmaps — Efficient set operations for node filtering and membership tests
  • Greedy Knapsack Budget — Packs the highest value-density chunks (relevance / tokens) first
  • Zero-Copy Ready — rkyv support for future hot-path serialization

Query Language

Weav uses a Redis-style command language optimized for context retrieval.

Graph Management

GRAPH CREATE "<name>"
GRAPH DROP "<name>"
GRAPH LIST
GRAPH INFO "<name>"

Node Operations

NODE ADD TO "<graph>" LABEL "<label>" PROPERTIES {json} [EMBEDDING [f32, ...]] [ENTITY_KEY "<key>"] [TTL <ms>]
NODE GET "<graph>" <id>
NODE GET "<graph>" WHERE entity_key = "<key>"
NODE UPDATE "<graph>" <id> [PROPERTIES {json}] [EMBEDDING [f32, ...]]
NODE DELETE "<graph>" <id>
NODE MERGE "<graph>" <source_id> INTO <target_id> [POLICY keep_target|keep_source|merge]

Edge Operations

EDGE ADD TO "<graph>" FROM <source> TO <target> LABEL "<label>" [WEIGHT <f32>] [PROPERTIES {json}] [TTL <ms>]
EDGE GET "<graph>" <id>
EDGE DELETE "<graph>" <id>
EDGE INVALIDATE "<graph>" <id>

Bulk Operations

BULK NODES TO "<graph>" DATA [{node}, {node}, ...]
BULK EDGES TO "<graph>" DATA [{edge}, {edge}, ...]

Context Query

The star of the show — retrieve structured, budget-aware context for your LLM:

CONTEXT "<query>" FROM "<graph>" [BUDGET <n> TOKENS]
[SEEDS VECTOR [f32, ...] TOP <k>]
[SEEDS NODES ["entity_key", ...]]
[DEPTH <u8>]
[RETRIEVAL LOCAL|GLOBAL|HYBRID|DRIFT]
[RERANK {json}]
[DIRECTION IN|OUT|BOTH]
[FILTER LABELS ["label", ...] MIN_WEIGHT <f> MIN_CONFIDENCE <f>]
[DECAY EXPONENTIAL <ms> | LINEAR <ms> | STEP <ms> | NONE]
[PROVENANCE]
[AT <timestamp>]
[LIMIT <u32>]
[SCORE BY relevance|recency|confidence ASC|DESC]

Vector and node seeds can be combined by repeating SEEDS in the same command.

How the context pipeline works:

 Query Text ──→ Vector Search ──→ Seed Nodes
│
Explicit Seeds ─────────────────────┤
▼
Graph Traversal
(BFS to max_depth)
│
▼
Flow Scoring
(relevance propagation)
│
▼
Temporal Filtering
(bi-temporal validity)
│
▼
Conflict Detection
(label-group dedup)
│
▼
Token Budget Enforcement
(greedy knapsack)
│
▼
Sorted ContextChunks[]

Server Commands

PING
INFO
STATS ["<graph>"]
SNAPSHOT

Authentication & ACL Commands

AUTH <password> # Redis-compat single-password auth
AUTH <username> <password> # Username + password auth
ACL SETUSER <user> [>password] [on|off] [+@cat|-@cat] [~pattern:perm]
ACL DELUSER <username>
ACL LIST
ACL GETUSER <username>
ACL WHOAMI
ACL SAVE # Persist ACL to file
ACL LOAD # Reload ACL from file

Command categories:+@connection, +@read, +@write, +@admin, +@all

Graph patterns:~*:readwrite, ~app:*:read, ~shared:admin


Authentication & Authorization

Weav includes a Redis-ACL-inspired auth system that works across all three protocols. Auth is disabled by default — zero config change needed for existing deployments.

How It Works

LayerMechanism
HTTPAuthorization: Bearer <api_key> or Authorization: Basic <base64> header
RESP3AUTH [username] password command (per-connection identity)
gRPCauthorization metadata key

Permission Model

Command categories control what types of operations a user can perform:

CategoryCommands
connectionPING, INFO, AUTH
readNODE.GET, EDGE.GET, GRAPH.INFO, GRAPH.LIST, STATS, CONTEXT, CONFIG.GET, ACL WHOAMI
writeNODE.ADD, NODE.UPDATE, NODE.DELETE, EDGE.ADD, EDGE.DELETE, EDGE.INVALIDATE, BULK.INSERT.*
adminGRAPH.CREATE, GRAPH.DROP, SNAPSHOT, CONFIG.SET, ACL SETUSER/DELUSER/LIST/GETUSER/SAVE/LOAD

Graph-level ACL controls which graphs a user can access, using glob patterns:

[[auth.users]]
username = "app_writer"password = "writepass"categories = ["+@read", "+@write"]
graph_patterns = [
{ pattern = "app:*", permission = "readwrite" },
{ pattern = "shared", permission = "read" },
]

API Keys

Users can be assigned API keys (prefixed wk_) for Bearer token auth. The server stores only SHA-256 hashes — raw keys are never persisted.

[[auth.users]]
username = "service_account"categories = ["+@read"]
api_keys = ["wk_live_abc123def456"]

Backward Compatibility

  • Auth is OFF by default — pass no config and everything works as before
  • require_auth = false (the default when auth is enabled) allows mixed authenticated/unauthenticated connections during migration
  • All SDK auth parameters are optional — existing client code is unchanged

API Reference

HTTP REST API

Base URL: http://localhost:6382

All responses follow { "success": bool, "data"?: T, "error"?: string }. The Response column below shows the data payload.

Graphs

MethodEndpointBodyResponse
POST/v1/graphs{ "name": "..." } or { "scope": { ... } }empty
GET/v1/graphs["graph_a", "graph_b"]
GET/v1/graphs/{name}{ "name", "node_count", "edge_count", "vector_count", "label_count", "default_ttl_ms"? }
DELETE/v1/graphs/{name}empty

Nodes

MethodEndpointBodyResponse
POST/v1/graphs/{g}/nodes{ "label", "properties?", "embedding?", "entity_key?", "ttl_ms?" }{ "node_id": u64 }
GET/v1/graphs/{g}/nodes/{id}{ "node_id", "label", "properties" }
PUT/v1/graphs/{g}/nodes/{id}{ "properties?", "embedding?" }empty
DELETE/v1/graphs/{g}/nodes/{id}empty
POST/v1/graphs/{g}/nodes/merge{ "source_id", "target_id", "conflict_policy?" }{ "node_id": u64 }
POST/v1/graphs/{g}/nodes/bulk{ "nodes": [...] }{ "node_ids": [u64] }

Edges

MethodEndpointBodyResponse
POST/v1/graphs/{g}/edges{ "source", "target", "label", "weight?", "properties?", "ttl_ms?" }{ "edge_id": u64 }
GET/v1/graphs/{g}/edges/{id}{ "edge_id", "source", "target", "label", "weight", "properties" }
DELETE/v1/graphs/{g}/edges/{id}empty
POST/v1/graphs/{g}/edges/{id}/invalidateempty
POST/v1/graphs/{g}/edges/bulk{ "edges": [...] }{ "edge_ids": [u64] }

Context

MethodEndpointBody
POST/v1/context{ "graph"?, "scope"?, "query"?, "retrieval_mode"?, "rerank"?, "embedding"?, "seed_nodes"?, "budget"?, "budget_preset"?, "max_depth"?, "include_provenance"?, "decay"?, "temporal_at"?, "limit"?, "sort_field"?, "sort_direction"?, "edge_labels"?, "direction"?, "explain"?, "output_format"?, "include_subgraph"? }

Returns ContextResult with chunks, token counts, and query timing.

graph and scope are mutually optional, with graph taking precedence when both are supplied. scope resolves to canonical graph names such as ws:acme:user:u_123. budget_preset accepts small/4k, medium/8k, large/16k, xl/32k, and xxl/128k. Set explain: true to return the query plan without executing it.

Decay parameter (object, not string):

{
"decay": {
"type": "exponential",
"half_life_ms": 3600000,
"max_age_ms": null,
"cutoff_ms": null
}
}

Supported types: exponential, linear, step, none.

Rerank parameter:

{
"rerank": {
"enabled": true,
"provider": "cross_encoder",
"model": "bge-reranker-v2-m3",
"candidate_limit": 50,
"score_weight": 0.35
}
}

Events

MethodEndpointQueryDescription
GET/v1/eventssince_sequence?, replay_limit?Replay recent events across all visible graphs, then continue as SSE
GET/v1/graphs/{g}/eventssince_sequence?, replay_limit?Replay recent events for one graph, then continue as SSE

Each SSE data: payload is JSON shaped like:

{
"sequence": 42,
"graph": "knowledge",
"timestamp_ms": 1712345678901,
"kind": "node_created",
"payload_json": "{\"node_id\":1,\"label\":\"person\"}"
}

Server

MethodEndpointDescription
GET/healthHealth check
GET/v1/infoServer info
POST/v1/snapshotTrigger snapshot
GET/metricsPrometheus metrics (when built with observability, enabled by default)

RESP3 Protocol

Connect on port 6380 with any Redis client or weav-cli. Commands are sent as RESP3 arrays.

gRPC

Connect on port 6381. Proto definitions live in weav-proto/proto/weav.proto and include unary graph operations plus streaming ContextQueryStream and SubscribeEvents RPCs.


MCP

weav-mcp exposes Weav operations as Model Context Protocol tools for agent runtimes that prefer stdio transport over direct HTTP/gRPC integration.

cargo run --release -p weav-mcp

The MCP server starts an in-memory Weav engine with persistence disabled by default. It is a good fit when you want an MCP client to create graphs, mutate nodes and edges, run context queries, or poll recent graph events without writing a separate adapter layer.


SDKs

Python

Install from this repository:

python -m pip install -e ./sdk/python
fromweavimportWeavClient, AsyncWeavClient# Sync clientclient=WeavClient(host="localhost", port=6382)
# Async clientclient=AsyncWeavClient(host="localhost", port=6382)
# With authenticationclient=WeavClient(host="localhost", port=6382, api_key="wk_live_abc123")
client=WeavClient(host="localhost", port=6382, username="admin", password="secret")
# LLM integrationsfromweavimportWeavLangChain, WeavLlamaIndex

Context result helpers:

result=client.context("my_graph", query="...", budget=4096)
result.to_prompt() # Formatted string for system prompt injectionresult.to_messages() # OpenAI-compatible message list

Full parameter support:

result=client.context({"workspace_id": "acme", "user_id": "u_123"},
query="transformer architectures",
retrieval_mode="hybrid",
rerank={"provider": "cross_encoder", "candidate_limit": 25, "score_weight": 0.35},
budget=4096,
decay={"type": "exponential", "half_life_ms": 3600000},
edge_labels=["derived_from", "related_to"],
temporal_at=1700000000000,
direction="outgoing",
limit=50,
sort_field="relevance",
sort_direction="desc",
include_provenance=True,
seed_nodes=["node_key_1"],
embedding=[0.1, 0.2, 0.3],
)

Node.js / TypeScript

After adding @weav/client to your app:

import{WeavClient,contextToPrompt,contextToMessages}from"@weav/client";constclient=newWeavClient({host: "localhost",port: 6382});// With authentication:// new WeavClient({ host: "localhost", port: 6382, apiKey: "wk_live_abc123" });// new WeavClient({ host: "localhost", port: 6382, username: "admin", password: "secret" });constresult=awaitclient.context({scope: {workspaceId: "acme",userId: "u_123"},query: "...",retrievalMode: "hybrid",rerank: {provider: "cross_encoder",candidateLimit: 25,scoreWeight: 0.35},budget: 4096,decay: {type: "exponential",halfLifeMs: 3600000},edgeLabels: ["related_to","derived_from"],temporalAt: Date.now(),direction: "outgoing",limit: 50,sortField: "relevance",sortDirection: "desc",});contextToPrompt(result);// Formatted prompt stringcontextToMessages(result);// OpenAI-compatible messages

Request parameters use camelCase (seedNodes, retrievalMode, includeProvenance), but some response objects preserve server field names such as node_id, node_count, and edge_count.


Configuration

Weav is configured via TOML file or environment variables.

# weav.toml
[server]
bind_address = "0.0.0.0"port = 6380# RESP3grpc_port = 6381# gRPChttp_port = 6382# HTTP RESTmax_connections = 10000tcp_keepalive_secs = 300read_timeout_ms = 30000
[engine]
num_shards = 8# Defaults to CPU countdefault_vector_dimensions = 1536max_vector_dimensions = 4096default_hnsw_m = 16default_hnsw_ef_construction = 200default_hnsw_ef_search = 50default_conflict_policy = "LastWriteWins"enable_temporal = trueenable_provenance = truetoken_counter = "CharDiv4"# or "TiktokenCl100k", "TiktokenO200k"
[persistence]
enabled = falsedata_dir = "./weav-data"wal_enabled = truewal_sync_mode = "EverySecond"# or "Always", "Never"snapshot_interval_secs = 3600max_wal_size_mb = 256
[memory]
max_memory_mb = 0# 0 = unlimitedeviction_policy = "NoEviction"arena_size_mb = 64
[auth]
enabled = false# Set true to enable authrequire_auth = false# Set true to reject unauthenticated connections# default_password = "secret" # Redis-compat: AUTH <password> only# acl_file = "./weav-data/acl.conf"# [[auth.users]]# username = "admin"# password = "supersecret"# categories = ["+@all"]## [[auth.users]]# username = "reader"# password = "readonly123"# categories = ["+@read", "+@connection"]# graph_patterns = [{ pattern = "*", permission = "read" }]# api_keys = ["wk_live_abc123def456"]

Environment Variable Overrides

VariableDescription
WEAV_SERVER_PORTRESP3 listen port
WEAV_SERVER_HTTP_PORTHTTP REST listen port
WEAV_SERVER_GRPC_PORTgRPC listen port
WEAV_SERVER_BIND_ADDRESSBind address
WEAV_ENGINE_NUM_SHARDSNumber of shards
WEAV_PERSISTENCE_ENABLEDEnable persistence (true/false)
WEAV_PERSISTENCE_DATA_DIRPersistence directory path
WEAV_MEMORY_MAX_MEMORY_MBMemory limit in MB
WEAV_AUTH_ENABLEDEnable authentication (true/false)
WEAV_AUTH_REQUIRE_AUTHRequire auth for all connections (true/false)
WEAV_AUTH_DEFAULT_PASSWORDDefault password for Redis-compat AUTH <password>

Data Model

TypeImportant FieldsNotes
Nodenode_id, label, properties, embedding?, entity_key?, temporalCore entity record; labels and property keys are interned
Edgeedge_id, source, target, label, weight, properties, provenance?, temporalDirected relationship between nodes
BiTemporalvalid_from, valid_until, tx_from, tx_untilTracks real-world validity and transaction time
Provenancesource, confidence, extraction_method, source_document_id?Keeps retrieval grounded in source metadata
ValueNull, Bool, Int, Float, String, Bytes, Timestamp, Vector, List, MapDynamic property type system

Context queries return ContextChunk values with node_id, content, label, relevance_score, depth, token_count, relationships, and optional provenance and temporal metadata.


Benchmarks

Run with:

cargo bench
BenchmarkScaleDescription
vector_search_100k_128d_k10100K vectors, 128 dimsTop-10 nearest neighbor search
bfs_100kn_depth3100K nodes, avg degree 5BFS traversal to depth 3
flow_score_100kn_depth3100K nodes, avg degree 5Relevance flow scoring
node_adjacency_10k10K insertionsAdjacency insert throughput
duplicate_suppression/*500 canonical entitiesFull-scan vs blocked duplicate suppression precision
link_existing_precision_at_1200 canonical entitiesMixed exact-key + fuzzy link-to-existing precision
retrieval_lift/*Summary-search eval graphPrecision lift from global and hybrid retrieval
rerank_lift/*Seeded local graphTop-1 precision lift from cross-encoder reranking

Benchmarks produce HTML reports via criterion.


Testing

# Run all tests (default features)
cargo test --workspace
# Run all tests including LLM provider tests
cargo test --workspace --features weav-server/full,weav-extract/llm-providers
# Run tests for a specific crate
cargo test -p weav-core
cargo test -p weav-graph
cargo test -p weav-server
# Python SDK testscd sdk/python && pip install -e ".[dev]"&& pytest
# Node SDK testscd sdk/node && npm test

Weav has broad Rust unit, integration, and end-to-end coverage plus Python and Node SDK tests.


License

MIT

About

⚡ In-memory context graph database written in Rust. Purpose-built for AI/LLM workloads — combines graph storage, vector search, temporal modeling, token budgeting, and provenance tracking in a single engine. Sub-10ms context retrieval. Redis-like speed with optional disk persistence.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages