# OKF bundle model

> Filesystem bundle layout (`index.md`, `log.md`, concept `.md` files), `Concept` dataclass fields, required `type` frontmatter, auto-timestamp behavior, reserved directories, and Hermes-native layout (`config/`, `sessions/`, `plans/`, `tools/`, `snapshots/`).

- Repository: EliaszDev/hermes-okf
- GitHub: https://github.com/EliaszDev/hermes-okf
- Human docs: https://www.grok-wiki.com/public/docs/eliaszdev-hermes-okf-b71befaafe02
- Complete Markdown: https://www.grok-wiki.com/public/docs/eliaszdev-hermes-okf-b71befaafe02/llms-full.txt

## Source Files

- `src/hermes_okf/bundle.py`
- `src/hermes_okf/concept.py`
- `docs/ARCHITECTURE.md`
- `docs/HERMES_INTEGRATION.md`
- `src/hermes_okf/hermes.py`
- `tests/test_bundle.py`

---

---
title: "OKF bundle model"
description: "Filesystem bundle layout (`index.md`, `log.md`, concept `.md` files), `Concept` dataclass fields, required `type` frontmatter, auto-timestamp behavior, reserved directories, and Hermes-native layout (`config/`, `sessions/`, `plans/`, `tools/`, `snapshots/`)."
---

An OKF bundle is a directory of Markdown files with YAML frontmatter, managed by `OKFBundle`. Each file (except reserved names) is a **concept** in an implicit knowledge graph. `OKFBundle.__init__` creates the bundle root if missing and calls `_init_bundle()` when `index.md` is absent. `HermesAgent` extends the same tree with agent-state directories under `config/`, `sessions/`, `plans/`, `tools/`, and `snapshots/`.

## Bundle layout

:::files
okf_bundle/
├── index.md                 # Bundle root index (reserved)
├── log.md                   # Chronological agent log (reserved)
├── projects/
│   ├── index.md             # Directory stub (excluded from concept listing)
│   └── my_project.md        # Concept: projects/my_project
├── decisions/
│   └── model_strategy.md
├── context/
│   └── openrouter_models.md
├── config/                  # Hermes-native (created by HermesAgent)
│   └── agent.md
├── tools/
│   └── search_web.md
├── sessions/
│   └── 2026-06-15T10-00-00Z.md
├── plans/
│   ├── research_ai_trends.md
│   └── archive/
│       └── completed_plan.md
└── snapshots/
    └── 2026-06-15T14-30-00Z.md
:::

Standalone `OKFBundle` initialization seeds `projects/`, `decisions/`, and `context/` with `index.md` stubs. `HermesAgent._ensure_structure()` adds `config/`, `tools/`, `sessions/`, `plans/`, and `plans/archive/` on first use. `snapshots/` is created when the first snapshot is written.

| Path | Role | Created by |
|------|------|------------|
| `index.md` | Bundle overview and navigation links | `OKFBundle._init_bundle()` |
| `log.md` | Append-only agent chronology | `OKFBundle._init_bundle()` |
| `projects/`, `decisions/`, `context/` | Default taxonomy directories | `OKFBundle._init_bundle()` |
| `config/agent.md` | Agent identity, model, system prompt | `HermesAgent._create_default_config()` |
| `tools/*.md` | Tool definitions with JSON schemas | `HermesAgent.register_tool()` |
| `sessions/*.md` | Per-session records | `HermesAgent.start_session()` |
| `plans/*.md` | Active task plans | `HermesAgent.create_plan()` |
| `plans/archive/*.md` | Completed or archived plans | `HermesAgent.archive_plan()` |
| `snapshots/*.md` | Point-in-time agent state | `HermesAgent.snapshot()` |

<Note>
Directory names are conventions, not enforced by the OKF spec. Types are user-defined strings in frontmatter; there is no fixed taxonomy.
</Note>

## Reserved files

`OKFValidator.REQUIRED_RESERVED_FILES` defines two root-level files that every conformant bundle must contain:

<ResponseField name="index.md" type="file">
Bundle directory listing. On init, contains `okf_version: "0.1"` in frontmatter and navigation links to default subdirectories.
</ResponseField>

<ResponseField name="log.md" type="file">
Chronological agent activity log. Initialized with `# Agent Log` and no frontmatter requirement.
</ResponseField>

Files named `index.md` or `log.md` at **any** depth are excluded from:

- `OKFBundle.list_concepts()` — not returned as concept IDs
- `OKFBundle.get_graph_edges()` — not treated as link sources
- `OKFValidator._check_all_concepts()` — not validated for `type` frontmatter

Root `index.md` and `log.md` are still checked for existence during full-bundle validation.

## Concept files

Each concept is one `.md` file. The **concept ID** is the relative path without the `.md` suffix, using forward slashes (for example `projects/my_project`). `read_concept` and `write_concept` normalize `/` to the OS path separator when resolving files.

### On-disk format

