# erebyx-sdk
> Type-safe Rust SDK for the EREBYX memory substrate. Persistent AI memory across every AI you use.
[](LICENSE-MIT)
[](CHANGELOG.md)
[](https://crates.io/crates/erebyx-sdk)
[](https://docs.rs/erebyx-sdk)
---
## Install in 5 lines
```toml
# Cargo.toml
[dependencies]
erebyx-sdk = "0.1"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```
```rust
# tokio_test::block_on(async {
let memory = erebyx_sdk::Memory::from_env()?;
let response = memory
.save("Anchor retrieval improves recall by 40%", "insight")
.send()
.await?;
println!("saved {}", response.memory_id);
# Ok::<_, erebyx_sdk::Error>(()) }).unwrap();
```
That's the whole loop: install -> save. Memory is encrypted in transit (TLS 1.3) and at rest using XChaCha20-Poly1305 envelope encryption (AES-256-GCM legacy supported on existing rows) with per-tenant Key Encryption Keys wrapped under a server-held master KEK. Per-user zero-knowledge encryption (passphrase-derived keys, EREBYX cannot decrypt) ships in v0.2.
---
## What it is
`erebyx-sdk` is the Rust client for the EREBYX memory substrate. It exposes the v0.1.1 cognitive surface as five async methods, each returning a builder for optional fields:
| Method | Purpose |
|---|---|
| `restore_identity()` | Wake up — load identity at session start |
| `load_context()` | Resume — load handoff + recent work |
| `save(content, category)` | Store a memory worth keeping |
| `search(query)` | Find what you know by meaning (the `remember` verb) |
| `wrap_up(what_we_built, whats_next)` | Create a session handoff at the end |
All processing — memory understanding, recall, organization, encryption — lives behind the API — you never need to think about it.
---
## Quickstart
```rust
use erebyx_sdk::Memory;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// Reads EREBYX_API_KEY + EREBYX_API_URL + EREBYX_INSTANCE_ID from env
let memory = Memory::from_env()?;
// Save
memory.save("Anchor-based retrieval improves recall by 40%", "insight")
.anchors(vec!["memory", "retrieval"])
.importance(0.9)
.send()
.await?;
// Search
let results = memory.search("anchor retrieval performance")
.limit(5)
.send()
.await?;
for record in &results.memories {
println!("{}: {}", record.id, record.content);
}
// Session handoff
memory.wrap_up("Wired the SDK into our agent loop", "Add streaming search")
.anchors(vec!["sdk", "rust"])
.send()
.await?;
Ok(())
}
```
---
## Configuration
```bash
# Required
export EREBYX_API_KEY="<YOUR_API_KEY>"
# Required for tenants registered at v0.1.1+ (Argon2id-default-on).
# Find it in your dashboard recovery panel. At v0.1.1, EREBYX holds a
# server-side master KEK and can decrypt for support/backup/recovery —
# this is NOT zero-knowledge. When per-user zero-knowledge ships in v0.2,
# your passphrase + BIP39 recovery seed become the ONLY keys to your
# memory; losing both will be unrecoverable by design. Keep both safe.
export EREBYX_PASSPHRASE="<YOUR_PASSPHRASE>"
# Optional (defaults shown)
export EREBYX_API_URL="https://core.erebyx.com"
export EREBYX_INSTANCE_ID="default"
```
Get your API key at [app.erebyx.com/keys](https://app.erebyx.com/keys).
The dashboard surfaces the matching `EREBYX_PASSPHRASE` value at registration;
both are required for new tenants.
Or pass everything explicitly:
```rust
let memory = Memory::builder("<YOUR_API_KEY>")
.api_url("https://core.erebyx.com")
.instance_id("my-service")
.build()?;
```
---
## X-Erebyx-Hint — lifecycle signals for free
Every SDK call surfaces the substrate's lifecycle hints (carried on the
`X-Erebyx-Hint` response header) and any tools the substrate auto-fired
(`X-Erebyx-Auto-Fired`). Both are typed fields on every response struct:
```rust
let response = memory.save("...", "insight").send().await?;
for hint in &response.hints {
match hint.as_str() {
"wrap_up_recommended" => { /* call wrap_up at next natural break */ }
"restore_identity_recommended" => { /* identity drift; re-anchor */ }
"load_context_recommended" => { /* refresh working memory */ }
"compact_imminent" => { /* consolidate before context fills */ }
_ => {}
}
}
// First call against a fresh (instance_id, session_id) tuple typically
// reports `["restore_identity", "load_context"]`; empty thereafter.
println!("auto-fired this call: {:?}", response.auto_fired);
```
Hint values:
- `wrap_up_recommended` — substrate sees a natural consolidation boundary
- `restore_identity_recommended` — voice drift detected
- `load_context_recommended` — retrieval scores trending low
- `compact_imminent` — sustained save volume; consolidate before context fills
Honoring hints is optional — the SDK never acts on them automatically. Full hint protocol at [DEV_QUICKSTART.md](DEV_QUICKSTART.md#x-erebyx-hint--lifecycle-signals).
---
## Reliability
Built-in circuit breaker — after 3 consecutive failures, the SDK refuses calls for 30s, then attempts a half-open retry. Memory failures degrade gracefully and never crash your application.
```rust
match memory.save("...", "insight").send().await {
Ok(response) => { /* memory persisted */ }
Err(erebyx_sdk::Error::CircuitOpen { cooldown_secs }) => {
// Substrate degraded; backed off. Don't block the user;
// the SDK auto-retries after the cooldown window.
tracing::warn!(cooldown_secs, "erebyx circuit open; skipping save");
}
Err(erebyx_sdk::Error::AuthenticationFailed(msg)) => {
// Caller-side problem — the API key is wrong / expired.
// No amount of retry fixes this.
tracing::error!(?msg, "erebyx auth failed");
}
Err(e) => { /* hard error; bubble up */ }
}
```
The SDK emits `tracing::debug!` + `tracing::warn!` events at substrate-call boundaries (circuit-breaker state transitions, retryable failures). Subscribe via `tracing_subscriber` to route them into your observability stack. Per-method spans via `#[instrument]` ship in v0.1.2.
---
## Architecture
```
src/
lib.rs Public API (Memory + builders)
client.rs HTTP client (reqwest, rustls) + circuit breaker
middleware.rs LLM call middleware (before/after memory hooks)
types.rs Request / response types
error.rs Typed errors
```
The SDK calls the substrate HTTP API at `${EREBYX_API_URL}` using plain JSON. Each method maps to one substrate route (`/v0/memory/store`, `/v0/memory/remember`, `/v0/session/wrap-up`, `/v0/identity/restore`, `/v0/session/load`). Headers on every request: `Authorization: Bearer <api_key>`, `X-Instance-ID`, `X-Erebyx-Session-Id`, `Content-Type: application/json`. Tenants registered at v0.1.1+ also send `X-Passphrase` (read from `EREBYX_PASSPHRASE` env var or `MemoryBuilder::passphrase`).
Override the per-process session id via `MemoryBuilder::session_id` if you want to bind it to an external identifier (harness conversation id, LLM thread id, browser tab id). Defaults to a fresh UUID v4 per builder.
---
## How to upgrade
Track releases in [CHANGELOG.md](CHANGELOG.md). Backward compatibility is a hard guarantee within v0.1.x — every release lists explicit breaking changes (none expected before v0.2).
```toml
[dependencies]
erebyx-sdk = "0.1" # always picks the latest 0.1.x
```
```bash
cargo update -p erebyx-sdk
```
---
## Build from source
```bash
git clone https://github.com/ProjectErebyx/erebyx-sdk.git
cd erebyx-sdk
cargo build --release
cargo test
```
Requires Rust 1.75+.
---
## See also
- [`erebyx-cli`](https://github.com/ProjectErebyx/erebyx-cli) — Native CLI for MCP integration
- [`@erebyx/sdk`](https://github.com/ProjectErebyx/erebyx-sdk-node) — Node.js / TypeScript SDK (napi wrapper around this crate)
- [Substrate overview](https://erebyx.com/core) — integration patterns + per-harness examples
---
## Contributing
Pull requests welcome. DCO sign-off required (`git commit -s`). See [CONTRIBUTING.md](CONTRIBUTING.md).
## Security
Vulnerability reports → `legal@erebyx.com`. See [SECURITY.md](SECURITY.md).
## License
Dual-licensed under MIT or Apache-2.0 at your option. See
[LICENSE-MIT](LICENSE-MIT), [LICENSE-APACHE-2.0](LICENSE-APACHE-2.0),
and [NOTICE](NOTICE).
---
**Built by EREBYX, LLC** — `https://erebyx.com`