Build on Semurg.
Point your application at a node you run, and read and write your data through one small, consistent surface. A client library in your language does the talking; the same mental model carries across your whole stack, because every face reads one copy.
Eleven languages, one small surface.
Every SDK is a thin client: you point it at the base URL of a node you operate, optionally hand it a token, and call the same handful of verbs, spelled the natural way for each language. There is no hosted control plane in the loop and no per-item egress, your bytes stay on your box. Most of these use only their language's standard library, so there is nothing extra to pull in.
| Language | HTTP stack | Extra dependencies |
|---|---|---|
| Python | urllib (standard library) | none |
| Rust | standard library | none |
| C++ | standard library | none |
| Go | net/http (standard library) | none |
| Java | java.net.http (JDK 11+) | none |
| C# | HttpClient (base class library) | none |
| F# | HttpClient (base class library) | none |
| Elixir | standard library | none |
| Erlang | httpc (standard library) | none |
| OCaml | standard library | none |
| Julia | Downloads (standard library) | none |
Each SDK ships with its own README (install plus a five-line usage example against a local node), a runnable round-trip example that connects and reads back, and offline codec tests. Per-language install, connect and round-trip instructions are on the Drivers page.
The SDKs ship with the release as one archive, downloadable and checksummed alongside the engine:
curl -fsSLO https://one.semurg.io/dl/clients.tar.gz && curl -fsSL https://one.semurg.io/dl/SHA256SUMS | grep clients.tar.gz | sha256sum -c - && tar xzf clients.tar.gzThe same names in every language.
Two scopes, spelled per-language (run_bench / RunBench,
fetch_batch / FetchBatch, and so on).
| Method | Does |
|---|---|
health() | liveness, engine state, dataset readiness |
version() | SDK version plus a summary of the node's identity |
benchmarks() | the catalog of runnable benchmark keys |
dashboard() | one-call headline snapshot |
bench(key) / run_bench(key, params) | run one benchmark, with default or explicit params |
| Method | Does |
|---|---|
status() | instance identity, licence, writability, store state |
query(op, args) | batch read: fetch | resolve | search | histogram |
fetch(ids), resolve(id), search(needle), histogram(field, buckets) | named wrappers over query |
fetch_batch(ids) | the binary fast path: many ids in, the matching records out, in request order |
ingest(records) | append a batch (needs the write capability) |
Each SDK maps node responses to typed errors: auth (401/403),
not-found (404), rate-limited (429 and warming 503, carrying Retry-After), server (5xx),
transport (unreachable/timeout), and a roadmap error for a transport whose live wire has not shipped. The
full endpoint shapes and status codes are on the API page.
One client, a pluggable transport.
Every SDK is built around one transport you can swap. The SDKs never fake a live wire: pick a method that has not fully shipped and you get the parts that are real today plus a clear, typed roadmap error for the rest.
| Method | Status | What it is |
|---|---|---|
| HTTP Live | the working default | The /api and /v1 surface. The default in every SDK. |
| WebSocket Roadmap | interface live, data wire on the roadmap | The node runs a socket for its live UI; a programmatic data-stream topic is on the roadmap. |
| Semurg ATP Roadmap wire | codec live in all 11; public wire roadmap | A fast native binary protocol. The frame codec is live and byte-identical to the node in all eleven SDKs; ATP-over-TCP runs as a local/loopback fast path in a few SDKs, and the public authed wire is on the roadmap. Use HTTP over the network. |
Add a new face, right next to the data.
Beyond the network API, Semurg can be extended in-process. An extension adds a new face, a new ingestor, or a new domain to the one substrate. It owns no storage of its own: it works through the engine and reads the same one copy every other face reads, so there is nothing to sync and no second store to keep in step.
- Inward only. An extension builds on the engine; it never reaches sideways into another extension. The boundary is enforced by the build, not by review.
- No side store. The storage, memory and background upkeep are always the engine's. An extension holds handles and calls functions.
- A real template ships in the tree. The two-way database ingestor (SQL and graph import) is a working extension you can read as a pattern.
Read the full Build-an-extension guide → the Tier-3 pattern in depth, a working template to copy, the inward-only boundary, and a preview of Helix — the swarm of role-agents that builds, tests, and deploys an extension for you.