```markdown
---
type: Project
title: My Project
tags:
  - ml
  - data
timestamp: 2026-06-15T10:30:00Z
---

# My Project

Markdown body content.
```

`write_concept` serializes frontmatter with `yaml.dump` (unsorted keys, Unicode allowed), wraps it in `---` delimiters, and appends the body with a trailing newline.

### `Concept` dataclass

`Concept` is the in-memory representation parsed from one file:

| Field | Type | Default | Source |
|-------|------|---------|--------|
| `id` | `str` | — | Relative path without `.md` |
| `type` | `str` | `"Unknown"` | Frontmatter `type` |
| `title` | `str` | concept ID | Frontmatter `title` |
| `description` | `str` | `""` | Frontmatter `description` |
| `tags` | `list[str]` | `[]` | Frontmatter `tags` (coerced to `[]` if falsy) |
| `resource` | `str \| None` | `None` | Frontmatter `resource` |
| `timestamp` | `str \| None` | `None` | Frontmatter `timestamp` |
| `body` | `str` | `""` | Markdown after closing `---` |
| `metadata` | `dict[str, Any]` | `{}` | Full parsed frontmatter dict |

<ParamField body="id" type="string" required>
Relative path without `.md`, e.g. `projects/my_project` or `sessions/2026-06-15T10-00-00Z`.
</ParamField>

<ParamField body="type" type="string" required>
OKF concept type. Required by the v0.1 spec for validation; defaults to `"Unknown"` at parse time if absent.
</ParamField>

<ParamField body="metadata" type="object">
Raw frontmatter dictionary. Hermes agent concepts store extra fields here (`model`, `status`, `schema`, `steps`, `progress`, etc.).
</ParamField>

Common `type` values used by Hermes OKF:

| `type` | Typical path | Written by |
|--------|--------------|------------|
| `Project` | `projects/*` | `HermesMemory.register_project()` |
| `Decision` | `decisions/*` | `HermesMemory.record_decision()` |
| `Directory` | `*/index.md` | `OKFBundle._init_bundle()` stubs |
| `AgentConfig` | `config/agent` | `HermesAgent._create_default_config()` |
| `Session` | `sessions/*` | `HermesAgent.start_session()` |
| `Tool` | `tools/*` | `HermesAgent.register_tool()` |
| `Plan` | `plans/*`, `plans/archive/*` | `HermesAgent.create_plan()` |
| `Snapshot` | `snapshots/*` | `HermesAgent.snapshot()` |

## Required `type` frontmatter

OKF v0.1 conformance requires every concept `.md` file (excluding files named `index.md` or `log.md`) to have YAML frontmatter starting with `---` and a `type` key.

| Layer | Enforces `type`? |
|-------|------------------|
| `OKFBundle.write_concept()` | No — accepts arbitrary `**frontmatter` kwargs |
| `OKFBundle._parse_concept()` | No — falls back to `"Unknown"` |
| `OKFValidator` | Yes — reports `Missing required 'type' field in frontmatter` |

<Warning>
Writing concepts without `type` succeeds at runtime but fails `hermes-okf validate`. Always pass `type=` to `write_concept`, or run validation before committing bundle changes.
</Warning>

Validation also checks frontmatter presence, closing `---` delimiter, valid YAML, and mapping shape. See the validation reference for error output format.

## Auto-timestamp behavior

### Concept writes

`write_concept` injects a UTC timestamp when `timestamp` is not supplied in frontmatter:

```
%Y-%m-%dT%H:%M:%SZ
```

Example: `2026-06-15T10:30:00Z`. An explicit `timestamp` in `**frontmatter` is preserved unchanged.

### Log appends

`append_log(entry, category="Update")` appends to `log.md`:

1. Creates a `## YYYY-MM-DD` section header if today's date section is absent (UTC date).
2. Appends a bullet: `* **{category}**: {entry}`

`HermesMemory.record_observation()` and `record_tool_call()` route through `append_log` with categories such as `Observation`, `Tool-Call`, `Session`, and `Plan`. `record_decision()` writes a full concept under `decisions/` (with auto-timestamp via `write_concept`) **and** does not duplicate into `log.md` unless called separately.

<RequestExample>

```python
from hermes_okf.bundle import OKFBundle

bundle = OKFBundle("./my_knowledge")
concept = bundle.write_concept(
    "projects/my_project",
    body="# My Project\n\nDescribe your project here.",
    type="Project",
    title="My Project",
    tags=["ml", "data"],
)
# concept.timestamp is set automatically

bundle.append_log("Dropped PyTorch due to ROCm issues", category="Decision")
```

</RequestExample>

## `OKFBundle` operations

