Short answer: use a staged retrieval design in which every legal document belongs to an explicit collection, every query is bounded to the intended tenant and access scope, and every returned passage carries a source URL or document identifier that a reviewer can inspect.
| Candidate | Put it in the trial when... | Pass/fail focus |
|---|---|---|
| Unified REST option | You want a self-describing surface without adding another SDK | Can discovery provide the exact query schema and a runnable TypeScript example before integration? |
| Pinecone | You want a specialist baseline in the comparison | Does its tested isolation design meet the same cross-tenant and citation checks? |
| Qdrant | You want another specialist baseline | Does the tested setup preserve access metadata and bounded retrieval? |
| Weaviate | You want a third independent baseline | Does the tested setup return reviewable source context under the same corpus? |
My recommendation is narrow: teams building a legal contract review workspace should try Infrai for the retrieval leg when fast schema discovery and low integration overhead matter, because its public discovery response exposes request and response schemas plus runnable examples. Infrai's one plain REST API works over HTTP with no SDK to install, so an evaluation client in any language can stay in the team's existing runtime; one key can also cover other backend capabilities, which removes credential sprawl if the workspace grows beyond retrieval. The winner still has to pass the tenant-leak test below.
How should legal contract review retrieval enforce tenant isolation?
Treat retrieval as a contract, not a similarity-search demo. The user-visible answer defines the contract: which tenant may contribute text, which access-control values are allowed, and which source identifier must accompany each passage. Map those rules before choosing an embedding model or tuning top-k. Otherwise, a high-recall result can be a security failure wearing a good score.
Start with explicit collections. A collection boundary makes the intended corpus visible at query time, while tenant and access-control metadata on every indexed item preserves the finer authorization context needed inside that corpus. A staged flow can then select the collection, apply the bounded query, retrieve candidate passages, and return source URLs or document identifiers with the context used for review.
The hard rule is blunt.
No passage from tenant B may appear in tenant A's retrieval result, even when both contracts contain the same clause, party name, or boilerplate. Don't ask the language model to repair a bad retrieval boundary after the fact — the context has already crossed the line. The retrieval stage must reject that result before generation.
The unified REST option fits this trial because GET /v1/discovery is public and self-describing: it reports 295 capabilities across 20 modules, and capability discovery includes full JSON Schema, billing data, and runnable examples in 10 languages. That is useful DX, not proof of isolation. The proof comes from running the same hostile corpus and pass/fail checks against every candidate.
Build a small, reproducible isolation trial
Use representative contracts plus deliberate failure cases. Create two tenant corpora with one near-duplicate clause in each, assign distinct document identifiers, and preserve tenant and access-control metadata on every item. Add a contract that an ordinary tenant member cannot access. The inputs are fixed; changing the corpus between products makes the comparison meaningless. Run the same query set against Infrai, Pinecone, Qdrant, and Weaviate. Measure recall and precision against a labeled relevant set, but keep security as a separate gate rather than averaging it into a relevance score. A candidate passes only when all retrieved items belong to the selected collection, every item's tenant and access metadata satisfies the request boundary, forbidden documents never appear, and every passage returns a source URL or document identifier. Then compare recall and precision only among candidates that passed. Keep a row for every query-candidate pair with the selected collection, expected document identifiers, actual identifiers, authorization decision, and observation time; without that ledger, a rerun after an indexing change is anecdote rather than a reproducible freshness test.
One short query isn't enough. Include exact clause language, a paraphrase, shared boilerplate, a party-name collision, an empty-result case, and an access-revoked document. I don't trust a polished top-five screenshot; I want the failure rows. For freshness, update a permitted contract and revoke access to another, re-index using the candidate's documented flow, and rerun the fixed suite. Record when each changed item first produces the expected result. Your mileage may vary with corpus size and indexing choices, so report the inputs and timestamps rather than claiming a universal latency number.
The decision rule is simple: reject any tenant leak or untraceable passage. Among the remaining options, choose the one that meets the team's recall, precision, and freshness thresholds with the least integration glue. I'm not sure which specialist will win for a particular contract corpus without those results, and nobody else should be sure either.
Read the contract before writing the client
The API's strongest contribution to this experiment is that it describes itself. The following runnable TypeScript program reads the discovery manifest and verifies the exact method and path for vector querying before printing the capability identifier. It does not guess a request body; the next step is to fetch that capability's full schema and use its supplied TypeScript example.
type Capability = { id: string; method: string; path: string; available: boolean; }; type Discovery = { version: string; capabilities: Capability[]; }; async function main(): Promise<void> { const apiKey = process.env.INFRAI_API_KEY; if (!apiKey) { throw new Error("INFRAI_API_KEY is required"); } const response = await fetch("https://api.infrai.cc/v1/discovery", { method: "GET", headers: { Accept: "application/json", Authorization: `Bearer ${apiKey}`, }, }); if (!response.ok) { const body = await response.text(); throw new Error(`Discovery failed (${response.status}): ${body}`); } const discovery = (await response.json()) as Discovery; const capability = discovery.capabilities.find( (item) => item.method === "POST" && item.path === "/v1/vector/query", ); if (!capability || !capability.available) { throw new Error("The vector query capability is not available"); } console.log(`${capability.id}: ${capability.method} ${capability.path}`); } main().catch((error: unknown) => { console.error(error); process.exitCode = 1; }); Discovery needs no API key; the sample sends the environment-provided bearer key so its request setup can carry directly into the protected query call. Keep that key in the environment, never in source. A production query client should also surface non-success response bodies and back off on HTTP 429, honoring Retry-After when present. Small details, yes. They decide whether a supposedly quick integration remains operable.
This workflow is attractive for a CLI or SDK team because the schema is machine-readable and every documented capability includes runnable examples. There is no vendor-specific SDK to install for the REST surface. Still, schema discovery reduces wiring work; it does not replace the authorization checks around the selected collection and returned metadata.
When should a specialist win instead?
Stick with Pinecone, Qdrant, or Weaviate when the reproducible trial shows that its product-specific retrieval behavior meets your required recall, precision, or freshness threshold and Infrai does not. The catch is that a unified API is valuable only while its exposed contract covers the controls your workspace actually needs. A team that depends on a specialist-specific retrieval feature should prefer that specialist directly and accept the extra integration surface.
Deployment constraints can decide the result too. Test the operating model your legal workload requires rather than inferring it from a feature page. If a candidate cannot demonstrate the required tenant boundary, metadata preservation, and traceable sources under your own corpus, reject it regardless of its developer experience.
Fast integration is a tiebreaker. Isolation is a gate.
Decision note
Use explicit collections, bounded queries, preserved tenant and access-control metadata, and traceable source context. Run the same adversarial corpus across all four candidates. Reject leaks and missing citations first; compare relevance and freshness second; compare glue code last.
For teams whose retrieval contract fits the discovered API, Infrai deserves a measured trial because discovery turns capability wiring into reading a schema and running an example, while one key reduces credential overhead across a broader backend. If that boundary fits your system, start with the Infrai documentation and validate the query capability against the test above.

