# mubit-sdk (Rust)
Canonical Rust SDK for MuBit.
## Install
```bash
cargo add mubit-sdk
```
## Three Layers
The SDK offers three integration depths. Start at the top and drop down only when you need more control.
| **Learn** | `learn` | Explicit `enrich_messages()` / `record()` / `end()` for closed-loop memory with lesson injection | Closed-loop learning with full async control |
| **Helpers** | `Client` | 17 explicit methods for memory write/read, context assembly, reflection, multi-agent coordination | Fine-grained control over what gets remembered, queried, and when reflection triggers |
| **Raw** | `client.auth`, `client.core`, `client.control` | Direct 1:1 mappings to every gRPC/HTTP endpoint | Wire debugging, async ingest job polling, compatibility routes |
## Layer 1: Learn (Closed-Loop Memory)
The `learn` module provides explicit methods for closed-loop memory. Unlike Python/JS, Rust does not use monkey-patching — call `enrich_messages()` before your LLM call and `record()` after.
```rust
use mubit_sdk::learn::{LearnSession, LearnConfig};
use serde_json::json;
let session = LearnSession::new(
LearnConfig::from_env()
.agent_id("my-agent")
.inject_lessons(true)
.auto_reflect(true)
).await;
let messages = vec![
json!({"role": "user", "content": "Fix the auth bug"}),
];
// Enrich with lessons before LLM call
let enriched = session.enrich_messages(&messages).await;
// Make your LLM call with enriched messages...
// Record the interaction
session.record("response text", "gpt-4o", 1500.0).await;
// End run (triggers reflection)
session.end().await;
```
Key config: `inject_lessons`, `injection_position`, `max_token_budget`, `auto_reflect`, `cache_ttl_seconds`, `fail_open`.
## Layer 2: Client Helpers
### Quickstart
```rust
use mubit_sdk::{Client, ClientConfig, RecallOptions, RememberOptions};
use std::env;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let api_key = env::var("MUBIT_API_KEY")?;
let client = Client::new(
ClientConfig::default()
.run_id("sdk-rust-demo")
.api_key(api_key),
)?;
let mut remember = RememberOptions::new(
"Checkpoint before replaying recovery after token signer rotation.",
);
remember.run_id = Some("sdk-rust-demo".to_string());
remember.intent = Some("lesson".to_string());
remember.lesson_type = Some("success".to_string());
client.remember(remember).await?;
let mut recall = RecallOptions::new("What should I do before replaying recovery?");
recall.run_id = Some("sdk-rust-demo".to_string());
recall.entry_types = vec!["lesson".to_string(), "rule".to_string()];
let answer = client.recall(recall).await?;
println!("{}", answer["final_answer"]);
Ok(())
}
```
### Methods by Use Case
| Basic memory | `remember`, `recall` | Ingest content with intent classification; semantic query with evidence scoring |
| Prompt context | `get_context` | Token-budgeted, pre-assembled context block for LLM prompt injection (rules → lessons → facts) |
| Exact artifacts | `archive`, `dereference` | Bit-exact storage with stable reference IDs; retrieval without semantic search |
| Run lifecycle | `checkpoint`, `reflect`, `record_outcome` | Durable pre-compaction state; LLM-powered lesson extraction; reinforcement feedback |
| Multi-agent | `register_agent`, `list_agents`, `handoff`, `feedback` | Scoped read/write access per agent; task transfer between agents |
| Diagnostics | `memory_health`, `diagnose`, `surface_strategies`, `forget` | Staleness metrics; contextual error debugging; lesson clustering; deletion |
Helper calls take typed option structs instead of raw `serde_json::Value` payload bags.
### The Learning Loop
```
1. remember() → ingest facts, traces, lessons into MuBit
2. reflect() → LLM extracts lessons from run evidence
(auto-promotes recurring lessons: run → session → global)
3. get_context() → retrieve relevant lessons for the next LLM call
4. record_outcome() → reinforce what worked, adjust confidence scores
```
With `LearnSession`, steps 1 and 3 are handled by `record()` and `enrich_messages()`. With helpers, you orchestrate them yourself.
### Exact References
```rust
use mubit_sdk::{ArchiveOptions, Client, ClientConfig, DereferenceOptions};
let client = Client::new(ClientConfig::default().run_id("sdk-rust-demo"))?;
let mut archive = ArchiveOptions::new(
"--- a/query.py\n+++ b/query.py\n@@ ...",
"patch_fragment",
);
archive.run_id = Some("sdk-rust-demo".to_string());
archive.labels = vec!["django".to_string(), "retry".to_string()];
let archived = client.archive(archive).await?;
let mut dereference = DereferenceOptions::new(
archived["reference_id"].as_str().unwrap_or_default(),
);
dereference.run_id = Some("sdk-rust-demo".to_string());
let exact = client.dereference(dereference).await?;
println!("{}", exact["evidence"]["content"]);
```
## Layer 3: Raw Domains
Low-level 1:1 mappings to every API endpoint on `client.auth`, `client.core`, and `client.control`.