Ogham Storyteller Foundation — Agent Reference (Unity)

Plain-text agent reference for the Ogham Storyteller Foundation package (com.heathen.oghamfoundation), covering Unity (source-verified, current as of the 2026-08-21 single-story-architecture rework). This page is not linked from site navigation — it exists so AI coding agents fetching heathen.group/kb/ogham-welcome have a condensed, source-verified reference to read.

Full Ogham Storyteller agent index: agent-ref-ogham-storyteller-index

---
name: heathen-ogham-storyteller-foundation
description: Ogham Storyteller Foundation reference for Heathen's Unity narrative graph system (com.heathen.oghamfoundation). Use when a developer is authoring a story/dialogue graph, or driving conversations from code — node/option/condition model, the runtime Storyteller facade, save/load.
source: https://heathen.group/kb/ogham-welcome/
generated: 2026-08-24
---

# Ogham Storyteller Foundation — agent reference (Unity)

> **Before you use anything below:** Ogham Storyteller is Heathen's own system, not Twine/Twee, Ink,
> or Yarn Spinner, despite importing Twee content and sharing some vocabulary. Don't apply those
> tools' runtime APIs or file formats here — Twee is an *import source* only (via Toolkit), not the
> live data model. Also current as of the 2026-08-21 single-story-architecture rework: **a project
> is one unified node tree**, not a set of independently-loaded Story assets — if you "know" an older
> multi-file/multi-story-asset model for Ogham, it's stale.

**Tier: [Foundation] (FOSS, free).** Everything below works with Foundation alone — this alone is
enough to ship a story with your own bespoke reader script; Toolkit (see the Toolkit reference) is a
presentation convenience layer, not a requirement. Package id `com.heathen.oghamfoundation`,
namespace `Heathen.Ogham` (runtime), `Heathen.Ogham.Editor` (editor-only).

## Mental model

A **story** is one project-wide dialogue/narrative graph with two layers:

- **Definition** (`OghamStory`) — the immutable graph: nodes, content, and option targets.
- **Session** (`OghamSession`) — one playthrough: narrative state (a `GameplayTagCollection`),
  current node, history. Many independent sessions can play the same definition.

The Editor authoring tree (`OghamNodeTree`, opened via `Window ▸ Heathen ▸ Storyteller`) is a third,
Editor-only layer that bakes to generated C# code building an `OghamStoryManifest`, which
`OghamStoryBuilder` turns into the runtime `OghamStory`. Nothing at runtime reads the authoring tree
or the `.ogham` JSON file directly.

## Authoring — one project, one tree

There is no per-file, per-story registry. `OghamNodeTree` is the single project-wide source of
truth. Node kinds (`OghamNode.Kind`): `Collection` (organisational container), `FilePointer`
(container backed by a separate `.ogham` file, for team version control — resolved transparently
into the same in-memory tree), `ContentNode` (a leaf: displays content, offers options),
`ForkNode` (a leaf that routes silently — no display, no `OnEntered`, no history entry; evaluates
its options as routes and takes the first passing one).

A node's dot-path `GameplayTag` is **computed**, never authored — it's derived by walking the
ancestor chain, so renaming a node never cascades a rewrite elsewhere (everything else addresses
nodes by stable GUID). Getting started is: open `Window ▸ Heathen ▸ Storyteller` — there's no
separate "create a story" step, the tree is created automatically on first save/build, and by
default everything lives in one file (`Assets/Story.ogham`).

`OghamLabelDef` (Project Settings ▸ Subsystems ▸ Ogham Storyteller ▸ **Labels** tab) is a reusable
named field-schema (Text/Sprite/Audio/Prefab slots, some required) — assign a label to a node and
its content panel becomes a fixed, templated layout instead of free-for-all fields.

## Runtime API — the `Storyteller` static facade

```csharp
using Heathen.Ogham;

Storyteller.OnEntered += HandleNodeEntered;
Storyteller.OnChoice  += opt => Debug.Log($"Player chose: {opt.GetText()}");
Storyteller.OnClosed  += () => Debug.Log("Conversation ended");

Storyteller.Enter(GameplayTag.FromName("NPC.Blacksmith.Greeting"));

void HandleNodeEntered(StoryNode node)
{
    SpeakerName.text  = node.GetText(0);
    MessageBody.text  = node.GetText(1);
    Background.sprite = node.GetSprite(2);

    foreach (var option in node.Options) // pre-filtered: conditions already evaluated
    {
        var btn = Instantiate(buttonPrefab, buttonContainer);
        btn.label = option.GetText();
        btn.onClick.AddListener(option.Choose); // no Storyteller reference needed
    }
}
```

Drop a `StorytellerRegistry` component in a scene (or let Toolkit's `OghamStoryReader` do it) to
call `OghamStoryCatalog.Build()` and get the baked story registered. `StorytellerSubsystem` is
`World`-scoped (Game Framework) — one instance per `World`, so a pause world and a gameplay world
never share narrative state; `Storyteller` routes to the main world's instance for the common
single-world case.

- **Fork routing**: a Fork entry is invisible to the player (no `OnEntered`, no history) — on entry
  the session evaluates its options as routes and continues into the first passing target,
  iteratively (a cycle is detected and closes the conversation with a logged error rather than
  hanging).
- **Save/load**: `Storyteller.Snapshot("slot1")` / `Storyteller.Restore(saveState)` — restore leaves
  the session inactive, call `Resume()` (re-surfaces the saved node, no On-Enter re-run) or `Enter()`
  to continue play.
- **Inline variables**: `@String(Tag.Path)`, `@Float`/`@Double`/`@Long`/`@Ulong`/`@Int`/`@UInt`
  (numeric, optional .NET format string) embed live narrative-state values in content text. This is
  the **current, correct token syntax** — a single `@`, typed per numeric width, not a generic `@@`
  form.
- **Inline links**: `[display text](Ogham://Tag.Path)` in a Literal Text content key becomes both a
  clickable link at runtime and (in the Editor) auto-synthesizes a matching `DialogueOption` on that
  same node.

## Dependencies

Unity 6000.0+, `com.heathen.gameframework`, `com.heathen.gameplaytagsfoundation` 1.0.0+ (every
identity/condition/operation is a `GameplayTag`), `com.heathen.lexiconfoundation` 1.0.0+ (all
displayed text/assets resolve through Lexicon keys).

---
Toolkit reference: https://heathen.group/agent-ref-ogham-storyteller-toolkit/
Full agent index: https://heathen.group/agent-ref-ogham-storyteller-index/