The Knowledge Graph

On this page
  1. Two axes, and a word that already means a third thing
  2. The subgraphs
    1. Schema
    2. Content
      1. Scenarios
      2. Workflows
      3. Skills
      4. Tools
      5. Tests
      6. Context
    3. Harness
    4. Dynamic Context
  3. Which way the arrows flow
  4. Repositories — four classes, three relations
    1. Content repositories
    2. Tool repositories
    3. Test repositories
    4. Consumer applications
    5. Three relations run between repositories
  5. What is declared today, measured
  6. Where the rules live

This page is generated from docs/source/concepts-knowledge-graph/ — each section below links to its own source.

✎ Edit

Everything this harness knows about itself is one graph: the Schemas that describe its content, the Skills an agent reads, the Workflows those Skills are invoked from, the Roles that own a lane, the Tools and Tests that exercise a Skill, and the running record of what is being worked on. That graph is the Knowledge Graph, bootstrap’s own term for it (called the KGraph until 2026-09-30).

Two sentences fix the whole model, and the rest of this page elaborates them.

An Agent utilizes Skills to execute one or more Tasks in a Workflow, with an associated Knowledge Graph of Static Context (Skills, User Stories) and Dynamic Context. Zero or more Tools may be associated with a Skill, for Test execution on an agentic-to-deterministic spectrum.

Knowledge Graphs are managed in git repositories, comprised of self-documenting JSON-LD. Content is rendered into various formats for consumption by downstream knowledge products, and by public-health, clinical-health and personal-health applications.

Three definitions come straight out of the first sentence and are used unchanged throughout:

  • A Role is a swimlane, played by a human, agentic or mechanical Actor.
  • A Task is a step in a Workflow — a node in the BPMN.
  • A Skill is a Capability with defined inputs and outputs.

The Knowledge Graph is not one directory, and not one repository. An instance declares the directories it scans and the kind of graph each holds, in its <name>.json root declaration; a dependent instance inherits those and may add its own. So the Knowledge Graph of a checkout is the union of what every instance in it declares — which is why “where is the Knowledge Graph” has no filesystem answer, and why a consumer asks for a kind rather than opening a path.

This page says what the subgraphs are, which way the references between them run, how repositories divide the work, and how much of it is declared today. It does not restate the declaration mechanism: that is directory-conventions, and the schema is schemas/cat-harness.ts.

Two axes, and a word that already means a third thing

✎ Edit

Two independent questions get asked about every subgraph, and reading either answer as the other is the mistake this section exists to prevent.

What is it about? Schemas, Skills, Workflows, Roles, Tools, Tests, Context, running state. This is the topical axis, and it is what the next section describes.

Does it change while a Workflow runs? This is the Static Context / Dynamic Context split from the anchor sentence above, and the declaration already answers it mechanically in the holds field of each kind: a graph is content (a process produces it), context (a process reads it and never writes it), state (a process writes it as it runs), or derived (something else computes it).

holdsexamples
Static Contextcontent, context, derivedSkills, User Stories, Schemas, Workflows, methodologies, memories
Dynamic Contextstatebeans, todos, Workflow instances, QA sidecars

A step that writes to a context graph is a defect rather than an update, which is the whole reason the field is REQUIRED — a kind that has not decided does not compile.

The two axes are orthogonal. Skills and Schemas are both Static and are nothing like each other topically; memories and methodologies are both Static for entirely different reasons. Asking “is this a Skill?” tells you nothing about whether a Workflow may write to it, and asking “may a Workflow write to it?” tells you nothing about what it is for.

A third meaning of subgraph is already in circulation, and it is worth pinning before it spreads. Subgraph viewers uses it for one declared directory — the thing a visualiser draws and a Skill governs. This page uses it for a branch of the topical taxonomy. One topical subgraph is usually several declared directories across several instances, so the two readings are related but do not count the same things. Where the number matters, this page says declared directory or graph typology and leaves subgraph for the taxonomy.

The subgraphs

✎ Edit

Schema

Every managed node has a definition — Zod authoritative, JSON Schema and JSON-LD generated from it — saying what shape it takes and what its fields mean. The Schema subgraph holds those definitions.

It arrives empty except for what is self-describing. A bare harness knows how to describe a declaration, a directory and a kind; everything else is contributed by the layer that introduces it. A harness that adds a content kind adds its Schema in the same change, or the kind is unvalidated and its documents are told apart by shape — which is the failure directory-conventions names when it says the files declare what they are.

Used for: validation at read time, the generated schema reference, and the @context a published Knowledge Graph is parsed against.

Content

Instances of knowledge assets — the authored material a Schema describes and a Skill governs. Catalogues, documentation pages, themes, boards, translation sources, artefact indexes. Four subgraphs below are kinds of Content, listed separately because they are referenced differently, not because they are something else.

