__all__ in
khora/__init__.py. Additive changes land in minor releases; breaking changes require
a major bump. Private imports (khora.engines.*, khora.query.engine,
khora.pipelines.flows) are not stable.
Khora
The primary facade. Delegates to a pluggable engine (default vectorcypher).
KhoraConfig, or nothing, to read
KHORA_DATABASE_URL / KHORA_NEO4J_URL.
run_migrations=True runs Alembic under an advisory lock on connect. Credential fields
are pydantic.SecretStr (rendered as '**********', call .get_secret_value() to read).
await Khora.shared() returns a process-wide, already-connected singleton (created and
connected on first call, reused after). Callers must not disconnect() it: its
lifetime is the process. await Khora.shared.clear() drops the cached instance and is
test-only.
Namespaces
create_namespace is keyword-only, no positional name. Use ns.namespace_id (the
stable public id) everywhere below, not the row-level ns.id. See
Namespaces & isolation.
delete_namespace is the inverse: it cascade-removes the namespace’s documents, chunks,
entities, relationships, graph nodes, and vector rows from every backend, then drops the
namespace row(s) and frees the storage. namespace can be the stable namespace_id or
any version’s row id, and all versions under that stable id go together, whether the
namespace is active or deactivated. Afterwards it no longer lists or resolves, and
recall / stats / forget on it raise ValueError. A cross-backend delete can
partially fail (say the graph backend is unreachable). Rather than raise, the failing
backend is recorded as a degradation on the result and the rest still run, so check
result.partial_failure to catch a half-deleted namespace. It is safe to re-run.
Writing
remember
metadata and the provenance kwargs (source_name, source_type, …) are denormalized
onto chunks and become filterable at recall (see Recall filters).
session_id propagates to the document and its chunks for session-scoped recall and
forget_session.
remember_batch
remember(), and per-doc values override the top-level kwargs.
submit_batch
PENDING, returns immediately. Requires
kb.start_pending_processor() (after connect()) or it raises. await handle.wait()
blocks until every document’s on_result has fired.
Reading
recall
filter= is a deterministic RecallFilter (or its dict
form) applied as a hard predicate alongside the ranking. start_time / end_time are
deprecated in favor of filter={"occurred_at": {...}} and cannot be combined with it.
Fusion weights, reranking, HyDE, and recency are global (KhoraConfig.query /
KHORA_QUERY_*). There’s no config= kwarg. See Retrieval and
Recall filters.
context_text
RecallResult into a flat LLM-context string (chunks grouped by document
title, then --- Entities --- and --- Relationships --- sections).
Entity & document reads
namespace is required on these (accepts str | UUID). Cross-namespace ids resolve
to None / empty rather than leaking the foreign row. The isolation contract holds at
every layer (see Namespaces & isolation). search_entities ranks
entities by embedding similarity to query. On the reads that take include_sources,
pass True to populate each entity’s source-document metadata (an extra lookup, off by
default).
Community reads
list[CommunityNode] (a summary string plus member_ids), the
community summaries the dream phase materializes into the graph.
get_communities lists a namespace’s communities; get_entity_communities returns the
ones a given set of entities belong to. Read-only, and empty on a stack without a graph
backend or without materialized communities.
Deleting
forget_session cascade-deletes every document tagged with session_id (chunks via FK
cascade, graph cleanup via the engine). For TTL cleanup, the opt-in helper
khora.gc.expire_sessions(*, kb, before, namespace_id=None) calls forget_session for
each session whose newest document predates before. Khora runs no scheduler. Call it
from your own loop.
Background processing & health
submit_batch needs the pending processor running: call start_pending_processor()
after connect() on services that write documents (read-only services skip it), and
stop_pending_processor() to cancel the background worker (it can be restarted).
health_check() returns a per-component health dict, or {"status": "disconnected"}
before connect().
Result types
All result types are frozen, slotted dataclasses.RememberResult: document_id, namespace_id, chunks_created,
entities_extracted, relationships_created, relationships_skipped (un-remappable
edges the ingest pipeline dropped, always 0 outside the shared pipeline), metadata,
llm_usage.
BatchResult: total / processed / skipped / failed, chunks / entities
/ relationships, metadata, llm_usage, per_document (one entry per submitted
document in input order, mapping each back to its stored document_id; populated by
VectorCypher, may be empty on other engines).
BatchHandle: batch_id, total, the read-only properties completed / failed
/ is_done, and await handle.wait().
DocumentResult (per-doc on_result payload): document_id, namespace_id,
success, error, per-doc counts, llm_usage, skipped, external_id (the caller’s
Document.external_id, for mapping a result back to its source row).
Stats: documents / chunks / entities / relationships, last_activity_at.
NamespaceDeletionResult (from delete_namespace): namespace_id, removed_row_ids,
the removed counts namespaces_removed / documents_removed / chunks_removed /
vector_rows_removed / graph_nodes_removed, degradations, and the partial_failure
property (True when any backend purge failed).
CommunityNode (from get_communities / get_entity_communities): a materialized
dream community: id, namespace_id, summary, member_ids, summary_depth, and an
optional embedding.
UsageSummary (from khora import UsageSummary): an aggregate over a list of
LLMUsage. Carries total_prompt_tokens, total_completion_tokens, total_tokens,
total_cost_usd, total_latency_ms, and the by_operation / by_model breakdowns.
Build one with UsageSummary.from_usage(result.llm_usage).
RecallResult
Producer invariant: every
chunks[i].document_id and every id in
entities[i].source_document_ids / relationships[i].source_document_ids appears in
documents[]. RecallChunk carries id, document_id, content, score,
created_at, occurred_at, connected_entity_ids, chunker_info.
engine_info["filter"]
On a recall(filter=...), engine_info["filter"] carries a FilterPushdownReport: an
honest account of how the filter was handled. Both it and the per-channel
FilterChannelReport are public (exported from khora).
pushed_keys, post_filtered_keys, and unenforced_keys form a total, disjoint partition
of the filter’s constraint leaves. See Recall filters for
the full filter grammar.
SearchMode
Engines
vectorcypher is the default and the engine these docs cover. Prefer the engine=
argument to Khora(...) over create_engine directly. Custom engines must implement
the full MemoryEngineProtocol. See VectorCypher.
Expertise
ExpertiseConfig (a stable public API) defines a domain ontology, with entity/relationship
types plus a system prompt, correlation rules, and inference rules. See
Expertise & ontologies for the full guide:
Hooks & errors
kb.subscribe(event_type, callback, filter=None) / kb.unsubscribe(id) / kb.hooks.
For delivery that survives a restart, kb.subscribe_persistent(event_type, delivery, *, filter=None, namespace_id=None) / kb.unsubscribe_persistent(id) record a webhook or
queue target to PostgreSQL. See Semantic hooks.
All domain errors subclass KhoraError. Catch it at system boundaries.
Ingestion
What
remember() / remember_batch() / submit_batch() do under the hood.Retrieval
What
recall() does and how to read a RecallResult.