khive-runtime
Composable Service API used by khive's daemon, MCP server, and CLI: entity/note CRUD,
graph traversal, hybrid search, and curation, plus the pack registration and
verb-dispatch machinery that lets packs (kg, gtd, memory, …) extend the surface.
Features
KhiveRuntime— a cloneable handle wrapping akhive-db::StorageBackendwith namespace-scoped accessors for every storage capability, plus a lazily-configured embedder registryVerbRegistry/VerbRegistryBuilder— registers packs (PackRuntimeimpls), an authorizationGate, an actor identity, and dispatches verbs by namePackRuntimetrait — the object-safe runtime counterpart tokhive-types::Pack; every pack declares handlers, owned entity/note kinds, edge-endpoint extensions, and an optional auxiliarySchemaPlan- Curation (
EntityPatch,NotePatch,EdgePatch,MergeSummary,EntityDedupMergePolicy) — update/merge semantics per ADR-014 - Retrieval objectives (
RrfFusionObjective,VectorSimilarityObjective,TextRelevanceObjective,TemporalRecencyObjective,DecayAwareSalienceObjective, …) composed into aMemoryRecallPipeline - Graph traversal (
PathNode) and validation (ValidationRule,ValidationReport,Violation) for domain-specific graph-shape rules - Daemon (unix only) —
run_daemon, socket/pid path helpers, and the request/response frame types for the persistentkkernel mcp --daemonprocess
Usage
use ;
use Namespace;
// In-memory runtime (tests); production callers set RuntimeConfig::db_path or
// use KhiveRuntime::from_backend with a pre-built StorageBackend.
let runtime = new?;
// Every read/write is scoped by a NamespaceToken minted through the configured Gate.
let token = runtime.authorize?;
let entities = runtime.entities?; // Arc<dyn khive_storage::EntityStore>
let graph = runtime.graph?; // Arc<dyn khive_storage::GraphStore>
Packs are composed through the builder, not KhiveRuntime directly:
use ;
use Arc;
let mut builder = new;
builder
.with_gate
.with_default_namespace;
// .register(KgPack::new(...)) // any Pack + PackRuntime impl
let registry = builder.build?;
let result = registry
.dispatch
.await?;
Architecture
KhiveRuntime::new(RuntimeConfig)
│
StorageBackend (khive-db)
│
┌──────────────────┼──────────────────────┐
authorize(ns) entities/graph/notes/… embedder(name)
│ (khive-storage traits) (lattice-embed)
▼
NamespaceToken ──── VerbRegistryBuilder::register(pack) × N
│
VerbRegistryBuilder::build()
│
VerbRegistry::dispatch(verb, params)
│ │
Gate::check first pack whose handlers() match verb
(authoritative
Deny; errors
fail open)
dispatch short-circuits to describe_verb when params["help"] == true, otherwise
resolves the request namespace (explicit namespace arg, else the registry default),
checks the Gate, and routes to the first registered pack whose HandlerDefs cover
the verb. KhiveRuntime::authorize mints a NamespaceToken whose read-visibility set
defaults to [ns]; authorize_with_visibility widens it for callers that read across
namespaces (e.g. an agent reading both its own and a shared namespace) while writes
stay pinned to the primary.
Where this sits
khive-runtime sits directly above khive-db/khive-query/khive-gate/khive-fusion
and below every pack crate:
types -> score -> storage -> db -> query -> runtime -> pack-kg / pack-gtd / … -> mcp
It re-exports the khive-db and khive-gate types packs need
(StorageBackend, ConnectionPool, Gate, GateDecision, ActorRef, …) so most
pack crates depend on khive-runtime alone rather than reaching past it. Governing
ADRs: pack contract and object-safe dispatch
(ADR-017),
verb surface, visibility and composition
(ADR-023),
dynamic pack loading via self-registration
(ADR-027),
pack-scoped backends and per-pack schema
(ADR-028),
and the authorization gate
(ADR-018).
License
Apache-2.0.