--- name: cortexdb-memory-hermes description: Give a Python agent (such as Hermes Agent by Nous Research) durable, local-first memory plus a queryable SPARQL knowledge graph, backed by CortexDB through its gRPC sidecar and the cortexdb-client PyPI package. Use when a Python agent needs to remember facts about a user across turns/sessions, recall them by meaning, store entities and relations, or answer multi-hop questions — and when the user mentions CortexDB, agent memory, long-term memory, RAG, knowledge graph, Hermes, or "remember this". license: MIT compatibility: Requires Python 3.9+, pip, and the cortexdb-grpc sidecar binary (Go install or prebuilt release). Optional embeddings via any OpenAI-compatible endpoint (e.g. Ollama). metadata: {"author": "liliang-cn", "project": "cortexdb", "version": "1.0"} --- # CortexDB memory for a Python agent (Hermes) Wire CortexDB in as the memory layer for a Python agent. CortexDB is a pure-Go, single-file database; the Python agent talks to it over gRPC via the `cortexdb-client` package. Beyond vector/lexical recall, it gives the agent a real **knowledge graph** (RDF + SPARQL) — the thing most agent-memory layers lack. ## When to use this - The agent should remember user facts/preferences across turns or sessions. - The agent should recall memories by meaning, not exact match. - The agent needs entities + relations and multi-hop questions ("who, among the people Alice knows, works on X"). - You're integrating with Hermes Agent (or any Python agent/framework). ## Step 1 — Run the sidecar (once) CortexDB runs as a local sidecar process, owning one SQLite file. ```bash # install the binary (or download a prebuilt release) go install github.com/liliang-cn/cortexdb/v2/cmd/cortexdb-grpc@latest # lexical mode — zero config, no API key: CORTEXDB_PATH=agent.db CORTEXDB_GRPC_TOKEN=s3cret cortexdb-grpc # → listening on 127.0.0.1:47821 ``` To enable vector/semantic recall, point it at any OpenAI-compatible embeddings endpoint (e.g. a local Ollama): ```bash OPENAI_BASE_URL=http://localhost:11434/v1 \ CORTEXDB_EMBED_MODEL=embeddinggemma CORTEXDB_EMBED_DIM=768 \ CORTEXDB_PATH=agent.db CORTEXDB_GRPC_TOKEN=s3cret cortexdb-grpc ``` ## Step 2 — Install the client ```bash pip install cortexdb-client # or: uv add cortexdb-client ``` ## Step 3 — The two core moves: remember + recall ```python from cortexdb_client import CortexClient, proto client = CortexClient.connect("127.0.0.1:47821", token="s3cret") # remember a fact about the user (scoped per user) client.memory.SaveMemory(proto.SaveMemoryRequest( memory_id="pref-coffee", user_id="alice", scope="user", content="Alice prefers dark roast coffee and dislikes heavy frameworks.", )) # later turn / next session: recall by meaning hits = client.memory.SearchMemory(proto.SearchMemoryRequest( query="what does the user like to drink?", user_id="alice", scope="user", top_k=3, )) for h in hits.results: print(h.memory.content, h.score) ``` **Memory scopes** isolate data: `scope="user"` (per `user_id`), `scope="session"` (per `session_id`), or `scope="global"`. Use `user` for durable preferences and `session` for short-lived conversation state. ## Step 4 — Knowledge instead of plain memory (RAG) For documents the agent should retrieve from (not just per-user notes), use the knowledge service — it chunks, indexes, and (with an embedder) does GraphRAG: ```python client.knowledge.SaveKnowledge(proto.SaveKnowledgeRequest( knowledge_id="doc-1", title="Project brief", content="The user is building an autonomous research agent in Python.", )) res = client.knowledge.SearchKnowledge(proto.SearchKnowledgeRequest( query="what is the user building?", top_k=3, )) ``` ## Step 5 — The differentiator: a knowledge graph Store entities and relations, then traverse them with SPARQL. This is what makes CortexDB more than a vector store for an agent. ```python iri = lambda v: proto.RdfTerm(kind="iri", value=v) client.graph.UpsertNamespace(proto.UpsertNamespaceRequest( prefix="ex", uri="https://example.com/")) client.graph.UpsertKnowledgeGraph(proto.UpsertKnowledgeGraphRequest(triples=[ proto.RdfTriple(subject=iri("ex:alice"), predicate=iri("ex:knows"), object=iri("ex:bob")), ])) ans = client.graph.QuerySparql(proto.QuerySparqlRequest( query="SELECT ?o WHERE { ?o . }")) print(ans.result.count, "result(s)") ``` ## Expose CortexDB as Hermes tools Hermes runs Python and dispatches tools/subagents. Wrap the calls above as small tool functions the agent can call — `remember(text)`, `recall(query)`, `relate(from, rel, to)`, `ask_graph(sparql)`. Each is a 3-line wrapper over the client. A ready-to-import module is provided: - `scripts/memory_tools.py` — `remember`, `recall`, `save_knowledge`, `search_knowledge`, `relate`, `ask_graph`, plus unified `recall_context` and `remember_context`, returning plain dicts/strings that drop straight into a tool-calling loop. For automatic pre-turn recall and completed-turn synchronization, install the native Hermes `MemoryProvider` at `plugins/hermes-cortexdb-memory` and set `memory.provider: cortexdb`. A skill or MCP server exposes tools but does not by itself participate in Hermes' native memory lifecycle. ## Install this skill into Hermes Hermes adopts the agentskills.io standard; skills live under `~/.hermes/skills/` and activate as `/skill-name`. ```bash # from a URL to this SKILL.md, or a local checkout: hermes skills install https://raw.githubusercontent.com/liliang-cn/cortexdb/main/skills/cortexdb-memory-hermes/SKILL.md --name cortexdb-memory-hermes # or point Hermes at a directory of skills via ~/.hermes/config.yaml: # skills: # external_dirs: # - /path/to/cortexdb/skills ``` Then in a Hermes session: `/cortexdb-memory-hermes`. Hermes also speaks MCP — if you prefer, run `cortexdb-mcp-stdio` and connect it as an MCP server instead of (or alongside) this skill. ## Sub-clients (full surface) `client.knowledge`, `client.memory`, `client.graph` (RDF/SPARQL/SHACL/inference/ ontology), `client.graphrag`, `client.tools` (generic dispatch, same shape as MCP), `client.admin`. Every RPC takes a `proto.Request` and returns the response message. Auth is a bearer token; pass `token=` to `connect`. ## Notes & gotchas - **Zero-key default**: without an embedder the sidecar uses lexical retrieval — good enough to start, no credentials needed. - **One file, one process**: the sidecar owns one SQLite file. Isolate multiple users via memory scopes (above), not multiple files. - **Plaintext localhost**: the bearer token rides plain gRPC; fine on localhost, add TLS / a reverse proxy for cross-machine use. - Package and docs: https://pypi.org/project/cortexdb-client/ · https://github.com/liliang-cn/cortexdb