Python reference
Generated from the installed lokf package. Every entry below is the real signature and docstring of the shipped code.
lokf.model
Section titled “lokf.model”Load and represent LOKF knowledge bundles.
A bundle is a directory of markdown concept files (OKF layout). This module lifts it into Python objects and, via the published JSON-LD context, into an RDF graph:
import lokf
bundle = lokf.load_bundle("examples/acme-knowledge")g = bundle.graph() # rdflib.Graph of the whole bundleload_bundle(path: 'str | pathlib.Path') -> 'Bundle'
Section titled “load_bundle(path: 'str | pathlib.Path') -> 'Bundle'”Load a bundle directory into a Bundle.
index.md/log.md are reserved (OKF §3) and not parsed as concepts;
the root index.md frontmatter becomes Bundle.meta.
class Concept
Section titled “class Concept”One concept document: frontmatter data (with body) plus its file.
class Bundle
Section titled “class Bundle”A knowledge bundle: root index.md metadata plus its concepts.
Bundle.resolve(self, ref: 'str') -> 'str'
Section titled “Bundle.resolve(self, ref: 'str') -> 'str'”Resolve a Concept ID or IRI to an absolute Concept IRI.
Bundle.iri(self, concept: 'Concept') -> 'str'
Section titled “Bundle.iri(self, concept: 'Concept') -> 'str'”A concept’s IRI: explicit id or base_iri + Concept ID.
Bundle.by_iri(self) -> 'dict[str, Concept]'
Section titled “Bundle.by_iri(self) -> 'dict[str, Concept]'”IRI -> Concept index (built once, cached).
Bundle.get(self, ref: 'str') -> 'Concept | None'
Section titled “Bundle.get(self, ref: 'str') -> 'Concept | None'”Look up a concept by IRI, Concept ID, or bundle-relative path.
Bundle.docs(self) -> 'list[dict]'
Section titled “Bundle.docs(self) -> 'list[dict]'”Each concept’s frontmatter with its IRI injected as id.
Bundle.to_jsonld(self, context: 'dict | None' = None) -> 'list[dict]'
Section titled “Bundle.to_jsonld(self, context: 'dict | None' = None) -> 'list[dict]'”Each concept’s frontmatter as a JSON-LD document (context attached).
Bundle.graph(self, context: 'dict | None' = None)
Section titled “Bundle.graph(self, context: 'dict | None' = None)”The whole bundle as one rdflib.Graph.
All concepts are parsed in a single pass (one @graph document) so
the JSON-LD context is compiled once, not once per concept.
lokf.schema
Section titled “lokf.schema”Programmatic access to the LOKF LinkML schema and its vocabulary.
The schema (lokf.yaml) and the published JSON-LD context are the single
source of truth for LOKF’s types, typed-relation slots, and relation
vocabulary. This module reads them so tools never hardcode the vocabulary.
Both files are resolved in this order: an explicit path argument, a walk
up from the current directory for a repo checkout (so local edits always
win), then the copies packaged under lokf/data/ (regenerated by
lokf-build) so installed wheels work outside a checkout.
load_schema(path: 'str | pathlib.Path | None' = None) -> 'dict'
Section titled “load_schema(path: 'str | pathlib.Path | None' = None) -> 'dict'”Return the LOKF LinkML schema as a plain dict (cached per file).
load_context(path: 'str | pathlib.Path | None' = None) -> 'dict'
Section titled “load_context(path: 'str | pathlib.Path | None' = None) -> 'dict'”Return the published JSON-LD @context mapping (cached per file).
vocabulary(schema_path: 'str | pathlib.Path | None' = None) -> 'Vocabulary'
Section titled “vocabulary(schema_path: 'str | pathlib.Path | None' = None) -> 'Vocabulary'”Load the schema and return its Vocabulary (cached per file).
class Relation
Section titled “class Relation”One relationship predicate: a frontmatter name bound to an RDF IRI.
Relation.as_row(self) -> 'dict'
Section titled “Relation.as_row(self) -> 'dict'”A JSON-serializable row (the lokf vocab --json / MCP shape).
class Vocabulary
Section titled “class Vocabulary”The LOKF vocabulary derived from the LinkML schema.
Vocabulary.subclasses_of(self, ancestor: 'str') -> 'set[str]'
Section titled “Vocabulary.subclasses_of(self, ancestor: 'str') -> 'set[str]'”Class names descending from ancestor (inclusive), via is_a.
Vocabulary.expand(self, curie: 'str') -> 'str'
Section titled “Vocabulary.expand(self, curie: 'str') -> 'str'”Expand a prefix:local CURIE to a full IRI.
Vocabulary.compact(self, uri: 'str') -> 'str'
Section titled “Vocabulary.compact(self, uri: 'str') -> 'str'”Compact a full IRI to a CURIE where a prefix matches.
lokf.parse
Section titled “lokf.parse”Parse OKF/LOKF concept markdown into JSON-LD-ready dictionaries.
These helpers are the seed of the LOKF toolkit’s parser: parse_concept
splits a concept file into frontmatter + body, and isoify normalizes
YAML-parsed dates to the ISO-8601 Z form used by the committed RDF
projections.
isoify(o)
Section titled “isoify(o)”Recursively convert datetime/date values to ISO-8601 strings.
+00:00 offsets are normalized to Z so JSON/RDF output matches the
committed examples/*.nt projections byte-for-byte.
parse_concept(path: 'str') -> 'dict'
Section titled “parse_concept(path: 'str') -> 'dict'”Read one concept markdown file into a dict of frontmatter + body.
Raises ValueError with a clear message if the file has no ---
delimited YAML frontmatter (e.g. a plain markdown or reserved file).
lokf.rdf
Section titled “lokf.rdf”Convert LOKF markdown (a single concept or a whole bundle) to RDF.
This is the engine behind lokf convert. A concept file is lifted to
JSON-LD via the published context and parsed with rdflib, so it serializes to
any format rdflib supports.
from lokf import rdf
print(rdf.serialize("examples/acme-knowledge/metrics/weekly-active-users.md"))print(rdf.serialize("examples/acme-knowledge", fmt="nt"))docs_to_graph(docs: 'list[dict]', context: 'dict | None' = None)
Section titled “docs_to_graph(docs: 'list[dict]', context: 'dict | None' = None)”Parse a list of concept docs into one rdflib.Graph.
The docs are wrapped in a single @graph JSON-LD document so the
context is compiled once. This is the shared seam behind
lokf.model.Bundle.graph and graph_of.
graph_of(source: 'str | pathlib.Path', context: 'dict | None' = None)
Section titled “graph_of(source: 'str | pathlib.Path', context: 'dict | None' = None)”RDF graph for a concept file or a bundle directory.
A directory is projected as a whole bundle. A single .md file is
resolved against its enclosing bundle when one exists (so id follows
the bundle’s base_iri); a standalone file falls back to its explicit
id or a file:// IRI derived from its path.
serialize(source: 'str | pathlib.Path', fmt: 'str' = 'ttl', context: 'dict | None' = None) -> 'str'
Section titled “serialize(source: 'str | pathlib.Path', fmt: 'str' = 'ttl', context: 'dict | None' = None) -> 'str'”Serialize a concept file or bundle to RDF text in fmt (default Turtle).
lokf.store
Section titled “lokf.store”A pyoxigraph-backed RDF store for querying a LOKF knowledge base.
Load a bundle (or any RDF graph) into an in-memory Oxigraph store and run SPARQL over it — the knowledge-retrieval layer of the toolkit.
from lokf.store import GraphStore
store = GraphStore.from_bundle("examples/acme-knowledge")for row in store.select("SELECT ?s WHERE { ?s a lokf:Metric }"): print(row["s"])query_form(sparql: 'str') -> 'str'
Section titled “query_form(sparql: 'str') -> 'str'”The SPARQL query form: ‘select’, ‘ask’, ‘construct’, or ‘describe’.
Leading comments and PREFIX/BASE lines are skipped. Defaults to ‘select’ when no form keyword is found. Shared by the CLI, server, and MCP so all three classify a query identically.
class GraphStore
Section titled “class GraphStore”An in-memory SPARQL store over a LOKF knowledge base.
prefixes (the schema’s namespace table) are prepended to every query
and update, so lokf:/schema:/prov: and friends work without a
per-query PREFIX block.
GraphStore.query(self, sparql: 'str', **kw)
Section titled “GraphStore.query(self, sparql: 'str', **kw)”Run a SPARQL query with the schema prefixes in scope.
Returns pyoxigraph’s native result: QuerySolutions (SELECT),
QueryBoolean (ASK), or QueryTriples (CONSTRUCT/DESCRIBE).
Federated SERVICE queries are rejected: the engine would issue an
outbound request to a query-controlled host, which is an SSRF vector
for the local lokf serve endpoint. (LOAD/INSERT/DELETE
are already rejected by pyoxigraph’s read-only query.)
GraphStore.select(self, sparql: 'str', **kw) -> 'list[dict]'
Section titled “GraphStore.select(self, sparql: 'str', **kw) -> 'list[dict]'”Run a SELECT and return rows as {var: python value} dicts.
Every selected variable is a key in every row (None when unbound),
so the column set is complete even when a variable is unbound in all
rows; bound bindings are reduced to their lexical value.
GraphStore.ask(self, sparql: 'str', **kw) -> 'bool'
Section titled “GraphStore.ask(self, sparql: 'str', **kw) -> 'bool'”Run an ASK query and return the boolean.
GraphStore.construct(self, sparql: 'str', fmt: 'str' = 'ttl', **kw) -> 'str'
Section titled “GraphStore.construct(self, sparql: 'str', fmt: 'str' = 'ttl', **kw) -> 'str'”Run a CONSTRUCT/DESCRIBE and serialize the resulting graph.
GraphStore.serialize_results(self, sparql: 'str', fmt: 'str' = 'json', **kw) -> 'bytes'
Section titled “GraphStore.serialize_results(self, sparql: 'str', fmt: 'str' = 'json', **kw) -> 'bytes'”Run a SELECT/ASK and serialize results in the SPARQL results format.
GraphStore.rdflib_graph(self, sparql: 'str | None' = None)
Section titled “GraphStore.rdflib_graph(self, sparql: 'str | None' = None)”The store (or a CONSTRUCT/DESCRIBE result) as an rdflib.Graph.
With no query, the whole store is returned. This backs the live graph visualization, which projects the graph to cytoscape elements.
GraphStore.dump(self, fmt=<RdfFormat Turtle>) -> 'bytes'
Section titled “GraphStore.dump(self, fmt=<RdfFormat Turtle>) -> 'bytes'”Serialize the whole store (default graph) as RDF text.
lokf.server
Section titled “lokf.server”A local SPARQL endpoint + live graph visualization for a knowledge base.
lokf serve <bundle> loads the bundle into a ~lokf.store.GraphStore
and publishes it over HTTP so agents (and people) can query and explore it
locally — no external services, entirely offline:
GET|POST /sparql— the SPARQL 1.1 protocol. SELECT/ASK returnapplication/sparql-results+json; CONSTRUCT/DESCRIBE return Turtle.GET /graph.json— cytoscape.js elements for the whole graph.GET /— an interactive cytoscape view with a live SPARQL box.
The server is stdlib-only (http.server); cytoscape.js ships in the package.
build_server(store: 'GraphStore', host: 'str' = '127.0.0.1', port: 'int' = 8000)
Section titled “build_server(store: 'GraphStore', host: 'str' = '127.0.0.1', port: 'int' = 8000)”A ThreadingHTTPServer serving store (start/stop it yourself).
serve(source, host: 'str' = '127.0.0.1', port: 'int' = 8000) -> 'None'
Section titled “serve(source, host: 'str' = '127.0.0.1', port: 'int' = 8000) -> 'None'”Load source and serve it until interrupted.
lokf.propose
Section titled “lokf.propose”Propose typed relations from the markdown links in concept bodies.
Concept prose often links to other concepts without asserting the
relationship in frontmatter. This module extracts those links
(extract_links), classifies each one against a cue-phrase table
(propose), and can write accepted proposals back into the source
files’ frontmatter without disturbing formatting (apply).
extract_links(concept: 'Concept', bundle: 'Bundle') -> 'list[Link]'
Section titled “extract_links(concept: 'Concept', bundle: 'Bundle') -> 'list[Link]'”Markdown prose links in concept.body (code blocks/spans excluded).
propose(bundle: 'Bundle', vocab: 'Vocabulary | None' = None, concept: 'Concept | None' = None) -> 'list[Proposal]'
Section titled “propose(bundle: 'Bundle', vocab: 'Vocabulary | None' = None, concept: 'Concept | None' = None) -> 'list[Proposal]'”Propose relations for prose links not already asserted in frontmatter.
proposal_row(proposal: 'Proposal', applied_ids: 'set[int] | None' = None) -> 'dict'
Section titled “proposal_row(proposal: 'Proposal', applied_ids: 'set[int] | None' = None) -> 'dict'”A JSON-serializable row for a proposal.
Shared wire shape for lokf propose --json and the MCP
propose_relations tool. When applied_ids is given (apply mode), the
row gains an applied flag; in dry-run mode it is omitted.
apply(proposals: 'list[Proposal]', min_confidence: 'float' = 0.0) -> 'list[Proposal]'
Section titled “apply(proposals: 'list[Proposal]', min_confidence: 'float' = 0.0) -> 'list[Proposal]'”Write accepted proposals into source frontmatter; return those written.
Slot relations append the target IRI under the slot key; non-slot
relations append {predicate, target} to relations. Files are
edited with round-trip YAML so comments, key order, and quoting survive;
duplicates are never written, and everything outside the frontmatter
block (any preamble before the first --- and the whole body after
the second) is preserved byte-for-byte.
class Link
Section titled “class Link”One markdown prose link, resolved (where possible) to a bundle concept.
class Proposal
Section titled “class Proposal”A proposed relation from source to link.target.
lokf.export
Section titled “lokf.export”Graph and search projections of a bundle, derived without rdflib.
The knowledge-graph page and JSON-LD blocks in the docs are built in a CI
environment that has neither rdflib nor the installed lokf package, so
everything here is derived from concept frontmatter and the Vocabulary
alone. to_cytoscape projects typed relations to edges (RDF predicates
from typed relation slots and reified relations entries, never plain
markdown body links); dataset_search_jsonld emits schema.org
Dataset documents for Google Dataset Search.
to_cytoscape(bundle, vocab=None) -> 'dict'
Section titled “to_cytoscape(bundle, vocab=None) -> 'dict'”Bundle as cytoscape.js elements (nodes + typed-relation edges).
Nodes are the bundle’s concepts; edges are RDF predicates drawn from each
concept’s typed relation slots and reified relations entries, keeping
only those whose target resolves to another concept in the bundle.
Named-slot edges match the concept-to-concept subset of
Bundle.graph one-to-one and carry data.reified = False. Reified
relations entries are flattened to direct labeled edges for display
(in the RDF projection they remain reified statements, not direct
concept-to-concept triples) and are marked data.reified = True.
Non-dict relations entries are skipped; validation reports them.
graph_to_cytoscape(graph, vocab=None) -> 'dict'
Section titled “graph_to_cytoscape(graph, vocab=None) -> 'dict'”Any rdflib.Graph as cytoscape.js elements.
Nodes are resources that carry an rdf:type in the graph (labelled by
schema:name/rdfs:label when present, else the local IRI part);
edges are triples whose predicate is a LOKF relation predicate and whose
object is itself a node. This drives the live server’s visualization of a
SPARQL CONSTRUCT result, mirroring to_cytoscape for a store.
dataset_search_jsonld(bundle, vocab=None) -> 'list[dict]'
Section titled “dataset_search_jsonld(bundle, vocab=None) -> 'list[dict]'”schema.org Dataset JSON-LD docs for each Dataset/Table concept.
Shaped for Google Dataset Search; only keys with values are emitted, and
bundle-relative references (url/isPartOf/hasPart) are resolved
to absolute IRIs through Bundle.resolve.
lokf.agentskills
Section titled “lokf.agentskills”Access and install the Claude Code agent skills bundled with LOKF.
The skills live under lokf/skills/<name>/SKILL.md, each a directory with a
SKILL.md carrying YAML frontmatter (name/description) and a markdown
body of instructions that drive the real lokf CLI. This module locates them
(zip-safe, like lokf.schema), lists their frontmatter, and copies the
tree into a project’s .claude/skills so an agent can use them.
skills_dir() -> 'pathlib.Path'
Section titled “skills_dir() -> 'pathlib.Path'”Return the packaged skills directory (lokf/skills).
list_skills() -> 'list[tuple[str, str]]'
Section titled “list_skills() -> 'list[tuple[str, str]]'”Return (name, description) from each skill’s SKILL.md frontmatter.
install(dest: 'str | pathlib.Path | None' = None) -> 'pathlib.Path'
Section titled “install(dest: 'str | pathlib.Path | None' = None) -> 'pathlib.Path'”Copy the skills tree into dest (default .claude/skills); return it.
Parents are created and same-named skills are overwritten in place.
lokf.mcp_server
Section titled “lokf.mcp_server”A FastMCP stdio server that exposes the LOKF toolkit to agents.
LOKF is a semantic profile of the Open Knowledge Framework: a knowledge base
is a bundle of markdown concepts (frontmatter + prose) that projects to
RDF and is queryable with SPARQL. The tools here let an agent list and inspect
concepts, run SPARQL, convert markdown to RDF, propose typed relations from
prose links, read the relation vocabulary, and summarize a bundle. Point tools
at a bundle directory (e.g. examples/acme-knowledge) unless noted.
list_concepts(bundle: 'str') -> 'list[dict]'
Section titled “list_concepts(bundle: 'str') -> 'list[dict]'”List every concept in a bundle as {concept_id, type, title, iri}.
bundle is a LOKF bundle directory. A fast index of what the knowledge
base contains; use describe_concept for the full record of any one.
describe_concept(bundle: 'str', concept_id: 'str') -> 'dict'
Section titled “describe_concept(bundle: 'str', concept_id: 'str') -> 'dict'”Describe one concept: {iri, type, title, body, frontmatter, turtle}.
concept_id is a bundle-relative id (e.g. metrics/weekly-active-users,
with or without .md). turtle is the concept’s RDF projection.
Returns {error: …} if no concept matches.
sparql_query(bundle: 'str', query: 'str') -> 'dict'
Section titled “sparql_query(bundle: 'str', query: 'str') -> 'dict'”Run a SPARQL query over a bundle’s in-memory graph.
Schema prefixes (lokf/schema/prov/dcterms/skos/foaf/rdf/rdfs/owl/xsd/dcat) are preset, so queries need no PREFIX block. SELECT returns {columns: […], rows: [{…}]}; ASK returns {boolean: bool}; CONSTRUCT/DESCRIBE returns {turtle: ‘…’}. Returns {error: …} on a bad query.
convert(source: 'str', format: 'str' = 'ttl') -> 'dict'
Section titled “convert(source: 'str', format: 'str' = 'ttl') -> 'dict'”Convert LOKF markdown to RDF: {format, rdf}.
source is a concept .md file or a bundle directory; format is one
of ttl | nt | jsonld | xml | n3 | trig. Returns {error: …} for a bad
format.
propose_relations(bundle: 'str', min_confidence: 'float' = 0.0, apply: 'bool' = False) -> 'list[dict]'
Section titled “propose_relations(bundle: 'str', min_confidence: 'float' = 0.0, apply: 'bool' = False) -> 'list[dict]'”Propose typed relations from the markdown links in concept prose.
Each proposal is {source, link_text, target, predicate, curie, confidence,
rationale}. Proposals below min_confidence are dropped. When apply
is True the accepted proposals are written into the source files’
frontmatter and each carries an applied flag.
get_vocabulary() -> 'dict'
Section titled “get_vocabulary() -> 'dict'”Return the LOKF vocabulary: {classes, relations}.
classes maps class name -> CURIE. relations is a list of
{name, curie, uri, frontmatter_key, description}, where frontmatter_key
is True when the relation can be asserted as a frontmatter slot (else it is
used via a relations: entry).
bundle_summary(bundle: 'str') -> 'dict'
Section titled “bundle_summary(bundle: 'str') -> 'dict'”Summarize a bundle for quick orientation.
Returns {concept_count, types, triple_count, relation_edge_count}: the number of concepts, a per-type count, the size of the RDF projection, and the number of typed-relation edges between concepts.
main() -> 'None'
Section titled “main() -> 'None'”Run the LOKF MCP server over stdio.
lokf.build
Section titled “lokf.build”Reproduce every generated LOKF artifact from the single source of truth
(lokf.yaml), then assemble the reference bundle, validate it against the
schema, and project it to RDF.
Run from anywhere inside the repository:
uv syncuv run lokf-build # or: just buildOutputs (regenerated in place): lokf.context.jsonld JSON-LD context (+ type->@type, id->@id aliases) lokf.schema.json JSON Schema lokf.shacl.ttl SHACL shapes lokf.owl.ttl OWL ontology examples/acme-knowledge.bundle.json assembled bundle (git-ignored) examples/acme-knowledge.nt RDF triples for the whole bundle examples/weekly-active-users.nt RDF triples for one concept
run(cmd, **kw)
Section titled “run(cmd, **kw)”Echo cmd, then run it with subprocess.run(..., check=True).
generate(root: 'pathlib.Path') -> 'None'
Section titled “generate(root: 'pathlib.Path') -> 'None'”Run the four LinkML generators, then publish the authoring context.
assemble(root: 'pathlib.Path') -> 'dict'
Section titled “assemble(root: 'pathlib.Path') -> 'dict'”Assemble all concept files (+ root index.md metadata) into one bundle.
validate(root: 'pathlib.Path') -> 'None'
Section titled “validate(root: 'pathlib.Path') -> 'None'”Validate the assembled bundle against the schema’s KnowledgeBundle root.
to_rdf(root: 'pathlib.Path', bundle: 'dict') -> 'None'
Section titled “to_rdf(root: 'pathlib.Path', bundle: 'dict') -> 'None'”Project the bundle (and its Metric concept) to N-Triples in examples/.
main() -> 'int'
Section titled “main() -> 'int'”Entry point for the lokf-build console script.