Ortelius is a Codex-facing toolkit for building, validating, and materializing source-grounded typed/fibered graph JSON.
You point Codex + Ortelius at a domain, tell it to make a graph database / knowledge graph of that domain, and Codex, guided by Ortelius, does it.
Ortelius has two public layers:
- operational protocol assets that tell Codex how to compile and execute a graph-population workflow;
- a Python graph substrate for typed/fibered graph JSON.
In short: Ortelius provides Codex-facing graph-population protocols for typed/fibered graph JSON, plus the validation and materialization tools needed to keep that JSON usable.
The protocol assets are Markdown/JSON control surfaces for Codex. Codex reads them, creates a generated graph-population bundle, follows the bundle's loop specs, updates cursor/log state, and writes candidate graph JSON.
A first Ortelius prompt to Codex looks like this:
MAKE-GRAPH
Use assets/protocol_assets/system/graph_population/v001/graph_population_protocol_schema.md
as the graph-build request compilation schema.
Make graph on domain: <domain>, with <N> node types and <M> instances of each
type, and then <E> edge types and <K> instances of each.
Generated bundles are local runtime artifacts. They are ignored by git by default.
Ortelius uses Codex at two scales of control: globally, as a policy-driven interpreter for the workflow; locally, as a source-grounded semantic synthesis primitive at the leaves of that workflow.
Globally, Codex is not a mechanically enforced CPU, but the protocol documents constrain and cue its behavior because Codex chooses its next action by reading and following the protocol. The protocol schema acts as an executable metaprogram: Codex reads it, then generates the workflow manifest, loop specs, cursor/log scaffold, batch packets, and control-loop plan. The control protocol then acts as the interpreter contract: Codex reads the generated workflow program, advances the externalized program counter, executes the next legal bounded action, validates, logs, and resumes.
Locally, at the leaves of the workflow, Codex is used as the semantic engine. The system calls on Codex to perform source-grounded semantic synthesis: to identify meaningful types, discover fields, distinguish primitive relationships from query-derived edges, and decide what the evidence justifies writing.
The central design trick in Ortelius is keeping these two roles separated. Ortelius makes Codex rigid where it should be rigid and creative where it should be creative.
The Python package src/ortelius within Ortelius supports the above workflow by loading graph JSON, validating graph invariants, inspecting graph counts, and materializing graph structure for NetworkX, PyG, and DGL readiness.
Ortelius v0.1.0 does not itself call Codex, crawl the web, persist to a graph database, train graph ML models, or guarantee graph quality. It provides the public substrate and protocol surface that a Codex session can use to build and validate candidate graph data.
Ortelius expects a pair of graph IDs:
<fiber_graph_id> -> <type_graph_id>
The type graph defines admissible node types and edge types. Type records also define fields expected on concrete records.
The fiber graph contains concrete nodes and concrete edges. Every fiber node has
a type_id pointing to a type node. Every fiber edge has a type_id pointing to
a type edge.
For every fiber edge:
edge = fiber_edges[e]
edge_type = type_edges[edge.type_id]
source_node = fiber_nodes[edge.source_id]
target_node = fiber_nodes[edge.target_id]
source_node.type_id == edge_type.source_type_id
target_node.type_id == edge_type.target_type_id
That projection invariant is the center of the system.
This project uses uv.
uv syncRun the test suite:
uv run pytest
uv run ruff check .
git diff --checkassets/
images/
logo.jpg
protocol_assets/
system/graph_population/v001/
manifest.json
graph_population_protocol_schema.md
graph_population_control_protocol.md
prompts/
bundles/
.gitkeep
src/ortelius/
graph_io.py
model.py
validate.py
protocol_assets.py
cli.py
materialize/
tests/
fixtures/graph_assets/minimal_generic/
fixtures/protocol_assets/minimal_generated_bundle/
The main public workflow is to ask Codex to use the system protocol docs. The quick-start prompt appears above; use this guided form when you want Codex to show more state as it works.
Guided invocation:
MAKE-GRAPH
Use assets/protocol_assets/system/graph_population/v001/graph_population_protocol_schema.md
as the graph-build request compilation schema.
interaction_level: guided
diagnostic_verbosity: normal
Make graph on domain: <domain>, with <N> node types and <M> instances of each
type, and then <E> edge types and <K> instances of each.
Codex should create a generated bundle first, then execute bounded source-grounded graph actions through that bundle. The generated bundle, not model memory, is the run authority.
Generated bundles belong under:
assets/protocol_assets/bundles/<domain_slug>/<protocol_id>/
That path is ignored by git except for .gitkeep.
The two main protocol documents are:
assets/protocol_assets/system/graph_population/v001/graph_population_protocol_schema.md
assets/protocol_assets/system/graph_population/v001/graph_population_control_protocol.md
The protocol schema compiles a graph-building request into a generated bundle. The control protocol walks an existing generated bundle by reading its manifest, loop specs, graph JSON, cursor, and execution log.
Validate the system protocol assets:
uv run ortelius protocol validate-system --system-root assets/protocol_assets/system/graph_population/v001Validate and inspect the minimal generated-bundle fixture:
uv run ortelius protocol validate-bundle --protocol-root tests/fixtures/protocol_assets/minimal_generated_bundle
uv run ortelius protocol inspect-bundle --protocol-root tests/fixtures/protocol_assets/minimal_generated_bundleStable top-level imports:
from ortelius import GraphBundle, load_graph_bundle, validate_graph_bundleMaterializer imports:
from ortelius.materialize.networkx import (
to_networkx_fiber_graph,
to_networkx_type_graph,
)
from ortelius.materialize.pyg import validate_pyg_readiness, to_pyg_fiber_graph
from ortelius.materialize.dgl import validate_dgl_readiness, to_dgl_fiber_graphProtocol asset checks:
from ortelius.protocol_assets import (
validate_protocol_bundle,
validate_system_protocol_assets,
)Validate and inspect graph JSON:
uv run ortelius validate --graph-root tests/fixtures/graph_assets/minimal_generic/graphs --type-graph-id tg --fiber-graph-id fg --mode bootstrap
uv run ortelius inspect --graph-root tests/fixtures/graph_assets/minimal_generic/graphs --type-graph-id tg --fiber-graph-id fgRun materialization smokes:
uv run ortelius materialize networkx --graph-root tests/fixtures/graph_assets/minimal_generic/graphs --type-graph-id tg --fiber-graph-id fg
uv run ortelius materialize pyg --graph-root tests/fixtures/graph_assets/minimal_generic/graphs --type-graph-id tg --fiber-graph-id fg
uv run ortelius materialize dgl --graph-root tests/fixtures/graph_assets/minimal_generic/graphs --type-graph-id tg --fiber-graph-id fgAvailable commands:
ortelius validate
ortelius inspect
ortelius materialize networkx
ortelius materialize pyg
ortelius materialize dgl
ortelius protocol validate-system
ortelius protocol validate-bundle
ortelius protocol inspect-bundle
DGL is optional. Try installing it only if your platform has a compatible wheel:
uv add dglOrtelius keeps DGL readiness and missing-dependency behavior tested without requiring DGL as a default dependency.
Generated graph-population bundles are not release assets by default. Keep them local unless you deliberately promote a generated bundle into a fixture or public example.
The tracked generated-bundle placeholder is:
assets/protocol_assets/bundles/.gitkeep