Used for: everything a reader or a renderer consumes.

Scenarios

Actors, the Roles they can take, and the User Stories those Roles are there to serve.

An Actor is a concrete participant — person, agentic or mechanical — and persists across Workflows. A Role is the swimlane: a persona an Actor takes on because of the lane it is acting in, carrying the Skills that lane needs. Nothing is a reviewer; somebody acts as reviewer for the duration of a lane, and the same Actor is a different Role in the next diagram.

Used for: binding a lane to what its occupant is expected to know, and auditing whether a Role’s Skills actually cover its lanes.

Workflows

Business process as BPMN, with DMN for the decisions. Prefer Workflow over process throughout: they were used interchangeably, and the inconsistency cost more than the synonym bought.

The diagrams are executable rather than illustrative. A lane binds a Role, an activity names the Skill to run, and a gateway MAY compute its branch from a DMN table. Instance state is committed, so a sibling session reads the same position rather than inferring one.

Used for: running the work, and being the single answer to “where are we”.

Skills

A Capability with defined inputs and outputs — the instruction body an Actor needs to perform a Task, stated generically so that it is portable across forges, binaries and machines by construction. A Content repository MUST constrain those inputs and outputs with a Schema; the consequence of not doing so is in Repositories below, and it is not a small one.

A Skill MAY be designated mechanical, human, or either. That is a property of the Capability, not of whoever happens to run it today.

Tools

The concrete mechanisms. A Tool names the Skills it satisfies through its satisfies field, and one Skill MAY be satisfied by several Tools — which is the point of the separation rather than an allowance. Several Tools for one Skill is what lets the same Capability be exercised at different points on the spectrum from fully deterministic to fully agentic, and compared.

Used for: keeping the mechanism out of the instruction. A Skill that names a vendor, a CLI or an endpoint has swallowed a Tool, and the swallowing is what makes a layer un-portable.

Tests

What adjudicates whether a Skill was performed, and how well. A Test exercises a Skill; the Tools associated with that Skill are what a Test runs it through. So the chain reads Test → Skill → Task, and a Test that names a Tool directly has jumped the Skill and measures a mechanism rather than a Capability.

Used for: quality control, compliance testing, and comparing model performance across modalities. Tests are the third repository class below.

Context

README files, memories, methodologies, recorded confirmations: what changes the conditions a Workflow executes in, without changing during execution. Applying a set of it deliberately — a Context Overlay — is what lets the same Workflow be run twice and the difference attributed to the context rather than to chance.

Used for: repeatable testing across conditions. Covered in full by Managing agent context.

Harness

The layer that renders the rest: the JSON-LD export, the visualisers, and the documentation. Its obligation is stated as three separate requirements because they fail differently — nothing draws it, nothing says what it is for, nothing an agent can invoke against it.

Used for: making a declared directory something a person can actually look at. A directory nobody can see is one nobody checks.

Dynamic Context

What is being worked on and how far it got. Written by processes as they run, committed so it survives a fresh container. It splits by who the state is for, which is a sharper line than what the state holds:

  • beans — agentic state management. Used by Agents to coordinate and track internal state within a Workflow. “Changes to the vaccination schedule are ready for review at staging.”
  • todos — human state management. Attached to a step in a Workflow or to a knowledge asset, for human Actors. “Please review this change in medication.”

A todo attaching to a knowledge asset and not only to a step is what makes the two stores genuinely different rather than one store with an audience field: a bean without a Workflow position is incomplete, and a todo on a chapter has no Workflow position to be missing.

Workflow instances, QA sidecars and health results are Dynamic Context too, written by the process that produces them.

Used for: the work plan, and the evidence that a claim about the corpus was measured rather than remembered.

Which way the arrows flow

✎ Edit

A reference has a direction, and the direction is what makes the graph answerable. Every edge below is carried by a named field in a schema, so it can be followed mechanically rather than inferred:

fromfieldto
ActorrolesRole
RoleskillsSkill
VoiceactiveIn.rolesRole
User StoryroleRole
Workflow activity<bootstrap.processes:skill ref>Skill
Workflow lanepartitionElementRef → <bpmn:resource>Role
Workflow activity<cat-harness.processes:bean op>a work-plan operation
ToolsatisfiesSkill
Skill, CapabilitysatisfiesRequirement statement
Skillgraph-typologiesGraph typology
Skillinput, outputSchema (its contract)
Test runskillSkill
any content node$schemaSchema
Foliothe board layerBoard, then Position, then Note

Three properties of that table are worth stating, because each one is a decision that could have gone the other way.

