reasoninglayer
Rust client SDK for the Reasoning Layer API.
Idiomatic Rust naming (snake_case), ? for error propagation, fully typed DTOs for the
core resource surface, with HTTP, WebSocket (auto-reconnect, exponential backoff, 10 attempts,
30 s cap), and SSE transports built in. See [reasoninglayer::ws] and [reasoninglayer::sse].
Install
[]
= "0.1"
= { = "1", = ["macros", "rt-multi-thread"] }
TLS backend: rustls by default. Switch with features:
= { = "0.1", = false, = ["native-tls"] }
Rust toolchain
This crate tracks current stable Rust and does not maintain a fixed MSRV. The Rust async ecosystem (tokio, reqwest, the idna → icu_* chain) bumps minimum Rust versions in patch releases, so a fixed MSRV would either be a claim we can't keep, or would force us to lag dep upgrades and miss bug/security fixes. CI runs against the latest stable Rust on every push. If you have a non-current toolchain constraint, open an issue.
Quick start
use BTreeMap;
use ;
async
Configuration
| Field | Type | Default | Notes |
|---|---|---|---|
base_url |
String |
— | Required. Trailing / stripped. |
tenant_id |
String |
— | Required. Sent as X-Tenant-Id; not overridable per call. |
user_id |
Option<String> |
None |
X-User-Id; overridable per call. |
namespace_id |
Option<String> |
None |
X-Namespace-Id; overridable per call. |
authenticated_user |
Option<String> |
None |
X-Authenticated-User. |
bearer_token |
Option<String> |
None |
Authorization: Bearer …. |
timeout |
Duration |
30 s | Per-call override via RequestOptions. |
max_retries |
u32 |
3 | Per-call override via RequestOptions. |
retry_on_503 |
bool |
false |
Retry on Service Unavailable. |
Every request also sends X-SDK-Version and X-SDK-Language: rust so the backend can
identify the calling SDK.
Per-call options
use Duration;
use RequestOptions;
let opts = new
.with_user_id
.with_timeout
.with_retries;
client.sorts.list_sorts.await?;
Cancellation: drop the future (for example with tokio::select!) to abort the request in flight.
Two serialization formats
The Reasoning Layer API uses two serialization formats depending on the endpoint:
| Endpoint family | Format | Types |
|---|---|---|
| Term CRUD, query, fuzzy | Tagged ValueDto |
{"type": "String", "value": "hello"} |
| Inference (rules, facts, chaining) | Untagged TermInputDto |
Raw "hello" / 42 / null / {name: "?X"} |
Use the right type for the endpoint:
- Term CRUD: build
BTreeMap<String, ValueDto>viaValue::string(...),Value::integer(...), or.into()conversions from plain Rust values. - Inference: build
TermInputDtovalues via the inference builders re-exported from the crate root (see the [builders] module on docs.rs for the full list).
Errors
All fallible operations return Result<T, reasoninglayer::Error>. HTTP errors are Error::Api
wrapping an ApiError with a kind discriminant:
use ;
match client.terms.create_term.await
Automatic retry: HTTP 429 is retried with exponential backoff (honouring Retry-After).
503 is retried only when retry_on_503 is set. Transient network errors retry up to max_retries
times.
Resource surface
Core resources with fully typed request/response DTOs:
| Accessor | Alias | Highlights |
|---|---|---|
client.sorts() |
client.types() |
28 methods — CRUD, GLB/LUB, hierarchy queries, similarity learning |
client.terms() |
client.records() |
9 methods — CRUD, bulk, exists, clear |
client.inference() |
client.rules() |
20 methods — rules/facts, backward/forward/tagged, fuzzy, Bayesian, NAF, goals |
client.query() |
— | find_unifiable, find_by_sort, osf_search, validate_term, validated_unify, nl_query |
Additional resources with typed DTOs: health, admin, osfql, context, rl_training, rag,
generation, image_extraction, extract, preferences, discovery, functions, ontology,
analysis, scenarios, spaces, row, sources, ui, optimize, fuzzy, causal,
statistical, communities, visualization, constraints, namespaces, collections,
reasoning.
Resources currently exposing serde_json::Value (typed DTOs landing in patch releases):
control, reviews, action_reviews, webhook_actions, ilp, cdl, synthetic, utilities,
ingestion, execution, proof_engine, conversation, research, cognitive / agents,
oversight, neuro_symbolic.
Streams:
// WebSocket (auto-reconnect):
use WebSocketConnection;
let url = client.cognitive.agent_events_url?;
let mut ws = connect.await?;
while let Some = ws.next_message.await?
// SSE:
use StreamExt;
use stream;
let body = json!;
let mut events = Boxpin;
while let Some = events.next.await
Development
Releasing
Releases are driven by cargo-release per the configuration in release.toml. The actual publish to crates.io is done by GitLab CI on tag push, not from your laptop, so you never need a local crates.io token.
Substitute minor, major, or an explicit X.Y.Z for patch as needed. The script bumps Cargo.toml, refreshes Cargo.lock, rewrites CHANGELOG.md (moves [Unreleased] content under a dated [X.Y.Z] heading and inserts a fresh empty [Unreleased]), runs cargo test --all-features and cargo publish --dry-run, then commits, tags vX.Y.Z, and pushes. Pushing the tag triggers the GitLab publish stage which runs the actual cargo publish against crates.io using the masked CARGO_REGISTRY_TOKEN CI/CD variable.
License
MIT.