Skip to content

ops-ping/vector-rules

Repository files navigation

vector-rules

vector-rules defines an effective production role for LLMs while exposing the power of embeddings to every layer of the tech stack. Built for production operations, it replaces opaque prompt-based governance with a deterministic, GitOps-managed rule engine. Models can still summarize, generate, and explain, but an explicit, version-controlled policy layer maps unstructured text, log streams, tool traces, and complex API payloads to safe, audited actions. The result is LLMOps you can test, review, audit, and safely run at scale.

The same rule semantics run on the wire, at the edge, in stateful stream sessions, and in the browser. A team can author one Git-managed policy layer and reuse it for MCP proxying, organizational memory recall, application behavior, streaming data, and operator tooling.

vector-rules is fully open source and vendor-neutral by design. Policy lives in git-managed rules and open interfaces rather than in a proprietary hosted control plane, so teams can self-host the runtime, review or fork the stack, and move rules across models, clients, and deployment environments.

vector-rules is also local-first and embeddable from the ground up. Teams can drop the reasoning kernel, WASM package, proxy, or embedding-cache pieces into existing infrastructure instead of routing every decision through a new hosted platform.

If you are looking for an agent-governance, LLM guardrails, or policy-as-code framework, vector-rules approaches those practices as deterministic runtime infrastructure rather than prompt convention.

Embeddings, live inside the rules

The console runs the same v: vector rules in the browser (via vrules-wasm) against real EmbeddingGemma vectors served from the /vrest cache — no model in the page. A rule computes the classic analogy king − man + woman ≈ queen as vector arithmetic inside its when, and a second rule forward-chains off the fact the first one derives: meaning drives a deterministic RETE firing, which asserts a fact, which fires the next rule — the same engine, one fire_all().

The vector-rules console evaluating v: rules against real EmbeddingGemma embeddings: semantic similarity to "royalty", the king − man + woman ≈ queen analogy firing a rule, and that rule forward-chaining into a second rule that fires on the derived fact

This is not vector search bolted onto a rule engine: the embedding comparison is a first-class predicate the RETE network thresholds, and its result can gate a when or feed a then assignment that the rest of the ruleset reasons over.

Vision

That vision becomes four operating principles:

  • Deterministic production behavior. vrules-core evaluates rules through a RETE network, not an opaque reasoning loop. Forward runs return EXPLAIN-style traces; backward chaining can prove a goal and show the proof tree behind it.
  • Reusable organizational memory. Embeddings are canonicalized, content-addressed, and reused. Repeated inputs can hit locally, flow through an upstream tier, and be shared instead of recomputed on every machine.
  • One policy surface everywhere. The same GRL/JSON rule logic drives MCP tool exposure, request routing, browser what-if analysis, stateful stream sessions, and embedded application behavior through vrules-wasm.
  • GitOps governance. Rules live in git, can move through whatever review and promotion controls a customer wants, and every audited decision can be tied back to the exact rules commit that produced it.

Why vector-rules

vector-rules is for organizations that want AI-linked production behavior they can own: rules in git, explicit runtime decisions, governed memory, MCP mediation, browser what-if analysis, and audit records tied back to exact rules revisions.

What users get:

  • Meaning inside deterministic rules: v: embeds and compares meaning inside RETE evaluation, so similarity can gate when conditions or feed then assignments instead of living in a separate vector-store routing step.
  • A cheap deterministic pre-tier: c: canonicalization handles recurring and near-duplicate inputs before the embedding path is needed.
  • Least-privilege MCP mediation: vrules-proxy exposes tools through rules and connection context instead of making tool surfaces globally available.
  • Fenced native providers: Web grounding and other provider integrations run as separate varlink services over Unix sockets, keeping vendor code, credentials, and failures outside the proxy.
  • Governed organizational memory: vrules-vrest, em-log-n, and vrules-canon turn embedding reuse, recall, and audit search into managed infrastructure instead of prompt-only convention.
  • Portable policy: The same rule semantics run in the proxy, in Rust applications, in stream/session workloads, and in the browser through vrules-wasm.
  • Streaming without host lock-in: CompiledRuleset, RuleSession, StreamSession, FactBatch, and snapshots live in vrules-core, so proxy, browser/WASM, DataFusion-style batch adapters, and future Spark-style adapters can share one execution contract.
  • Local-first adoption: The core library, WASM package, proxy, and cache services can be used independently, so vector-rules fits into existing apps and infrastructure without requiring a new hosted control plane.
  • Reviewable behavior: Forward traces, backward proof, searchable audit records, and pinned rules commits make production decisions explainable after the fact.
  • Open extensions: Hosts can register Rust functions that rules call as predicates or decision writers while the rule engine stays transport-agnostic.
  • Strict authoring: Rule JSON is parsed, validated, and lowered with unknown fields rejected as hard errors instead of silently ignored configuration.

