Template System¶
Overview¶
Templates are reusable blueprints for creating actors, locations, and other narrative
entities. They are stored as immutable :class:Record objects inside
World.template_registry once a world is instantiated.
Content-addressable records. Templates inherit from
:class:tangl.core.content_addressable.ContentAddressable. Each template therefore
exposes a content_hash that captures the structure of the template while ignoring
metadata such as label or scope. Identical structures have the same hash,
allowing the registry to deduplicate entries, audit provenance, and perform content-based
queries.
template = world.find_template("generic_guard")
template.content_hash # raw bytes suitable for registry lookups
template.get_content_identifier() # 16-char hex string for logs and receipts
Use the hash when emitting receipts or proving which template created an entity. Fields
like kind, archetype, conditions, and effects influence the hash,
while metadata fields (label, scope, template_names) do not.
Declaration Levels¶
Templates can be declared at three levels. The world registry records where a template
originated via the optional :class:ScopeSelector metadata.
World Level (Global)¶
label: my_world
metadata:
title: Example World
author: StoryTangl
templates:
generic_guard:
kind: tangl.story.concepts.actor.actor.Actor
archetype: guard
Scene Level (Parent Scope)¶
scenes:
village:
label: village
blocks: {}
templates:
village_elder:
kind: tangl.story.concepts.actor.actor.Actor
Block Level (Source Scope)¶
scenes:
village:
label: village
blocks:
smithy:
label: village.smithy
templates:
apprentice:
kind: tangl.story.concepts.actor.actor.Actor
Explicit Scope Overrides¶
Set scope directly inside the template payload to override inference. Use null for
fully global templates declared inside nested scopes.
scenes:
village:
label: village
blocks: {}
templates:
traveling_merchant:
kind: tangl.story.concepts.actor.actor.Actor
scope: null # remains global instead of inheriting parent_label
Querying Templates¶
world = World(label="example", script_manager=manager)
# By label
template = world.find_template("generic_guard")
# By type
actors = world.actor_templates
locations = world.location_templates
# By criteria
guards = world.template_registry.find_all(
is_instance=ActorScript,
has_tags={"npc"},
archetype="guard",
)
Duplicate Labels¶
If multiple templates resolve to the same sanitized label, the world keeps the first entry and logs a warning for subsequent duplicates. Use unique labels when authoring content to avoid ambiguity.