Skill is a sink. Roles point at Skills, Workflow activities point at Skills, Tools point at Skills, Tests point at Skills — and a Skill points at none of them. It names a Capability and does not know who holds it, what runs it, or what measures it. That is what lets one Skill serve several Roles, be satisfied by several Tools and be exercised by several Tests without editing the Skill.

It is also why the chain reads Test → Skill → Task rather than Test → Tool. A Test that names a Tool directly has jumped the sink and is measuring a mechanism instead of a Capability — which is exactly the comparison the several Tools per Skill allowance exists to make possible.

The Harness points at everything and nothing points back. A board is a diagram of a folio in the OMG sense that a BPMNDiagram is a diagram of a bpmn:process: the folio carries what is true, the layout layer carries where it was drawn, and the arrow runs folio → board → position → note and never back. A folio is complete with no board. The same asymmetry holds for every visualiser: removing the rendering layer loses the picture and no content.

Workflows reference Context and never write it. The holds field makes that enforceable rather than conventional — a step writing into a context graph is a defect, not an update. This is the edge that makes a Context Overlay possible at all: if a run could mutate its own conditions, replaying it under the same conditions would not be a thing you could ask for.

User Story works this way too, as of #1168. CRDM produces Workflows, User Stories and Roles, and Scenarios is where the User Stories belong. Until then a Role carried its stories as useCases, free-text strings that could not be pointed at, counted, or traced to a Workflow. Each story is now a node in scenarios/stories.json that names its role, and the role names none — the same direction as a voice, which points at the role it addresses.

Repositories — four classes, three relations

✎ Edit

A Knowledge Graph is managed in git repositories, comprised of self-documenting JSON-LD, and rendered into whatever formats a downstream knowledge product, public-health system, clinical system or personal-health application needs. That makes a repository the unit of distribution, and repositories come in four classes. A class is defined by what it is ALLOWED to do, not by what it happens to contain.

Content repositories

Where the Knowledge Graph itself lives. A Content repository:

  • MAY define Schemas for the Content types of a Knowledge Graph’s nodes.
  • MAY instantiate instances of those Content types.
  • MAY define the Skills needed to publish and consume those instances.
  • MAY designate a Skill as mechanical, as human, or as either.
  • MUST constrain a Skill’s inputs and outputs with Schemas.

That last clause is the only absolute requirement in the whole four-class model, and it is what makes the rest of it hold together. A Skill is a Capability with defined inputs and outputs; a Tool claims to satisfy a Skill; a Test claims to exercise one. If the Skill’s boundary is not written down as a Schema, “does this Tool satisfy that Skill?” has no answer anyone can check, and the agentic-to-deterministic comparison the Tool and Test classes exist for cannot be run at all.

Tool repositories

Where the mechanisms live, out of the Content repository on purpose. A Tool repository:

  • MAY implement a Skill through coordinated use of Tools — scripts, retrieving and running software, remote or local services, containers.
  • MAY expose Tools to agents as MCP services.
  • MAY expose a Tool for local execution.
  • MAY configure Tools for a test harness.
  • MAY define more than one Tool for one Skill.

The last one is the point of the separation rather than an allowance. Several Tools for one Skill is what lets the same Capability be exercised at different points on the spectrum from fully deterministic to fully agentic, and compared.

Test repositories

Where adjudication, quality control and compliance testing live. A Test repository:

  • MAY contain test data.
  • MAY contain test-data generation templates and configuration data.
  • MAY define Test Plans.
  • MAY define test-language dialects such as Gherkin.
  • MAY make test data available to a test harness, or to a subject-matter expert or author for review.

Consumer applications

The downstream end. A consumer application:

  • MAY use a Knowledge Graph’s Schemas and instance data from a Content repository.
  • MAY execute decision logic or indicator calculation from a Content repository.
  • MAY use Test and Tool repositories when building, preparing for a connectathon, or compliance-testing.

Three relations run between repositories

The edges are not interchangeable, and each already has a carrier in the declaration — they had simply never been named as one set of three:

