Official Rust SDK for MemMesh — memory + prediction
for AI agents. Async (reqwest/tokio), semantic recall, a bi-temporal
knowledge graph, belief revision, reflection, and calibrated forecasting.
Add it to your Cargo.toml:
[dependencies]
memmesh = "0.2"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }or:
cargo add memmeshuse memmesh::{MemMesh, Subject, Observe, ReflectOpts};
#[tokio::main]
async fn main() -> Result<(), memmesh::Error> {
let mm = MemMesh::new("sk-...", "proj_...");
// Remember something — hand the engine the raw turn and let it extract
// what's worth keeping (returns { saved, candidate_count }).
mm.memory().observe(Observe {
text: Some("Sarah prefers email over phone.".into()),
..Default::default()
}).await?;
// Recall it, semantically
for hit in mm.memory().search("how to reach sarah", 5).await? {
println!("{}", hit.content);
}
// Synthesize higher-order insights, with provenance
let res = mm.memory().reflect(ReflectOpts { max_insights: Some(3), ..Default::default() }).await?;
for i in res.insights { println!("{} ({:.0}%)", i.content, i.confidence * 100.0); }
// Point-in-time knowledge graph
use memmesh::context::GraphQuery;
let edges = mm.context().query_graph(GraphQuery {
as_of: Some("2026-03-01T00:00:00Z".into()), ..Default::default()
}).await?;
let _ = edges;
Ok(())
}mm.memory() (observe/create/search/delete/confirm/reflect/prefetch_related/dedup) ·
mm.lattice() (extract_patterns/mine_memories/get_pattern/list_patterns/get_context/run_monitor_tick/get_monitor_status/predict/predict_target/get_profile/get_cohort/predict_by_cohort/estimate/get_calibration) ·
mm.context() (build/build_for/batch_build/query_graph) ·
mm.events() · mm.alerts() · mm.learning() (record_decision/record_outcome/get_outcomes/get_effectiveness) · mm.behaviors() (discover) · mm.compliance() · mm.health().
Errors are [memmesh::Error] (Http, Decode, Api { status, body }).
Apache-2.0 · memmesh.ai · docs
Observing doesn't only produce embeddable rows — extraction also resolves entities and writes typed edges between them. That graph reaches facts no single memory states outright.
use memmesh::graph::{ListEntities, Traverse};
// How much of what you remember made it into the graph?
let st = mm.graph().stats().await?;
println!("{} entities, {} edges", st.entity_count, st.edge_count);
// Multi-hop: who does Sarah ultimately report to?
let ents = mm.graph().list_entities(ListEntities { search: Some("Sarah".into()), ..Default::default() }).await?;
let chain = mm.graph().traverse(&ents[0].id, Traverse {
hops: Some(2),
predicates: Some(vec!["member_of".into(), "led_by".into()]),
..Default::default()
}).await?;Edges come back hydrated — subject and object are full entities, not ids.
Use stats(), not list_entities(..).len(), for any "how big is it" question:
the list routes page, so their length is the page size, not the total.
Read-only. Entities and edges are written by extraction during observe().