dakera-client 0.11.100

Rust client SDK for Dakera AI Agent Memory Platform
Documentation
//! Dakera Rust SDK — Playground Quickstart
//!
//! Demonstrates the 4 core memory operations against the Dakera Playground.
//!
//! Run:
//!   cargo run --example playground

use dakera_client::{DakeraClient, EdgeType, MemoryType, RecallRequest, StoreMemoryRequest};

const AGENT_ID: &str = "playground-agent";
const DEFAULT_URL: &str = "https://5-75-177-31.sslip.io";
const DEFAULT_KEY: &str = "playground-demo";

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let url = std::env::var("DAKERA_API_URL").unwrap_or_else(|_| DEFAULT_URL.to_string());
    let api_key = std::env::var("DAKERA_API_KEY").unwrap_or_else(|_| DEFAULT_KEY.to_string());

    // Generate a unique session ID so the sandbox proxy can isolate this run's
    // memories from other concurrent playground sessions (DAK-6806).
    // Uses nanosecond wall-clock time as a lightweight uniqueness source.
    let session_id = format!(
        "pg_{:x}",
        std::time::SystemTime::now()
            .duration_since(std::time::UNIX_EPOCH)
            .map(|d| d.as_nanos())
            .unwrap_or(0)
    );

    let client = DakeraClient::builder(&url)
        .api_key(&api_key)
        .header("X-Playground-Session", &session_id)
        .build()?;

    let health = client.health().await?;
    println!(
        "Playground: {} (healthy: {})",
        health.version.as_deref().unwrap_or("unknown"),
        health.healthy
    );

    // -------------------------------------------------------------------------
    // 1. Store memories
    // -------------------------------------------------------------------------
    println!("\n--- 1. Store Memories ---");

    let mem1 = client
        .store_memory(
            StoreMemoryRequest::new(
                AGENT_ID,
                "Dakera provides persistent, decay-weighted memory for AI agents.",
            )
            .with_type(MemoryType::Semantic)
            .with_importance(0.9)
            .with_tags(vec!["dakera".into(), "memory".into(), "overview".into()]),
        )
        .await?;
    println!("Stored: {}", mem1.memory_id);

    let mem2 = client
        .store_memory(
            StoreMemoryRequest::new(
                AGENT_ID,
                "The recall API returns semantically similar memories ranked by relevance.",
            )
            .with_type(MemoryType::Semantic)
            .with_importance(0.8)
            .with_tags(vec!["dakera".into(), "recall".into(), "api".into()]),
        )
        .await?;
    println!("Stored: {}", mem2.memory_id);

    let mem3 = client
        .store_memory(
            StoreMemoryRequest::new(
                AGENT_ID,
                "Session scoping lets agents isolate memories per task or conversation.",
            )
            .with_type(MemoryType::Episodic)
            .with_importance(0.7)
            .with_tags(vec!["sessions".into(), "isolation".into()]),
        )
        .await?;
    println!("Stored: {}", mem3.memory_id);

    // -------------------------------------------------------------------------
    // 2. Recall by query (semantic search)
    // -------------------------------------------------------------------------
    println!("\n--- 2. Recall by Query ---");

    let recalled = client
        .recall(RecallRequest::new(AGENT_ID, "How does Dakera memory work?").with_top_k(5))
        .await?;
    println!("Recalled {} memories:", recalled.memories.len());
    for m in &recalled.memories {
        let preview: String = m.content.chars().take(80).collect();
        println!("  [{:.3}] {}", m.importance, preview);
    }

    // -------------------------------------------------------------------------
    // 3. Search with filters (type=semantic)
    // -------------------------------------------------------------------------
    println!("\n--- 3. Search with Filters ---");

    let filtered = client
        .search_memories(
            RecallRequest::new(AGENT_ID, "memory API")
                .with_top_k(3)
                .with_type(MemoryType::Semantic),
        )
        .await?;
    println!("Filtered search ({} results):", filtered.memories.len());
    for m in &filtered.memories {
        let preview: String = m.content.chars().take(80).collect();
        println!("  [{:.3}] {}", m.importance, preview);
    }

    // -------------------------------------------------------------------------
    // 4. Knowledge graph link
    // Note: requires a full Dakera account; not available on the public sandbox.
    // -------------------------------------------------------------------------
    println!("\n--- 4. Knowledge Graph Link ---");

    match client
        .memory_link(&mem1.memory_id, &mem2.memory_id, EdgeType::RelatedTo)
        .await
    {
        Ok(link) => println!(
            "Linked {}{}: edge_type={:?}",
            mem1.memory_id, mem2.memory_id, link.edge.edge_type
        ),
        Err(e) => {
            println!("KG link not available in sandbox: {e}");
            println!("  Sign up at https://dakera.ai for full knowledge graph access.");
        }
    }

    println!("\nPlayground quickstart complete! Visit https://dakera.ai to learn more.");
    Ok(())
}