relationrunscarried by
dependsContent → Contentneeds in the declaration — the layer stack, foundation first
referencesTool → Content, Test → ContentremoteGraphs — a graph this instance knows about and does not hold
utilizesTool → Tool, Test → Tool, App → Content, App → Testdependencies in the config — what this instance USES, overlaid
associatedany harness ↔ any harnessassociatedHarnesses — a harness this one knows, and where it is published; never loaded or materialized (issue #1146, skill associate-harness)

Associated is a fourth, and it fixes no order: it is how a folio in another repository, such as ihris, is listed without being built here.

The three answer different questions, which is why collapsing them loses information a consumer needs. Depends is about layering: it fixes an order, so a cycle in it is a defect. References is about knowing a graph exists without holding it, so it crosses a repository boundary by definition. Utilizes is about consumption at run time, and a consumer application may utilize a Content repository it has no dependency on whatsoever.

What is declared today, measured

✎ Edit

The taxonomy above is what the Knowledge Graph is for. What the registry can actually produce is narrower, and the gap is worth stating plainly: a reader who takes the taxonomy for an inventory will go looking for directories that are not there.

Measured on this instance, 2026-09-21, by reading the registry and every instance declaration rather than by counting prose. Re-derive rather than quote: bun run cat kg:export dumps the graph, and instanceRootsIn plus readDeclaration give the directory census directly.

layer (holds)registered kinds
content13
state12
context5
derived1

Thirty-one kinds in total, of which exactly one — docs — is renderable. Renderability is what wires a graph to the site build, so the number being one is not an oversight: every other graph reaches a reader through a visualiser the Harness layer builds over it, never by being published directly.

Three of those kinds were one until 2026-09-21. cat-harness was declared by 22 directories that between them held Skills, Workflows, Scenarios and methodologies — four branches of the taxonomy above, indistinguishable to any consumer filtering on kind. “Give me the Workflows” was not a query anybody could write; it could only be approximated by matching a path, which is the fragility the graph exists to remove. skills, workflows and scenarios are now their own kinds and the query works.

cat-harness survives and is not deprecated, which surprises people twice over. An alias cannot express a split — GRAPH_TYPOLOGY_ALIASES maps one name to one name, and this would have to become three. And the kind had a fifth job the split does not name: on an entry declaring ["schemas", "cat-harness"] it means a schema IS a knowledge-graph node, which is why the skill scanner tests for the kind exactly rather than for its presence. That job is still real, so the umbrella stays, now meaning harness knowledge-graph content whose directory holds more than one part of it — the eight mixed schema entries. A downstream declaration still saying ["cat-harness"] keeps parsing and keeps being scanned for Skills; what it loses is the finer query, which it never had.

What the split cost, and where it nearly went wrong. Two directories that had been reached by convention stopped being reached the moment their parent changed kind: processes/ and methodologies/crdm/processes/ both sat inside a cat-harness directory and were found by walking it. Each declared workflows in its own right. (CRDM’s eight diagrams moved into processes/ on 2026-09-22 and that second declaration is gone, so only the first survives — the episode is recorded here in the past tense because it is what the orphan report caught, not a description of today’s layout.) The second was caught only because the generated process index reported it as an orphan rather than quietly indexing eight fewer diagrams — which is the whole argument for a generator that names what it pruned.

One gap remains, already named above:

  • fsh-guts is registered context, though it is topically Dynamic State. Both readings are defensible — it is read by processes and not written by them, which is what context asserts — but the two axes disagree here, and a disagreement nobody has written down is one that gets rediscovered.

How a dependent contributes into a shared body of knowledge. Through the kind, and that is the mechanism rather than a stopgap — settled by the owner, 2026-09-21. Three instances — agent-skills, cat-harness and who-style-guide (since folded into the IRIS replica, bean qsx4) — each declared their own voices/ directory of kind voices, and the overlay resolves all three together. A fourth instance wanting to contribute a Voice declares a directory, names the kind, and is done: no nesting, no subgraph declaration, nothing added to the schema.

The alternative considered and set aside was letting a directory entry declare nested subgraph directories, so that a shared body would live at a path such as skills/voices/ and dependents would add under the same path. It buys a hierarchy that nothing currently needs, at the cost of a schema change, a migration of every in-tree declaration, and an alias carried for downstream ones. The overlay already delivers the outcome, and it is already proven by three instances.

Where the rules live

✎ Edit

This page is a map. The discipline is in the Skills, and where a Skill and this page disagree, the Skill wins and this page is wrong.

questionwhere it is answered
How an instance declares its directories, and every graph typologydirectory-conventions
What content, context, state and derived each promise a consumercontent-context-and-state-graphs
Actors, Roles, Permissions, and why a Role is a swimlanerole-model
Authoring a Workflow activity, and what a bean-marked step performsbpmn-processes
Which store answers which question about a running Workflowworkflow-state
Why a Skill states a capability and a Tool the mechanismskills-and-tools
Context Overlays, and the several ways context is generatedManaging agent context
What a visualiser owes a declared directorySubgraph viewers

The schema behind every declaration on this page is schemas/cat-harness.ts; the Role and Actor shapes are in scenarios/roles.json and cat-harness/scenarios/actors/; the Tool shape is schemas/tool.ts.

The audit that checks these joins actually resolve is bun run cat kg:audit, one criterion per join, written as committed QA sidecars so that “unbound since it was drawn” and “broken in the commit under review” stay distinguishable.


folio-assistant — code under the Apache License 2.0, documentation under CC BY 3.0. Generated schema and API references are rebuilt from source on every push to main.

deployed dev