That posture is implemented across the workspace today: vrules-core provides the rules kernel, vrules-proxy is the reference MCP/WebSocket/stdio runtime, vrules-vrest plus em-log-n provide the embedding and memory substrate, vrules-wasm plus the console provide browser parity, and shared-rules gives the GitOps policy source of truth.

Operating model

vector-rules packages LLMOps, agent governance, guardrails, policy-as-code, memory discipline, streaming evaluation, and auditability as one rules-first runtime. The short version:

Practice vector-rules surface
deterministic control around non-deterministic models vrules-core rules, thresholds, traces, and proof
least-privilege tool access vrules-proxy rule-driven MCP exposure and routing
policy-as-code shared-rules git revisions loaded and stamped at runtime
evals and replay console what-if, A/B compare, forward trace, backward proof
governed memory vrules-vrest, em-log-n, and vrules-canon
streaming / batch portability RuleSession, StreamSession, FactBatch, snapshots
fenced providers varlink services over Unix sockets

Deployment shape

The main runtime can start as a local MCP command or as managed services. In both cases, agent IPC stays on Unix sockets, browser/admin surfaces stay explicit HTTP surfaces, and the embedding model is owned by the vrest daemon. Component-level READMEs document the exact lifecycle knobs.

LLMs in the loop

vector-rules is not anti-LLM. It gives LLMs a better role: let them do the fuzzy, language-heavy work they are good at while deterministic rules remain the production authority. An LLM can help turn policy intent into candidate rules, explain diffs, generate edge-case facts, read traces, summarize audit history, and propose fixes, but the deployed behavior is still explicit rule logic that can be reviewed, tested, replayed, and rolled back.

Useful places for LLMs are authoring, PR review, testing, debugging, and management: they can draft rules, propose facts, explain diffs, summarize traces, and prepare rollout notes. Compilation, schema validation, RETE firing, stream session state, proof, pinned rule revisions, and audit records remain the reviewable source of runtime truth.

Competitive posture

vector-rules sits between policy engines, semantic routers, MCP gateways, business-rules engines, GitOps tooling, streaming decision systems, and managed AI-governance platforms. The difference is the integrated rules-first stack: semantic predicates, canonicalization, stateful RETE sessions, browser/WASM parity, MCP mediation, organizational memory, and audit in one open framework. See docs/COMPETITIVE-LANDSCAPE.md for the detailed comparison and docs/ROADMAP.md for roadmap items.

Platform pieces

  • vrules-core is the reasoning kernel. It extends rust-rule-engine with v: vector expressions, c: canon expressions, CompiledRuleset, RuleSession, StreamSession, FactBatch, snapshots, forward traces, and backward proof.
  • vrules-proxy is the production runtime: a WebSocket/stdio MCP proxy that applies rules to routing, tool exposure, native varlink provider calls, third-party MCP mediation, and audited execution. It serves /mcp, /rpc, and the same-origin /vrest mount.
  • vrules-mcp-shim is a thin per-session stdio<->Unix-socket bridge so standard MCP clients can reach the proxy daemon without owning state.
  • vrules-gcp is the native GCP web-grounding provider. It runs as a fenced varlink service over a Unix socket, exposing ai.vrules.grounding.Ground and Summarize while hiding Vertex/Gemini details from the proxy.
  • vrules-vrest, vrules-vrest-store, and vrules-vrest-daemon provide the edge-distributed embedding cache. The daemon is the single writer and embedder owner; readers hit local data, pull through from an upstream tier, or trigger embed-once-and-write.
  • vrules-wasm + apps/console bring browser parity for the same rule engine: validation, forward evaluation, stream sessions, backward proof, and semantic what-if flows client-side with native Rust semantics.
  • shared-rules contains GitOps-managed rule sets and schemas. Routing, tool exposure, effort, and memory-recall policy can live there as reusable data rather than product-specific code.
  • vrules-canon provides deterministic canonicalization primitives that collapse recurring variants, stabilize audit keys, and maximize cache reuse before embeddings are needed.
  • em-log-n is the latency-first audit, search, and memory substrate underneath embeddings, ANN search, and organizational recall.

How it fits together

Architecture

