Skip to main content
RCP is point-to-point: one server answers for its own index. Querying all the engines you can reach is a client concern, layered on the core methods with zero new server obligations. There are two routing models, both drivable from a single rcp.json registry.

The registry — rcp.json

string
required
A client-local label used to tag fused hits by origin (meta.engine).
"stdio" | "http"
required
With command (stdio) or url (http).
integer
default:"0"
Higher wins for Selector’s primary → secondary fallback.
float
default:"1.0"
Scales the engine’s contribution during fusion.
boolean
default:"false"
If true, a connect/query failure fails the whole federated query instead of being skipped.
Discovery composes with the catalog capability: a registry entry can point at an aggregator that enumerates further engines via catalog/list.

Selector — pick one of many

When you have several backends but each query should hit exactly one, a Selector chooses it for you from the rcp.json registry. It connects lazily — listing ten candidates opens zero connections until you call a select_* method, and then only to the winner. There are three selection policies: Both select_primary and select_capable give you priority + liveness fallback for free: a multi-backend deployment stays up when a backend dies, without the client writing any failover glue. priority in the registry (higher wins) sets the order they’re tried.
Use select_capable as the default in a mixed fleet: it is the “any live backend that can do X, best one first” query, so a client never has to hard-code which engine owns which capability.

Federation — fuse many

A federated retrieve(query, k) fans out retrieve to every engine that advertises it, concurrently. Engines lacking the capability are skipped (not an error); a slow non-required engine is dropped after a client-side deadline so one bad backend can’t stall the query.

Reciprocal Rank Fusion

The default and recommended fusion is RRF (Cormack et al. 2009), which needs only ranks — not comparable scores — so it is robust across heterogeneous engines:
where rank_engine(d) is the 1-based position of document d in that engine’s list (engines that didn’t return d contribute nothing). The fused list is sorted by descending RRF(d) and truncated to k.
Never fuse raw scores directly — scores from different scorers are not comparable. If you must use weighted score fusion, min-max normalise per engine to [0,1] first. RRF is preferred by default precisely because it sidesteps this footgun.

Determinism & dedup

  • Tie-breaking is deterministic: order by (1) higher fused score, then (2) higher summed weight, then (3) lexicographically smaller stringified id — a total order independent of engine response arrival.
  • Deduplication keys on the stringified Hit.id. When two hits collapse, the fused hit SHOULD keep the richest body and merge meta. Each fused hit carries its origin in meta.engine.

The fusion primitive — rrf_fuse

You don’t need the full Federation facade to fuse. Every reference SDK exports the fusion algorithm as a standalone, tested function over ranked lists you already hold — a cache, a replay, two hand-issued retrieve calls — so no adopter re-derives §16.3 (and re-derives it subtly wrong). All four are byte-for-byte identical: same tie-break, same richest-body dedup, same origin tagging in meta.engine and meta.fusedScore.
The default rrfK is 60 (rcp.RRF_K_DEFAULT / fusion::RRF_K_DEFAULT). The live C++ Federation calls the very same rcp::fusion::rrf_fuse, so fan-out fusion and held-list fusion agree exactly.

One command: fan out and fuse

examples/example_federation.py is spec §16 made runnable in a single process — it spawns two genuinely independent engine subprocesses (each its own corpus), fans one query out to both, and fuses their rankings with rcp.rrf_fuse:
No servers to start, no ports, no config — the whole federation lives and dies with the process.

Federated capabilities

A client’s effective capability set over a federation is the union of its engines’ capabilities (it can embed if any engine can); its guaranteed set is the intersection. A federated retrieve runs against the subset advertising retrieve; a federated graph op against those advertising it. Reference SDKs expose both a per-engine handle and a Federation facade.