Skip to content

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.

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.
ObjectWhat it isKey fields
ProjectTop-level namespace. Revka uses two by default: CognitiveMemory (user memories, sessions, compactions) and Revka (skills and operational data).name, description, deprecated, created_at, metadata
SpaceA hierarchical path within a project that organizes items, e.g. Revka/AgentPool. Spaces nest under a parent_path.path, name, parent_path, created_at
ItemA 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
RevisionAn 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
ArtifactA 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
BundleA 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)
EdgeA typed directed relationship between two items.source_kref, target_kref, edge_type, metadata

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.skill

Selectors are appended as query parameters to pin a specific revision or artifact:

kref://CognitiveMemory/Skills/creative-memory.skill?r=2 # revision 2
kref://CognitiveMemory/Skills/creative-memory.skill?r=2&a=SKILL.md # artifact within revision 2
  • r=N — pin to revision number N. Omit it to address the item itself (callers then resolve latest or 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).

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:

SpacePurpose
Revka/AgentPoolPer-agent state — identity, expertise, tone, allowed-tool list.
Revka/Plans/<project>Plans the Operator decomposed for a project.
Revka/SessionsActive and historical chat sessions.
Revka/GoalsLong-running goals an agent is working toward.
Revka/AgentTrustPer-agent-template trust scores and recent-outcome buffer.
Revka/ClawHubMarketplace catalog state (skills, agents, workflows).
Revka/TeamsTeam composition and delegation topology.
Revka/WorkflowRunsOperator workflow run state and history.
Revka/OutcomesPer-run outcomes feeding the trust-score calculation.
CognitiveMemory/SkillsShared 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.

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:

TypeWhen to useExample title
decisionA choice with a rationale that should bind future agents.”Chose Axum over Actix on Mar 14”
preferenceStable user/operator preference.”User wants tests run before commits”
factVerified fact about the world or the system.”Daemon binds 0.0.0.0:42617 in network mode”
correctionOverrides a prior memory that proved wrong.”Operator does NOT auto-restart on panic (correction)“
architectureHigh-level structural choice or constraint.”Operator/Rust split per ADR-005 on Apr 18”
implementationConcrete how-it-works knowledge.”Skill kref resolution flow on Apr 20”
synthesisAggregated insight derived from multiple sources.”Q1 channel error patterns rolled up Apr 27”
reflectionPost-mortem or lesson learned.”Postmortem: stash overlap on Apr 27”
summaryCompacted session or thread summary.”Apr 27 docs-restructure session summary”
skillA reusable procedure to be discovered later.”creative-memory”

Provenance is what separates a graph memory from a flat note. Revka uses six edge types:

Edge typeMeaningHow it’s created
DERIVED_FROMThe new capture was derived from each source.Implied automatically when you pass source_krefs to kumiho_memory_reflect.
DEPENDS_ONStep/item B cannot start until A completes.Set explicitly via kumiho_create_edge.
REFERENCEDSoft pointer — one memory mentions another without depending on it.kumiho_create_edge, or inferred.
CONTAINSBundle/membership — a session contains its captures.Bundle membership.
CREATED_FROMOne item is a forked or transformed version of another.kumiho_create_edge.
BELONGS_TOOwnership/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.

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, each outcome:summary:timestamp.
  • last_run, template_name, optional last_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.

Revka reaches Kumiho through two transports, both transparent to you.

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 (also false/no/off).
  • The bridge script kumiho_sdk_bridge.py is materialized from an embedded resource to ~/.revka/kumiho/kumiho_sdk_bridge.py on first use, and listens on 127.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.log and …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 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:

ObjectMethods
Projectscreate_project, ensure_project
Spacescreate_space, ensure_space, ensure_child_space, list_spaces
Itemscreate_item, list_items, list_items_paged, list_items_filtered, get_item_by_kref, search_items, deprecate_item, delete_item
Revisionscreate_revision, get_latest_revision, get_revision, get_revision_by_tag, list_item_revisions, tag_revision, untag_revision, deprecate_revision, batch_get_revisions
Artifactscreate_artifact, get_artifacts, get_artifacts_by_location, get_artifact_by_name
Bundlescreate_bundle, get_bundle, delete_bundle, add_bundle_member, remove_bundle_member, list_bundle_members
Edgescreate_edge, list_edges, delete_edge
Skillscreate_skill, list_skills, search_skills, deprecate_skill

Behavior worth knowing:

  • Auth. The FastAPI transport sends X-Kumiho-Token from KUMIHO_SERVICE_TOKEN; the bridge uses KUMIHO_AUTH_TOKEN. They can differ. KUMIHO_SERVICE_TOKEN falls back to KUMIHO_AUTH_TOKEN when 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.

The dashboard and external clients reach the same model through the gateway:

GET /api/kumiho/{*path}?param=value
Authorization: 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.