harness-rs-cortexdb 0.0.61

CortexDB-backed Memory for harness-rs: implements the harness-core Memory trait over CortexDB's MCP server or its native gRPC protocol (memory_save / memory_search), giving any harness agent semantic recall + a shared knowledge brain. Optional.
Documentation

harness-cortexdb — CortexDB as a harness Memory

Implements [harness_core::Memory] over CortexDB's MCP server: recall calls memory_search (semantic / lexical vector retrieval) and write calls memory_save. Drop it in anywhere a Memory is expected — the MemoryGuide, the experience layer (harness-experience), a scheduler, etc. — to get semantic recall and a brain that can be shared with other tools (Claude Code / Codex all use ~/.cortexdb by default).

use harness_cortexdb::CortexdbMemory;
use std::sync::Arc;

// Spawn CortexDB's MCP server; share the global brain (~/.cortexdb).
let mem = Arc::new(CortexdbMemory::connect_stdio("cortexdb-mcp-stdio", &[]).await?);
let recorder = harness_loop::experience::ExperienceRecorder::new(mem); // semantic!

The memory does not have to be a process this agent spawns. Point it at a CortexDB that is already running — one brain shared by a fleet of agents, an editor and a chat client, and highly available in the ordinary way. Which constructor depends on what that CortexDB serves, and the two look alike written down:

// An MCP server reachable over Streamable HTTP:
let mem = Arc::new(CortexdbMemory::connect_http("https://cortex.internal/mcp").await?);

// CortexDB's own gRPC API — what the openclaw sidecar runs, on :47821.
// Requires the `grpc` feature; see `grpc::CortexdbGrpcMemory`.
let mem = Arc::new(CortexdbGrpcMemory::connect("http://127.0.0.1:47821").await?);

Harness MemoryEntry fields round-trip through CortexDB: content maps to the memory content; tags + source are stored under CortexDB's metadata and read back on recall.

Record conversations, then distill them into the graph

Pair the TranscriptRecorder hook (turns → CortexDB) with periodic [CortexdbMemory::consolidate] (memories → knowledge graph, server-side):

let mem = Arc::new(CortexdbMemory::connect_stdio("cortexdb-mcp-stdio", &[]).await?
    .with_scope("session").with_namespace("myapp-chat"));

// 1. capture every turn as it happens
let (recorder, rx) = harness_loop::experience::TranscriptRecorder::new("sess-1");
harness_loop::experience::spawn_transcript_writer(rx, mem.clone());
let loop_ = AgentLoop::new(model).with_hook(Arc::new(recorder));

// 2. every 10 min, let CortexDB distill accumulated turns into the graph
let m = mem.clone();
tokio::spawn(async move {
    let mut tick = tokio::time::interval(std::time::Duration::from_secs(600));
    loop { tick.tick().await; let _ = m.consolidate(serde_json::Value::Null).await; }
});