Reference
What a thread definition looks like. Reference template, not a product spec. Copy the form, fill in your own threads.
A thread catalog is the first artifact a substrate-first team produces. It comes before any UI is drawn, before any agent is wired, before any event handler is written. It's the document the rest of the system answers to.
This page shows you what a thread definition looks like — the shape, not the contents. The example below is a generic order lifecycle. Your domain might be cases, shifts, visits, campaigns, or claims. The form stays the same.
Calibration (timing intervals, escalation hierarchies, channel trust scores) is per-engagement and lives in your own catalog. Don't copy the numbers below. Copy the structure.
Each thread in your catalog should have the following fields. Treat the catalog as an append-only document: new threads get added, existing threads get versioned, threads are never quietly deleted.
thread: {thread.name}
description: One sentence. What lifecycle does this thread track?
trigger:
event: {event.name}
source: which system / persona / channel emits the trigger
terminal_events:
- {event.name} # describe each outcome explicitly
- {event.name}
expected_sequence:
- step: {step.name}
from_event: {event.name}
to_event: {event.name}
heartbeat:
fires_after: {duration}
on_fire: generates event {heartbeat.event.name}
escalation: which persona, which surface
context_attached:
- {context.field} # what enriches each event on this thread
- {context.field}
personas_involved:
- {persona.name}: what decisions this persona owns
policy_guardrails:
- {rule} # actions that never auto-route regardless of confidence
notes: free text on edge cases, prior incidents, calibration history
A generic B2B order from arrival to terminal outcome. The vocabulary is illustrative — replace with your domain.
thread: order.lifecycle
description: |
One B2B order from arrival through fulfillment to a terminal
event (delivered, returned, written off, or cancelled).
trigger:
event: order.received
source: channel.{marketplace|edi|portal|email}
terminal_events:
- order.delivered # happy path
- order.returned # buyer-initiated return
- order.written_off # admin-finalized exception
- order.cancelled # cancelled before fulfillment
expected_sequence:
- step: intake
from_event: order.received
to_event: order.acknowledged
heartbeat:
fires_after: PT15M
on_fire: generates order.intake_stalled
escalation: ops_manager, action_queue
- step: allocation
from_event: order.acknowledged
to_event: order.allocated
heartbeat:
fires_after: PT30M
on_fire: generates order.allocation_stalled
escalation: ops_manager, action_queue
- step: pick_and_pack
from_event: order.allocated
to_event: order.packed
heartbeat:
fires_after: PT4H
on_fire: generates order.fulfillment_stalled
escalation: floor_lead, watch_face_complication
- step: handoff
from_event: order.packed
to_event: order.handed_to_carrier
heartbeat:
fires_after: PT12H
on_fire: generates order.handoff_missed
escalation: ops_manager, approval_surface
- step: in_transit
from_event: order.handed_to_carrier
to_event: order.delivered
heartbeat:
fires_after: {sla_per_service_level}
on_fire: generates order.transit_overdue
escalation: customer_service, pinned_chat
context_attached:
- customer.history
- customer.chargeback_rate
- warehouse.on_time_rate
- carrier.service_level
- sku.value
- sku.fragility_flag
- channel.trust_score
personas_involved:
- ops_manager: approves expedites, swaps warehouses
- floor_lead: signs off picks, handles equipment exceptions
- customer_service: writes back to buyer on disputes
- finance: approves credits, writes off losses
policy_guardrails:
- chargebacks above {threshold} never auto-respond
- returns to first-time buyers always notify customer_service
notes: |
Allocation heartbeat tightened from 60m to 30m after the
Q4 stockout incident. See ADR-014.
If you're starting fresh: write your top three or four threads first. The big ones — the lifecycles that touch every persona on your team. Get those right and the smaller threads fall out as variants.
If you're retrofitting an existing product: walk the database. Every table whose rows have a clear beginning and end is a thread. Every status column is a terminal-event hint. Every cron job that nags a stale record is a heartbeat that should be made explicit.
The catalog is a living document. Add a thread when a new lifecycle shows up in your business. Version a thread when its expected sequence changes. Don't quietly mutate fields — that loses the record of why decisions were made.
Pair the thread catalog with a stimulus channels reference. Threads tell you what lifecycles exist; stimulus channels tell you how events arrive.
If you'd like help writing a thread catalog for your product, see substrate audits. Or read how we build for the six-step method this artifact lives inside.