flowchart LR
    Policy["shared-rules<br/>GitOps policy"]
    Runtime["vrules-proxy<br/>production policy runtime"]
    Kernel["vrules-core<br/>deterministic rules kernel"]
    Memory["vrules-vrest + em-log-n<br/>governed embedding memory"]
    Providers["fenced providers<br/>varlink / MCP backends"]
    Browser["vrules-wasm + console<br/>browser what-if + replay"]
    Hosts["host apps / streams / batches"]
    Clients["MCP clients / operators / apps"]

    Policy --> Runtime
    Clients --> Runtime
    Runtime --> Kernel
    Kernel --> Memory
    Runtime --> Providers
    Browser -. same rules .-> Kernel
    Hosts -. same rules .-> Kernel
    Runtime --> Browser
Loading

A typical production request enters vrules-proxy over MCP. The proxy loads a pinned shared-rules commit, asserts request facts into vrules-core, and fires deterministic rules. c: handles recurring or structured variants cheaply; v: resolves semantic classification or organizational-memory recall through vrules-vrest; routing rules can write the backend interface and method to the decision blackboard. The proxy then calls the selected fenced provider over the varlink backend bus, audits the result, and exposes only the MCP tools that the active rules allow for that connection context.

Streaming and batch workloads use the same kernel. Hosts compile a CompiledRuleset, feed records or batches through RuleSession or StreamSession, and snapshot state for replay or handoff. The browser StreamRuleEngine exposes the same path to native browser streams, while future Arrow/DataFusion/Spark adapters can lower rows or partitions into FactBatch without changing rule semantics.

GitOps and runtime loop

sequenceDiagram
    participant Author as Author / reviewer
    participant Git as shared-rules
    participant Console as Console / what-if
    participant Client as Client / app
    participant Runtime as vrules-proxy
    participant Core as vrules-core
    participant Memory as governed memory
    participant Provider as fenced provider
    participant Audit as audit trail

    Author->>Git: edit and review rules
    Console->>Git: load candidate revision
    Console->>Runtime: validate / replay / compare
    Author->>Git: promote approved revision
    Client->>Runtime: production request
    Runtime->>Git: use pinned rules revision
    Runtime->>Core: assert facts and fire rules
    Core->>Memory: canonicalize / embed / recall
    Memory-->>Core: semantic evidence
    Core-->>Runtime: decision and trace
    Runtime->>Provider: rule-selected call
    Provider-->>Runtime: grounded result
    Runtime->>Audit: record rules SHA, model token, trace
    Runtime-->>Client: governed response
Loading

The same rules can then be tested in the browser through vrules-wasm, promoted through git, and executed natively in Rust in production. When a team needs to answer why did this happen?, forward traces and backward proof provide the explanation surface.

Raw rule-evaluation performance

The current architecture benchmark measures scalar rule evaluation through the proxy/core adapter path with NullEmbedder, not embedding calls, semantic v: predicates, provider I/O, chaining-heavy rules, or host application work. It is a baseline for the raw rules path that host apps build on.

Run:

cargo run -p vrules-proxy --bin streaming-load-test --release -- \
  --events 200000 --high-percent 35

Current result on this tree:

mode events/sec elapsed accuracy
fresh per event 254k 787 ms 100%
stream session 506k 395 ms 100%

StreamSession is about 2.0x faster than rebuilding/evaluating fresh per event for this workload, while preserving the same rule semantics used by proxy, Rust hosts, and vrules-wasm.

The same StreamSession, in the browser

Because the kernel compiles to WASM, that streaming path also runs client-side with no server round-trip. The console's Streaming panel drives it: on this machine the in-browser StreamSession sustains ~230k events/s at 100% accuracy — RETE alpha-memory streaming at native-shaped throughput, in a tab, not something a JavaScript rule loop can reach.

The vector-rules console Streaming panel: the WASM StreamSession evaluating 50,000 events at 232,666 events/s with 100% accuracy, ~2x the fresh per-event path

Layout

crates/        all Rust crates (workspace members)
apps/console/  Svelte/Vite PWA; its built dist/ is embedded into the proxy via include_dir!
shared-rules/  rule JSON + schemas + vrules-rules.toml (GitOps source of truth)

Install (prebuilt binaries)

You do not need to build vector-rules to run it. Each release ships prebuilt Linux binaries for x86_64 and aarch64 (the latter runs on any 64-bit ARM Linux, including on-device via the Android AVF "Linux Terminal" Debian guest on supported Android devices) as both Debian packages and portable tarballs, plus a macOS Apple Silicon portable tarball, on the Releases page. The same release also publishes a versioned browser package archive (vrules-wasm-<version>-web.tar.{zst,gz}) built from crates/vrules-wasm/pkg.

