Rust SDK

Install, initialize, and use the ConvoMem Rust SDK.

The ConvoMem Rust SDK is async-first, built on tokio and reqwest.

Install

cargo add convomem

Or add to Cargo.toml:

[dependencies]
convomem = "0.1"
tokio = { version = "1", features = ["full"] }

Initialize

use convomem::ConvoMem;
 
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = ConvoMem::new(std::env::var("CONVOMEM_API_KEY")?);
    Ok(())
}

With a custom timeout:

use convomem::ConvoMem;
use std::time::Duration;
 
let client = ConvoMem::builder()
    .api_key(std::env::var("CONVOMEM_API_KEY")?)
    .timeout(Duration::from_secs(15))
    .build()?;

Identity

CustomerIdentity routes every call to the right customer. When customer_id is set the SDK uses the direct /customers/:id/… path. Otherwise the server resolves the customer from email, phone, or external_id.

use convomem::CustomerIdentity;
 
// By known ID — most direct
let identity = CustomerIdentity::from_id("cust_uuid_123");
 
// By email — server resolves the customer
let identity = CustomerIdentity::from_email("[email protected]");
 
// By phone (E.164 format recommended)
let identity = CustomerIdentity::from_phone("+14155550100");
 
// By external system ID
let identity = CustomerIdentity::from_external_id("crm-456");

Capture

Send conversation turns for background memory extraction. Fire-and-forget — memories become searchable within seconds.

use convomem::{ConvoMem, CustomerIdentity, Message};
 
client.capture(
    vec![
        Message { role: "user".into(),      content: "I need help with my order".into() },
        Message { role: "assistant".into(), content: "Of course, let me look that up.".into() },
    ],
    &CustomerIdentity::from_email("[email protected]"),
    Some("CHAT"),   // channel
    None,           // user_name
    None,           // idempotency_key
).await?;

Look up context

Recall semantically relevant memories before generating a reply.

let ctx = client.lookup(
    "order and shipping preferences",
    &CustomerIdentity::from_email("[email protected]"),
    None,   // auto_create
    None,   // user_name
).await?;
 
println!("Context: {}", ctx.context);
for mem in &ctx.memories {
    println!("  - {:?}", mem.content);
}

Agent loop pattern

use convomem::{ConvoMem, CustomerIdentity, Message};
 
let client = ConvoMem::new(std::env::var("CONVOMEM_API_KEY")?);
 
async fn handle_message(
    client: &ConvoMem,
    user_msg: &str,
    email: &str,
) -> Result<String, Box<dyn std::error::Error>> {
    let identity = CustomerIdentity::from_email(email);
 
    // 1. Recall context
    let ctx = client.lookup("customer support", &identity, None, None).await?;
 
    // 2. Call your LLM (pseudo-code)
    let reply = call_llm(&ctx.context, user_msg).await;
 
    // 3. Capture the turns
    client.capture(
        vec![
            Message { role: "user".into(),      content: user_msg.into() },
            Message { role: "assistant".into(), content: reply.clone() },
        ],
        &identity,
        Some("CHAT"),
        None,
        None,
    ).await?;
 
    Ok(reply)
}

Memories

use convomem::{CustomerIdentity, MemoryAddRequest};
 
let identity = CustomerIdentity::from_id("cust_uuid_123");
 
// List all memories
let result = client.list_memories(&identity, None, None, None).await?;
for mem in &result.memories {
    println!("- {:?}", mem.content);
}
 
// Add manually
let memory = client.add_memory(
    "Prefers email contact",
    &identity,
    Some("preference"),
).await?;
 
// Update (requires customer_id)
let updated = client.update_memory(
    "mem_uuid_456",
    &identity,
    Some("Prefers email and text contact"),
    None,
).await?;
 
// Delete (requires customer_id)
client.delete_memory("mem_uuid_456", &identity).await?;

Customers

use convomem::{CustomerCreateRequest, CustomerIdentity, CustomerUpdateRequest};
 
// Create
let customer = client.create_customer(&CustomerCreateRequest {
    name: Some("Alice".into()),
    email: Some("[email protected]".into()),
    ..Default::default()
}).await?;
 
// Get — by ID (direct) or by identity (server resolves)
let customer = client.get_customer(
    &CustomerIdentity::from_email("[email protected]")
).await?;
println!("Customer ID: {}", customer.id);
 
// Update
let updated = client.update_customer(
    &CustomerIdentity::from_id("cust_uuid_123"),
    &CustomerUpdateRequest {
        name: Some("Alice Smith".into()),
        ..Default::default()
    },
).await?;
 
// List
let result = client.list_customers(Some(1), Some(20), None).await?;
println!("{} of {}", result.customers.len(), result.total);
 
// Stats
let stats = client.get_stats().await?;
println!("Total customers: {}", stats.total_customers);
println!("Total memories:  {}", stats.total_memories);
 
// Delete
client.delete_customer(&CustomerIdentity::from_id("cust_uuid_123")).await?;

Conversations

use convomem::CustomerIdentity;
 
let identity = CustomerIdentity::from_id("cust_uuid_123");
 
// Start
let conversation = client.start_conversation(&identity, "CHAT").await?;
println!("Conversation: {}", conversation.id);
 
// List
let result = client.list_conversations(&identity, None, None, None).await?;
 
// End — path-based when both IDs are known
client.end_conversation(
    Some("conv_uuid_456"),
    &identity,
    Some("Resolved billing issue"),
).await?;
 
// End — flat route when only identity is known
client.end_conversation(
    None,
    &CustomerIdentity::from_email("[email protected]"),
    Some("Resolved"),
).await?;
 
// Escalate
client.escalate_conversation(
    Some("conv_uuid_456"),
    &identity,
    Some("Complex billing dispute"),
).await?;

Handoff

Generate a briefing for the human agent taking over the conversation.

use convomem::CustomerIdentity;
 
let handoff = client.get_handoff(
    &CustomerIdentity::from_email("[email protected]"),
    None,   // fresh
    None,   // narrative
).await?;
 
if handoff.found {
    if let Some(narrative) = &handoff.narrative {
        println!("Narrative: {}", narrative);
    }
    for mem in &handoff.key_memories {
        println!("  - {}", mem.content);
    }
}

Embed tokens

use convomem::CustomerIdentity;
 
let result = client.create_embed_token(
    &CustomerIdentity::from_id("cust_uuid_123"),
    Some(3600),  // ttl_seconds
).await?;
 
println!("Token: {}", result.token);
println!("Expires in: {}s", result.expires_in);

Error handling

use convomem::ConvoMemError;
 
match client.get_customer(&CustomerIdentity::from_id("cust_uuid_123")).await {
    Ok(customer) => println!("Found: {}", customer.id),
    Err(ConvoMemError::Api { status, message }) => {
        println!("API error {}: {}", status, message);
    }
    Err(e) => println!("Other error: {}", e),
}

Low-level resource client

For advanced use cases you can use ConvoMemClient directly:

use convomem::{ConvoMemClient, CaptureRequest, Message};
 
let client = ConvoMemClient::new(std::env::var("CONVOMEM_API_KEY")?);
 
let result = client.capture(&CaptureRequest {
    messages: Some(vec![
        Message { role: "user".into(), content: "Hello".into() },
    ]),
    email: Some("[email protected]".into()),
    ..Default::default()
}).await?;

Other SDKs