COOLJAPAN
← All posts

OxiRouter 0.1.0 Released — Learned SPARQL Federation, Pure Rust, on the Edge

Pure Rust autonomous semantic federation engine: learned source selection for SPARQL federated queries — context-aware, ML/RL-driven, edge & WASM-ready. 501 tests, 23k LoC, no_std-capable. No JVM. No C. No server farm.

release oxirouter sparql federation semantic-web edge-computing rust machine-learning wasm rdf

What if your SPARQL federation engine could learn which data source to ask — and run that decision on a sensor at the edge, in a WASM sandbox, with no JVM behind it?

Today we released OxiRouter 0.1.0 — a Pure Rust Autonomous Semantic Federation Engine for the Edge that performs learned source selection for SPARQL federated queries.

For two decades, federated SPARQL has been the domain of heavy JVM stacks — Apache Jena’s federation, FedX, SPARQL 1.1 SERVICE engines — bolted onto server farms. That works in a datacenter. It does not work on a gateway, a wearable, or inside a browser tab. OxiRouter is different by construction: it is Pure Rust, no_std-capable, compiles to wasm32-unknown-unknown, and ships a tiny edge binary. No JVM. No C. No server farm.

Why OxiRouter matters

Federated querying has a quiet, expensive problem: picking the right endpoint. Send a query blindly to every registered source and you pay a fan-out tax — latency, bandwidth, and wasted compute on sources that were never going to answer. Hard-code a routing table and it rots the moment endpoints change behavior. And the moment you reach for a mature federation engine, you inherit a JVM and a server to host it.

OxiRouter 0.1.0 is an alpha — feature-complete for the 0.1.x line, with an API that may still evolve — but it is already capable where it counts:

Edition 2024, MSRV 1.85, Apache-2.0.

Technical Deep Dive

OxiRouter is layered, and almost every layer is an opt-in feature flag so the edge build stays lean.

Core router + pure-Rust semantic-web parsing. src/core/ holds the Router, query, source, and state machinery. Crucially, OxiRouter ships its own pure-Rust parsing rather than pulling a heavyweight semantic-web stack. The sparql feature provides prefix expansion plus SELECT-variable projection extraction (src/core/sparql.rs, with a scanner/parser/property-path AST under src/core/sparql_ast/). The void feature adds a pure-Rust Turtle-subset parser (src/core/turtle.rs) so you can register source capabilities declaratively from a VoID/Turtle descriptor via Router::register_from_void_ttl. This was a deliberate design choice — more on that below.

The ML engine (ml). src/ml/ is a no_std-compatible inference engine (via libm): a neural network (with optional dropout), a naive Bayes classifier, an ensemble, and a federated-learning path — layer, activation, optimizer, schedule, feature, and model modules included. This is what learns the scoring function from your history.

The RL policy (rl). src/rl/ adds reinforcement-learning exploration — ε-greedy, UCB, and Q-learning strategies over a SmallRng — so when a source has little history, OxiRouter can explore intelligently instead of guessing. policy, reward, and feedback modules back the loop.

The four context “brains” (src/context/). Each is feature-gated and backed by a real COOLJAPAN dependency: geo, device, load, and legal, with sensor/provider adapters to feed live context in.

Federation execution (src/federation/). A planner, executor, and aggregator. With the http feature, the executor performs live federation over ureq — synchronous, no async runtime required, which keeps the edge story honest.

WASM bindings (src/wasm/). bindings and context_provider expose the router (and its context providers) to JavaScript via wasm-bindgen + js-sys.

State is durable too: OxiRouter persists with an OXIR wire format — a magic-prefixed binary header followed by a serde_json body — saved and loaded straight from the CLI.

Getting Started

cargo add oxirouter

Or add it to Cargo.toml:

oxirouter = "0.1"

Register a couple of sources, parse a query, and let the router rank them:

use oxirouter::core::source::SourceCapabilities;
use oxirouter::prelude::*;

fn main() -> Result<(), OxiRouterError> {
    let mut router = Router::new();

    router.add_source(
        DataSource::new("dbpedia", "https://dbpedia.org/sparql")
            .with_capabilities(SourceCapabilities::full())
            .with_vocabulary("http://dbpedia.org/ontology/")
            .with_region("EU"),
    );
    router.add_source(
        DataSource::new("wikidata", "https://query.wikidata.org/sparql")
            .with_capabilities(SourceCapabilities::full())
            .with_vocabulary("http://www.wikidata.org/")
            .with_region("EU"),
    );

    let query = Query::parse(
        r"
        PREFIX dbo: <http://dbpedia.org/ontology/>
        SELECT ?name WHERE {
            ?person a dbo:Person .
            ?person dbo:name ?name .
        }
        LIMIT 100
        ",
    )?;

    let ranking = router.route(&query)?;
    if let Some(best) = ranking.best() {
        println!("Best source: {} (confidence {:.2})", best.source_id, best.confidence);
    }
    Ok(())
}

The whole point is that routing improves. Close the loop by logging the route and feeding back the outcome:

// Route and record the decision in one step.
let ranking = router.route_and_log(&query)?;

// Later, after the source actually answered, tell the router how it went:
let query_id = query.predicate_hash();
router.learn_from_outcome(query_id, "dbpedia", true, 150, 100)?;
//                        query_id, source_id, success, latency_ms, result_count

There is also an oxirouter-cli binary with route, explain, void-import, and state save/load subcommands.

What’s inside

Everything in the 0.1.0 line:

Tips

A few ways to get the most out of OxiRouter 0.1.0:

  1. Register sources declaratively. Enable the void feature and feed Router::register_from_void_ttl a VoID/Turtle descriptor instead of hand-coding SourceCapabilities — your topology becomes data, not code.
  2. Close the learning loop. Use route_and_log() followed by learn_from_outcome() so the router improves its source selection from real observed latency and success rates.
  3. Turn on the right brains for the job. ml (neural / naive Bayes / ensemble, no_std via libm) sharpens scoring when you have history; rl (ε-greedy exploration) helps when you don’t.
  4. Make routing context-aware. Enable geo, device, load, and legal individually — or ecosystem for all four — so decisions factor in location, device, system load, and jurisdiction.
  5. Build genuinely small for the edge. Try --no-default-features --features "alloc,wasm,ml,rl,cache" with the release-edge profile and wasm-opt -Oz to ship a tiny WASM router.
  6. Let the circuit breaker protect you. Configure the per-source failure threshold + cooldown so a single flaky endpoint can’t sink your whole federation.
  7. Expose it to LLM agents. With the agent feature, oxirouter.route / .learn / .explain are OpenAI/Anthropic tool-call compatible — drop them straight into an agent’s tool list.

This is the foundation

OxiRouter does not stand alone. Its four context “brains” are real, shipped COOLJAPAN dependencies, each pulled in behind its own feature flag:

These let a routing decision factor in where you are, what you’re running on, how loaded the system is, and what’s legally permissible — together, the richest part of the OxiRouter story.

And one honest design note, because it’s also a selling point: OxiRouter deliberately does not depend on a full semantic-web stack. The SPARQL prefix-expansion and Turtle-subset parsing are implemented inline in pure Rust (src/core/sparql.rs, src/core/turtle.rs) with zero new dependencies — a lean, edge-friendly choice that keeps the WASM binary tiny and the dependency tree shallow.

Repository: https://github.com/cool-japan/oxirouter

Star the repo if learned, lean, sovereign federation is something you want to see grow — Pure Rust semantic federation is here: learned, lean, and sovereign.

KitaSan at COOLJAPAN OÜ May 3, 2026

↑ Back to all posts