Embeddings are core and run in a separate, prebuilt llama-server (Vulkan) engine plus the EmbeddingGemma model. Native grounding providers run as separate varlink services over Unix sockets; the first provider, grounding-service from vrules-gcp, fronts GCP Vertex/Gemini web grounding without linking vendor code into the proxy. The engine and model are build-once / reuse components, not part of the binaries — two scripts fetch them (with pinned SHA256s) so you don't compile anything:

# Debian / the AVF Debian guest — apt pulls runtime deps (libvulkan1 + iproute2):
sudo apt install ./vrules-vrest-daemon_*_arm64.deb ./vrules-proxy_*_arm64.deb ./vrules-mcp-shim_*_arm64.deb ./vrules-gcp_*_arm64.deb
/usr/share/vrules/fetch-engine.sh     # prebuilt llama-server (Vulkan) → ~/.local/share/vrules/engine/
/usr/share/vrules/fetch-model.sh      # EmbeddingGemma F32 GGUF        → ~/.local/share/vrules/models/
vrules-vrest-daemon                   # owns + supervises the engine; prints a READY line
grounding-service                     # optional fenced native GCP provider; registers a varlink socket
vrules-proxy                          # reads embeddings from the daemon over its Unix socket

Portable tarball (any distro): extract, apt install libvulkan1 iproute2, then run ./fetch-engine.sh && ./fetch-model.sh and the binaries under bin/ (vrules-proxy, vrules-mcp-shim, vrules-vrest-daemon, grounding-service).

The daemon is the single embedding owner: it spawns the prebuilt llama-server inside a private network namespace, exposes the model path to the parent only through a daemon-owned Unix socket, embeds via em-log-n's ServerEmbedder, and answers the proxy over the vrest Unix socket. Embeddings are the real EmbeddingGemma model — never stubbed. Tune the engine with VRULES_EMBED_ENGINE (binary), VRULES_EMBED_MODEL (GGUF), and VRULES_EMBED_ENGINE_SOCK (private UDS path).

Provider services register sockets under VRULES_BACKENDS_DIR (default ~/.local/share/vrules/backends). The proxy discovers them by varlink introspection at startup; routing rules choose the provider interface and method, which supports A/B routing between an existing MCP/Node Gemini backend and the native GCP provider.

Model source: the F32 GGUF is pinned by SHA256 in release/pins.env; set MODEL_URL there to wherever your copy is hosted (the public ggml-org repo ships only Q8_0).

Build from source

The workspace is pure Rust — nothing compiles llama.cpp and no Vulkan SDK is needed to build. Provider integrations are separate Rust binaries and communicate with the proxy over varlink Unix sockets rather than dynamic plugin linkage. See CONTRIBUTING.md. The console is embedded into the proxy at compile time, but its built dist/ is committed, so a plain build needs no Node:

cargo build --workspace          # pure Rust; no GPU SDK
cargo fmt --all -- --check
cargo clippy --workspace --all-targets -- -D warnings

To build or run only the native GCP provider:

cargo build -p vrules-gcp --bin grounding-service
GOOGLE_CLOUD_PROJECT=... grounding-service

Only regenerate the checked-in varlink bindings when the provider interface changes: varlink-rust-generator < crates/vrules-gcp/src/ai.vrules.grounding.varlink > crates/vrules-gcp/src/grounding_varlink.rs.

rust-rule-engine is patched in from its public fork by git URL, so a fresh clone is self-contained. The conformance suite (vrules-core) and the proxy's embedder tests connect to a running engine and fail (not skip) if it is absent — start one (or the daemon) first (release/fetch-engine.sh + release/fetch-model.sh).

Cross-build the release artifacts (.deb + .tar.zst per arch) with rootless cross — pure-Rust, native-speed, no docker required:

cargo install cross cargo-deb
CROSS_CONTAINER_ENGINE=podman ./release/build.sh   # → dist/ (both arches + SHA256SUMS)

License

Dual-licensed under MIT or Apache-2.0, at your option.

About

A deterministic, GitOps-managed rule engine that defines and enforces the production role of LLMs while exposing embeddings and organizational memories across the tech stack.

Topics

Resources

License

Apache-2.0, MIT licenses found

Licenses found

Apache-2.0
LICENSE-APACHE
MIT
LICENSE-MIT

Contributing

Stars

0 stars

Watchers

0 watching

Forks

Packages

 
 
 

Contributors

Languages