Graph model: spaces, items & provenance
The Kumiho data model — projects, spaces, items, revisions, artifacts, bundles, edges, krefs, and trust.
Everything Revka remembers lives in Kumiho, a graph-native cognitive memory backend. Kumiho is not a flat key-value store: memories are items inside hierarchical spaces, each item carries a chain of immutable revisions, and items are connected by typed edges that encode provenance. This page is the reference for that data model — the project/space/item/revision/artifact/bundle hierarchy, the kref addressing scheme, the edge and capture types Revka uses, the AgentTrust space, and the client surfaces (the SDK bridge and KumihoClient) that read and write all of it.
Read this page when you need to understand how memories are shaped on disk — for example when navigating the dashboard’s Memory Auditor, writing through the Asset Browser, or interpreting a kref. For the agent-side usage pattern (engage before responding, reflect after), see Kumiho graph memory and Kumiho memory tools. For the runtime split between NoneMemory and Kumiho, start at Memory overview.
The hierarchy
Section titled “The hierarchy”Kumiho’s object model nests from coarse to fine:
project (e.g. CognitiveMemory, Revka) └─ space (hierarchical path, e.g. Revka/AgentPool) └─ item (a named node — one decision, agent, skill, …) └─ revision (immutable version; revisions never mutate, they append) └─ artifact (file/blob attached to a revision, e.g. SKILL.md)Two cross-cutting object types span the tree:
- Bundles — items whose purpose is to group other items by membership (a team groups its agent members; a session groups its captures).
- Edges — typed, directed relationships between items that encode provenance and dependency.
| Object | What it is | Key fields |
|---|---|---|
| Project | Top-level namespace. Revka uses two by default: CognitiveMemory (user memories, sessions, compactions) and Revka (skills and operational data). | name, description, deprecated, created_at, metadata |
| Space | A hierarchical path within a project that organizes items, e.g. Revka/AgentPool. Spaces nest under a parent_path. | path, name, parent_path, created_at |
| Item | A named node — one decision, fact, agent, skill, etc. Identified by a kref and a slugified item_name. Has a kind (the capture type). | kref, name, item_name, kind, deprecated, metadata |
| Revision | An immutable version of an item. New writes append a revision with an incrementing number; the latest is flagged latest: true. Revisions carry tags (e.g. published). | kref, item_kref, number, latest, tags, metadata |
| Artifact | A file or blob (e.g. SKILL.md, a PNG) attached to a revision, with a location URI pointing at where the bytes live. | kref, name, location, revision_kref, item_kref, metadata |
| Bundle | A grouping item whose members are other item krefs linked by CONTAINS-style membership. Teams and sessions are bundles. | bundle kref + members[] (item_kref, added_at, added_in_revision) |
| Edge | A typed directed relationship between two items. | source_kref, target_kref, edge_type, metadata |
krefs — addressing the graph
Section titled “krefs — addressing the graph”A kref (Kumiho reference) is the URI that addresses any object in the graph. The base form names the item by project, space path, and slugified name with a kind suffix:
kref://CognitiveMemory/Skills/creative-memory.skillSelectors are appended as query parameters to pin a specific revision or artifact:
kref://CognitiveMemory/Skills/creative-memory.skill?r=2 # revision 2kref://CognitiveMemory/Skills/creative-memory.skill?r=2&a=SKILL.md # artifact within revision 2r=N— pin to revision numberN. Omit it to address the item itself (callers then resolvelatestor a tag).a=NAME— pin to a named artifact within that revision.
When you pass a kref that carries selectors to an item-level operation (deprecate, lookup), Revka strips the ?… suffix down to the bare item kref automatically, so …creative-memory.skill?r=2&a=SKILL.md and …creative-memory.skill resolve to the same item. Names are slugified to be kref-safe: lowercased, non-alphanumeric runs collapsed to single hyphens ("Chose gRPC over REST" → chose-grpc-over-rest).
To resolve a kref to concrete identifiers or fetch the addressed object, use the kumiho_resolve_kref and kumiho_get_item MCP tools, or fetch a tagged revision with kumiho_get_revision_by_tag (default tag published).
The Revka space hierarchy
Section titled “The Revka space hierarchy”Revka scopes its own memory under the Revka/… prefix (configurable via [kumiho] space_prefix), while the CognitiveMemory/… tree holds user memories and cross-agent shared knowledge. The spaces Revka relies on by convention:
| Space | Purpose |
|---|---|
Revka/AgentPool | Per-agent state — identity, expertise, tone, allowed-tool list. |
Revka/Plans/<project> | Plans the Operator decomposed for a project. |
Revka/Sessions | Active and historical chat sessions. |
Revka/Goals | Long-running goals an agent is working toward. |
Revka/AgentTrust | Per-agent-template trust scores and recent-outcome buffer. |
Revka/ClawHub | Marketplace catalog state (skills, agents, workflows). |
Revka/Teams | Team composition and delegation topology. |
Revka/WorkflowRuns | Operator workflow run state and history. |
Revka/Outcomes | Per-run outcomes feeding the trust-score calculation. |
CognitiveMemory/Skills | Shared skill library (cross-agent procedures). |
The project names come from [kumiho] config: memory_project defaults to CognitiveMemory, harness_project to Revka. See Kumiho setup for the full config block.
Capture types (item kinds)
Section titled “Capture types (item kinds)”When an agent stores a memory via kumiho_memory_reflect, each capture gets a type — which becomes the item’s kind. The type drives retrieval ranking and DreamState consolidation behavior. Revka uses ten:
| Type | When to use | Example title |
|---|---|---|
decision | A choice with a rationale that should bind future agents. | ”Chose Axum over Actix on Mar 14” |
preference | Stable user/operator preference. | ”User wants tests run before commits” |
fact | Verified fact about the world or the system. | ”Daemon binds 0.0.0.0:42617 in network mode” |
correction | Overrides a prior memory that proved wrong. | ”Operator does NOT auto-restart on panic (correction)“ |
architecture | High-level structural choice or constraint. | ”Operator/Rust split per ADR-005 on Apr 18” |
implementation | Concrete how-it-works knowledge. | ”Skill kref resolution flow on Apr 20” |
synthesis | Aggregated insight derived from multiple sources. | ”Q1 channel error patterns rolled up Apr 27” |
reflection | Post-mortem or lesson learned. | ”Postmortem: stash overlap on Apr 27” |
summary | Compacted session or thread summary. | ”Apr 27 docs-restructure session summary” |
skill | A reusable procedure to be discovered later. | ”creative-memory” |
Provenance edges
Section titled “Provenance edges”Provenance is what separates a graph memory from a flat note. Revka uses six edge types:
| Edge type | Meaning | How it’s created |
|---|---|---|
DERIVED_FROM | The new capture was derived from each source. | Implied automatically when you pass source_krefs to kumiho_memory_reflect. |
DEPENDS_ON | Step/item B cannot start until A completes. | Set explicitly via kumiho_create_edge. |
REFERENCED | Soft pointer — one memory mentions another without depending on it. | kumiho_create_edge, or inferred. |
CONTAINS | Bundle/membership — a session contains its captures. | Bundle membership. |
CREATED_FROM | One item is a forked or transformed version of another. | kumiho_create_edge. |
BELONGS_TO | Ownership/scope — ties an artifact to a project, workflow run, or agent. | kumiho_create_edge. |
The recommended pattern: let discover_edges: true on reflect (the default) infer edges via the server-side LLM. Create edges manually only when you hold semantic information the LLM cannot infer — DEPENDS_ON ordering is the typical case. To inspect edges, use kumiho_get_edges, or open the Memory Auditor’s force-graph.
The AgentTrust space
Section titled “The AgentTrust space”Revka/AgentTrust holds a rolling reputation signal per agent template. Each item lives at /<harness>/AgentTrust/<template> (so the project is harness_project, default Revka), and its revision metadata carries:
trust_score— recency-weighted mean success ratio, rounded to 3 decimals.total_runs— count of recorded outcomes.total_score— running sum of per-run score weights.recent_outcomes— a ring buffer of the last 10 outcomes, eachoutcome:summary:timestamp.last_run,template_name, optionallast_agent_id.
Outcomes fold into the score with fixed weights: success = 1.0, partial = 0.5, failed = 0.0 (any unrecognized label is treated as partial). The score is the mean of those weights across runs (total_score / total_runs).
Trust is recorded as a side effect: call record_agent_outcome with both template_name and status (after wait_for_agent) and the outcomes handler updates trust inline — there is no separate “record trust” tool. Trust is read via the get_agent_trust tool, which returns templates sorted by descending trust_score. Orchestration patterns consume it — refinement_loop auto-switches critics when a template’s trust drops below 0.7. Trust-update failures are non-fatal: a failed write logs a warning but does not fail the underlying outcome record.
See Agents, teams & swarms and Spawning & coordinating agents for how trust feeds multi-agent orchestration.
How Revka reads and writes the graph
Section titled “How Revka reads and writes the graph”Revka reaches Kumiho through two transports, both transparent to you.
Kumiho SDK bridge
Section titled “Kumiho SDK bridge”The SDK bridge is a process-local Python HTTP sidecar that exposes the Kumiho Python SDK over loopback, bypassing the hosted FastAPI for lower-latency reads. KumihoClient uses it as the primary transport and falls back to FastAPI when it is unavailable.
- Enabled by default. Disable by setting
REVKA_KUMIHO_SDK_BRIDGE=0(alsofalse/no/off). - The bridge script
kumiho_sdk_bridge.pyis materialized from an embedded resource to~/.revka/kumiho/kumiho_sdk_bridge.pyon first use, and listens on127.0.0.1:<ephemeral-port>. - It requires the Kumiho Python venv at
~/.revka/kumiho/venv/. If the venv is absent, the bridge fails to start and all requests fall back to hosted FastAPI (graceful). - Timeouts: 10 s health check on startup, 10 s per request. The process is restarted automatically if it exits.
- Logs:
~/.revka/logs/kumiho-sdk-bridge.stdout.logand…stderr.log.
Fallbacks to FastAPI also trigger on HTTP 501 responses with error_code: "kumiho_sdk_bridge_unsupported" and on server-side 5xx from the bridge. The transport that served a given request is reported on the Kumiho proxy response via the X-Revka-Kumiho-Transport: sdk-bridge | fastapi header.
KumihoClient CRUD surface
Section titled “KumihoClient CRUD surface”KumihoClient wraps the full Kumiho REST API and is used by gateway routes, CLI commands, and the memory-graph endpoint. The methods, grouped by object type:
| Object | Methods |
|---|---|
| Projects | create_project, ensure_project |
| Spaces | create_space, ensure_space, ensure_child_space, list_spaces |
| Items | create_item, list_items, list_items_paged, list_items_filtered, get_item_by_kref, search_items, deprecate_item, delete_item |
| Revisions | create_revision, get_latest_revision, get_revision, get_revision_by_tag, list_item_revisions, tag_revision, untag_revision, deprecate_revision, batch_get_revisions |
| Artifacts | create_artifact, get_artifacts, get_artifacts_by_location, get_artifact_by_name |
| Bundles | create_bundle, get_bundle, delete_bundle, add_bundle_member, remove_bundle_member, list_bundle_members |
| Edges | create_edge, list_edges, delete_edge |
| Skills | create_skill, list_skills, search_skills, deprecate_skill |
Behavior worth knowing:
- Auth. The FastAPI transport sends
X-Kumiho-TokenfromKUMIHO_SERVICE_TOKEN; the bridge usesKUMIHO_AUTH_TOKEN. They can differ.KUMIHO_SERVICE_TOKENfalls back toKUMIHO_AUTH_TOKENwhen unset. - Retries. GET requests retry (3 attempts, jittered 500 ms / 1500 ms backoff, on HTTP 502/503/504/520/522/524, 15 s total budget). Writes (POST/PUT/DELETE) are never retried — Kumiho has no idempotency keys, so retrying a create could duplicate it.
- Stale cache. Reads are cached 10 s fresh; on upstream errors a stale response up to 120 s old is returned (surfaced as
X-Revka-Cache: hit | stale). The cache key is(token_hash, url), token-scoped to prevent cross-account pollution. - HTML stripping. Upstream HTML error pages (e.g. a Cloudflare 502 splash) are stripped before reaching the dashboard.
Gateway routes over the model
Section titled “Gateway routes over the model”The dashboard and external clients reach the same model through the gateway:
GET /api/kumiho/{*path}?param=valueAuthorization: Bearer <gateway token>A read-only proxy: only GET requests are forwarded, query params pass through verbatim, and the X-Revka-Cache / X-Revka-Kumiho-Transport headers describe how the request was served. Write operations go through the typed Asset Browser routes (POST /api/assets/items, /api/assets/revisions, /api/assets/artifacts, /api/assets/bundles, /api/assets/edges, …) or the typed agent/skill/team routes. The aggregated graph view for the Memory Auditor is GET /api/memory/graph.