Skip to main content
The examples/30_workloads/ tier is where the Basics and Core APIs come together into applications you’d actually ship. Each is a single runnable file with a heavily commented walkthrough. The summaries below distil what each one teaches and the one call that carries it.
These workloads lean on VectorCypher’s knowledge graph, so they’re best on PostgreSQL + Neo4j (make dev). Pass --config examples/khora.standard.yaml to point at that stack. They also run on the zero-infra embedded backend (pip install "khora[sqlite-lance]" + OPENAI_API_KEY), but entity vectors aren’t indexed there yet, so write-time dedup and some graph reads degrade.
WorkloadTeaches
Support-ticket graphVector search vs. multi-hop graph traversal
Namespace versioningThe dual-UUID model and the storage API
Resume searchFull extraction + cross-document entity resolution

Support-ticket knowledge graph

Ingest ~100 support tickets, then ask two shapes of question. “Tickets about login failures” is a ranked-list problem. Vector search nails it. “Give me context around Acme Logistics” is a neighborhood problem. The answer is Acme’s tickets, the products Acme uses, the agents handling them, the error categories, and other customers on the same products. That’s a 2-hop graph walk, not a similarity search.
batch = await kb.remember_batch(docs, namespace=ns_id,
                                entity_types=["ORGANIZATION", "PRODUCT", "CONCEPT", "PERSON"],
                                relationship_types=["AFFECTS", "ASSIGNED_TO", "RELATES_TO", "MENTIONS"])

# vector shape:
await kb.recall("tickets about login failures", namespace=ns_id, limit=5)

# graph shape — walk outward from the customer entity:
acme = _find_entity(await kb.list_entities(namespace=ns_id, entity_type="ORGANIZATION"), "Acme")
related = await kb.find_related_entities(acme.id, namespace=ns_id, max_depth=2, limit=25)
Takeaway: pick the retrieval shape to match the question. The entity taxonomy is chosen deliberately (customer = ORGANIZATION, SKU = PRODUCT, error category = CONCEPT, agent = PERSON) so the multi-hop walk has real structure to follow.

Namespace versioning

A MemoryNamespace carries two UUIDs: namespace_id is the stable id (same across every version: hold this in your application code), and id is the row primary key, distinct per version. The high-level facade (kb.remember / kb.recall) takes the stable id and resolves to the active version. The storage layer (kb.storage.*) takes a row id to address a specific version.
v1 = await kb.create_namespace()
stable_id, v1_row = v1.namespace_id, v1.id

await kb.remember(text, namespace=stable_id, ...)            # facade → active version

v2 = await kb.storage.create_namespace_version(previous_version=v1)  # atomically flips active
active_row = await kb.storage.resolve_namespace(stable_id)   # stable id → active row id
v1_entities = await kb.storage.list_entities(v1_row)         # read a frozen older version
Takeaway: one version is active at a time. Historical versions are read-only and addressable only through the storage layer by row id. The pattern earns its keep for re-indexing with a better extractor, A/B-testing a chunking change, or snapshotting a graph before re-ingesting. The entity-centric workload where dedup is the story: 50 résumés where “Stripe”, “Stripe Inc.”, “Stripe, Inc.” and “stripe.com” must resolve to one node, and “k8s” / “K8s” / “Kubernetes” to another, before you can answer “Stripe alumni who know Kubernetes.” It runs VectorCypher at full extraction (skeleton_core_ratio=1.0: the documented replacement for the removed graphrag engine) with a domain-specific ExpertiseConfig whose system prompt does the canonicalization.
engine_kwargs = {"vectorcypher_config": VectorCypherConfig(skeleton_core_ratio=1.0,
                                                           min_extraction_tokens=0)}
expertise = ExpertiseConfig(name="recruiter_demo", system_prompt="…canonicalize companies & skills…",
                            entity_types=[...], relationship_types=[...])

batch = await kb.remember_batch(resumes, namespace=ns_id, expertise=expertise, ...)
# then unify_entities collapses surface-form variants, and a two-set graph
# intersection answers "Stripe alumni ∩ Kubernetes users"
Takeaway: pick full extraction when every chunk is dense (résumés have no filler) and cross-document resolution matters. The ExpertiseConfig system prompt is the stable API for taxonomies. Defaults to PostgreSQL + Neo4j. The embedded backend has no entity-vector index, so similarity dedup can’t catch variants the LLM didn’t already collapse.

Next steps

extension

Integrations

Wire these patterns into CrewAI, LangGraph, Google ADK, OpenAI Agents, or LlamaIndex.
settings_input_component

VectorCypher

How the engine fuses vector, graph, and keyword search behind these examples.