Bauen
Erste Schritte
Lesen Sie die kurzen Dokumente, lassen Sie das Konformitätskorpus laufen, validieren Sie Ihre eigene Nachricht mit eingeschalteter Format-Assertion und veröffentlichen Sie sie. Dann wählen Sie eine Stufe und sprechen mit der Arbeitsgruppe.
Schritt 1
Vier Dinge lesen, in dieser Reihenfolge
Einführung ↗
Warum es SOM gibt, die drei Substantive und die sechs Prinzipien.
02 · für ImplementiererKonformität ↗
Was es heißt, konform mit SOM 1.0 zu sein — kürzer, als Sie erwarten.
03 · das klarste BildDas Hurrikan-Beispiel ↗
Eine Story, erzählt über sieben Snapshots.
04 · Ihre erste Familiestory-context-Schema ↗
Die Familie, die Sie mit ziemlicher Sicherheit zuerst implementieren.
Schritt 2
Das Konformitätskorpus ausführen
Das Repository der Spezifikation liefert durchgerechnete Beispiele, die validieren müssen, zwanzig Negativfälle, die abgewiesen werden müssen, und reine Python-Tools, die beides prüfen.
git clone https://github.com/storyobjectmodel/som.git
cd som
pip install jsonschema rfc3339-validator
python3 tools/validate.py # every example is legal
python3 tools/validate_negative.py # every negative case is rejected
python3 tools/som_lint.py schema # schemas agree with their own claims
python3 tools/validate_sequence.py examples/hurricane-run
# a story over time holds together- Ist diese Nachricht gültig? —
validate.py - Schränken die Schemas tatsächlich ein? —
validate_negative.py. Neunzehn Fälle scheitern an den Schemas; der zwanzigste,som_version: "0.3.2", scheitert an der Regel zur Wire-Version, die Ihre Implementierung selbst anwenden muss. - Stimmt das Schema mit dem überein, was es über sich selbst sagt? —
som_lint.py - Hält eine Folge von Snapshots zusammen? —
validate_sequence.py, dort, wo die teuren Bugs wohnen.
Installieren Sie rfc3339-validator. Ohne ihn akzeptiert Pythons jsonschema stillschweigend einen fehlerhaften timestamp. Das Negativkorpus enthält genau diesen Fall, damit die Prüfung laut scheitert, wenn das Paket fehlt.
Schritt 3
Im eigenen Stack validieren — mit durchgesetzten Formaten
Zwei Implementierungen, die sich uneinig sind, ob message_id eine UUID sein muss, sind nicht interoperabel. In Node heißt das: der 2020-12-Build von Ajv plus ajv-formats.
// npm i ajv ajv-formats
import Ajv2020 from 'ajv/dist/2020';
import addFormats from 'ajv-formats';
const BASE = 'https://storyobjectmodel.com/schema/1.0';
const FAMILY_SCHEMA: Record<string, string> = {
'story.context': 'story-context',
'skill.warning.raised': 'skill-warning',
'delivery.media_available': 'delivery-media-available',
'link.committed': 'link-event', 'link.gate_changed': 'link-event', 'link.withdrawn': 'link-event',
'telling.started': 'telling-event', 'telling.ended': 'telling-event', 'telling.exposed': 'telling-event',
'system.audit': 'system-audit',
};
const ajv = new Ajv2020({ strict: false, allErrors: true });
addFormats(ajv); // conformance §4: uuid and date-time MUST be asserted
const load = async (name: string) => (await fetch(`${BASE}/${name}.schema.json`)).json();
export async function validateMessage(msg: { som_version?: string; message_type?: string; payload?: unknown }) {
const envelope = ajv.compile(await load('envelope'));
if (!envelope(msg)) return { ok: false, errors: envelope.errors };
// §3: 0.3.2 is not SOM 1.0 — and never branch on the version otherwise.
if (msg.som_version?.startsWith('0.')) return { ok: false, errors: ['pre-1.0 som_version'] };
// §2 and §5: dispatch on message_type only; ignore families you don't handle.
const family = FAMILY_SCHEMA[msg.message_type ?? ''];
if (!family) return { ok: true, ignored: true };
const payload = ajv.compile(await load(family));
return payload(msg.payload) ? { ok: true } : { ok: false, errors: payload.errors };
}Zur Veranschaulichung, keine Referenzimplementierung — cachen Sie kompilierte Validatoren, statt pro Nachricht nachzuladen. Die Schemas werden unter der URL in ihrer eigenen $id ausgeliefert, die Auflösung per Identifier funktioniert also ebenfalls.
Schritt 4
Einen konformen Story-Snapshot veröffentlichen
{
"som_version": "1.0.0",
"message_id": "0199a1c4-7a2e-7b31-8c55-4d2f9e6a1b07",
"correlation_id": "0199a1c4-0000-7000-8000-000000000911",
"message_type": "story.context",
"timestamp": "2026-09-11T16:41:00.000000Z",
"originating_system": {
"system_id": "ncs-nyc-01", "system_type": "ncs"
},
"topic": "som.story.context.hurricane-2026-0911",
"payload": {
"story_id": "hurricane-2026-0911",
"slug": "HURRICANE-LANDFALL",
"headline": "Hurricane makes Cat 4 landfall",
"story_type": "ACTIVE",
"lifecycle": { "phase": "BREAKING",
"phase_entered_at": "2026-09-11T14:00:00Z" },
"sequence_number": 7,
"updated_at": "2026-09-11T16:41:00Z"
}
}- Eine neue UUID als
message_id(v7 empfohlen); dieselbecorrelation_idfür den gesamten Lebenszyklus der Story. - Dieselbe
story_id, eine höheresequence_number, ein späteresupdated_at. - Jedes Feld, auch die, die andere Systeme beigesteuert haben. Weglassen heißt: nicht vorhanden.
lifecyclegenau dann vorhanden, wennstory_typegleichACTIVEist.- Ihr eigenes
originating_system, bei jeder Veröffentlichung neu gestempelt. - Alles, was der Standard nicht trägt, gehört unter
extensions["com.{vendor}.…"].
Sehen Sie es auf einem laufenden Bus. Der Emulator ↗ des Projekts ist ein Dashboard auf einem laufenden Bus, das Sie selbst nutzen können, und die IBC-Demos ↗ zeigen zwei vollständige Szenarien von Anfang bis Ende. Eine .NET-Referenzimplementierung folgt in einem separaten Repository; das Hackathon-Starterkit aus der Zeit vor 1.0 sendet 0.3.2 und ist kein 1.0-Traffic.
Einstieg
Nichts über Ihr Produkt muss offengelegt werden
Ein System reicht für den Anfang. Integrationen werden in drei Stufen beschrieben.
Abonnieren und veröffentlichen
Lesen Sie die Story und legen Sie Ihre eigene Familie auf den Bus. Das Projekt schätzt den Aufwand auf Tage, nicht Monate.
Kontext in beide Richtungen
Ihr Tool konsumiert strukturierten Kontext und steuert ihn auch bei — Assertions, Herkunft, Links, Tellings.
Anhand der Story entscheiden
Ihr Tool handelt eigenständig auf Grundlage dessen, was es liest — über einen Executor, der die Skills des Hauses anwendet.
Mitmachen
Die Arbeitsgruppe ist offen
Interesse anmelden ↗
Dagegen entwickeln, Skills schreiben, eine Story-Archaeology-Session durchführen, der Arbeitsgruppe beitreten oder die Arbeit einfach verfolgen — das offizielle Formular fragt, wer Sie sind und was Sie vorhaben.
Formular auf storyobjectmodel.com →Eine Änderung vorschlagen ↗
Jede Änderung kommt als Pull Request, und jeder darf einen eröffnen. Schema-Änderungen unterliegen der Kompatibilitätsrichtlinie; offene Fragen stehen im offenen Register.
GOVERNANCE · CONTRIBUTING →Eine Integration durchsprechen
Für alles, was das README des Repositorys nicht beantwortet, schreiben Sie an das Projekt.
hello@storyobjectmodel.com →Die Schemas haben recht. Wenn irgendein Text — diese Website eingeschlossen — einem veröffentlichten Schema widerspricht, gilt das Schema. Die sieben Familien ansehen →