FermiHDI SDK — Mojo
BETA. Written from scratch in September 2026 and built on every change. Newest of the wrappers; expect the least mileage.
A real binding to the FermiHDI SDK, built on the C ABI in
include/fermihdi_c_api.h. Every function in FermiHDISDK.mojo reaches a
symbol in libfermihdi_client.so.
History, because it matters
Two files used to sit here and were deleted on 2026-08-27 because neither
worked and both reported success while doing nothing -- one had its single FFI
call commented out. They had a reason to cheat: the SDK exported no C symbols
at all. Go worked only because its C shim (go/sdk_bridge.cpp) is compiled
into the cgo package, which is no help to a language with plain FFI.
The fhd_* surface now lives in the shared library, so there is something real
to bind to.
Building
mojo build your_program.mojo \
-Xlinker -L$FERMIHDI_SDK_ROOT/lib \
-Xlinker -lfermihdi_client \
-Xlinker -rpath -Xlinker $FERMIHDI_SDK_ROOT/lib
Symbols resolve at link time rather than through dlopen, because dlsym in
this Mojo returns a data pointer rather than a callable and there is no
supported way to call through it.
For a static binary, link the archive instead and drop the rpath:
mojo build your_program.mojo \
-Xlinker $FERMIHDI_SDK_ROOT/lib/libfermihdi_client_static.a \
-Xlinker -lstdc++
Modes
Mojo calls the C ABI's query client directly. That ABI carries a target-setting
call and no registration or ingest call, which leaves Mojo in proxy mode
(or querying SCC targets it was given) and unable to register as an
HD_CLIENT node or to ingest. The
SDK overview has the
modes and their per-binding support.
API
sdk_version() -> String # read from the library, not hardcoded
struct QueryClient:
QueryClient(proxy_url, data_plane_iface="", ctrl_plane_iface="",
return_port=6987)
is_open() -> Bool
close() # explicit; see the note below
stop()
load_schema(schema_json) -> Bool
set_scc_target(ip, port)
health() -> String # JSON: status (liveness), ready
generate_query(hdquery_json) -> String # "" if the full-scan guard refuses
prepare_query(query_id) # arm the listener FIRST
submit_to_proxy(query_json, query_id) -> String
# JSON: {"ok":..,"empty":..,"found_batches":[..],"error":".."}
set_timeout_ms(ms)
set_filter_verdict(verdict_json) -> Bool # for a query you dispatched yourself
false_negatives() -> String # JSON: bloomrf_mode, false_negatives
cancel_query(query_id)
set_filter_verdict() is for a query placed by your own route rather than
submit_to_proxy(): pass the proxy's result event JSON verbatim so the SDK
knows what the filter service would have excluded. Without it the
false-negative check at the end of the query never runs. false_negatives()
must come back with an empty list; one entry is a filter defect.
submit_to_proxy() places the query and holds the connection for the life of
the query, reporting the ending itself — see
§2.3. Nothing else to relay.
Use cases
A Mojo service querying HD directly, with no Python or JVM runtime in the image. Link the static archive for a single binary.
Numeric work on returned records, close to where they land, without an intermediate copy through another runtime.
Usage
from FermiHDISDK import QueryClient, sdk_version
def main():
print(sdk_version())
var client = QueryClient(String("https://proxy.example:443"))
if not client.is_open():
return
_ = client.load_schema(schema_json)
print(client.health())
client.close()
Gotchas
close()is explicit. Anexternal_callinside__deinit__crashes the current Mojo compiler outright --kgen.call_param op invalid use of parameter with no declaration callee, reproducible with a three-line struct -- so the destructor cannot be the thing that frees.- The full-dataset-scan guard returns
""fromgenerate_query— see §3.2. - Query IDs must be distinct across every client talking to the cluster; seed at random rather than from the clock.
- Advertise an address the storage nodes can reach, or the query returns nothing and reports no error.