| Method | Behavior |
|--------|----------|
| `read_concept(id)` | Parse file to `Concept`, or `None` if missing |
| `write_concept(id, body, **frontmatter)` | Create parent dirs, write file, return `Concept` |
| `delete_concept(id)` | Remove file; returns `True` if existed |
| `list_concepts(subdir=None)` | All concept IDs, optionally filtered by subdirectory prefix |
| `append_log(entry, category)` | Append dated entry to `log.md` |
| `read_log()` | Full `log.md` contents |
| `search_by_tag(tag)` | Concepts whose `tags` contain `tag` |
| `get_graph_edges()` | Markdown `[label](target)` links as `{source, target, context}` |
| `get_neighbors(id)` | Outgoing edges from one concept |
| `to_dict(id)` | `dataclasses.asdict(Concept)` for JSON export |

External `http`/`https` link targets are excluded from graph edges. Relative `.md` link targets are normalized by stripping the `.md` suffix.

## Hermes-native layout

When `HermesAgent(bundle_path, agent_id)` starts, `_ensure_structure()` creates the agent directories and seeds `config/agent` if absent:

```yaml
---
type: AgentConfig
title: {agent_id} Configuration
model: gpt-4o
system_prompt: You are a helpful, autonomous Hermes agent.
version: 0.1.0
---
```

### Sessions

`start_session()` writes `sessions/{session_id}.md` with `type: Session`, `status: active`, and `started_at`. Session IDs default to filename-safe UTC timestamps (`%Y-%m-%dT%H-%M-%SZ`, colons replaced with hyphens). `end_session()` updates `status` to `completed` and sets `ended_at`.

### Tools

`register_tool(name, description, schema, example)` writes `tools/{name}.md` with `type: Tool`, `tags: [tool]`, and `schema` as a JSON string.

### Plans

`create_plan(task, steps)` writes `plans/{slug}_{date}.md` with `type: Plan`, `status: active`, `steps` list, and `progress: 0`. Step completion updates the markdown checklist (`[ ]` → `[x]`) and recalculates `progress`. `archive_plan()` copies to `plans/archive/` with `status: archived` and deletes the active file.

### Snapshots

`snapshot(note)` writes `snapshots/{filename_safe_timestamp}.md` with `type: Snapshot` and a JSON state block containing `agent_id`, `model`, `current_session`, `current_plan`, `system_prompt`, and `note`. `restore()` reads metadata back into the agent instance.

```mermaid
classDiagram
    class OKFBundle {
        +Path root
        +read_concept(id) Concept
        +write_concept(id, body) Concept
        +list_concepts(subdir) list
        +append_log(entry, category)
    }
    class Concept {
        +str id
        +str type
        +str title
        +list tags
        +str timestamp
        +str body
        +dict metadata
    }
    class HermesAgent {
        +str model
        +str current_session_id
        +str current_plan_id
        +_ensure_structure()
        +start_session()
        +register_tool()
        +create_plan()
        +snapshot()
    }
    OKFBundle --> Concept : parses/writes
    HermesAgent --> OKFBundle : memory.bundle
```

## Initialize and validate

<Steps>
<Step title="Create a bundle">

```bash
hermes-okf init ./knowledge
```

`OKFBundle(path)` creates the directory, `index.md`, `log.md`, and seeded subdirectories. If the target directory is non-empty, the CLI exits with an error unless `--force` is passed.

</Step>
<Step title="Write concepts with required frontmatter">

Always include `type` (and typically `title`) when calling `write_concept` or agent memory APIs.

</Step>
<Step title="Validate conformance">

```bash
hermes-okf validate --path ./knowledge
```

Expected success output: `Bundle is valid.`

</Step>
</Steps>

## Implicit graph edges

Markdown links inside concept bodies define directed edges. `[label](target.md)` from concept `a` to `b` produces `{source: "a", target: "b", context: "label"}`. Directory hierarchy and tag clustering provide additional navigation via `GraphExtractor`, but link edges are extracted directly by `OKFBundle.get_graph_edges()`.

<Info>
Reserved `index.md` files can contain navigation links, but they are not included as edge sources. Subdirectory `index.md` stubs are written with `type: Directory` for human readability only.
</Info>

## Related pages

<CardGroup>
<Card title="Quickstart" href="/quickstart">
Create a bundle, write a concept, search it, and run `hermes-okf validate`.
</Card>
<Card title="OKF validation reference" href="/okf-validation-reference">
`OKFValidator` rules, `validate_file`/`quick_check` helpers, and CLI error output.
</Card>
<Card title="Knowledge graph" href="/knowledge-graph">
Link edges, tag clustering, BFS traversal, and `GraphExtractor` queries.
</Card>
<Card title="Two-memory model" href="/two-memory-model">
Hot buffer vs cold OKF archive and flush behavior into bundle files.
</Card>
<Card title="Python SDK reference" href="/python-sdk-reference">
Full `OKFBundle` and `Concept` API surface.
</Card>
<Card title="Example: OKF bundle basics" href="/example-okf-bundle-basics">
Copy-paste recipe for create, write, search, log, and graph inspection.
</Card>
</CardGroup>
