FLUXFLUX
  • Introduction
  • Quickstart
  • Two Specs, One Substrate
  • The Six Families
  • The FLUID Seam
  • Deterministic & Governed
  • Runtime & Evidence
  • Anatomy
  • The Nineteen Kinds
  • Versions
  • Changelog
  • JSON Schema 0.5.1
  • UI Hints 0.5.1
  • Enforcement Contract 0.5.0
  • Bundle Manifest 0.5.0
  • Overview
  • Tutorial
  • How-to guides
  • Reference
  • Explanation
  • Command line
  • Error codes
  • Accuracy program
  • The vNext Plan
  • The Nine RFCs
  • RFC-10 (proposed)
  • Conformance Profiles
Examples
What's New
FLUID
GitHub
  • Introduction
  • Quickstart
  • Two Specs, One Substrate
  • The Six Families
  • The FLUID Seam
  • Deterministic & Governed
  • Runtime & Evidence
  • Anatomy
  • The Nineteen Kinds
  • Versions
  • Changelog
  • JSON Schema 0.5.1
  • UI Hints 0.5.1
  • Enforcement Contract 0.5.0
  • Bundle Manifest 0.5.0
  • Overview
  • Tutorial
  • How-to guides
  • Reference
  • Explanation
  • Command line
  • Error codes
  • Accuracy program
  • The vNext Plan
  • The Nine RFCs
  • RFC-10 (proposed)
  • Conformance Profiles
Examples
What's New
FLUID
GitHub
  • FLUX Simulation Engine
  • Tutorial
    • First evidence pack in five minutes
  • How-to guides
    • Model your customers
    • Add a journey
    • Use the FLUID seam
    • Calibrate from aggregates: declare a scorecard
    • Ship with evidence
  • Reference
    • Command line
      • fluxsim init
      • fluxsim validate
      • fluxsim plan
      • fluxsim apply
      • fluxsim run
      • fluxsim verify
      • fluxsim ship
      • fluxsim replay
      • fluxsim calibrate
      • fluxsim accuracy
      • fluxsim gate
      • fluxsim expr
      • fluxsim describe
      • fluxsim plugins
      • fluxsim explain
    • Error codes
    • Python API
    • Schemas
  • Explanation
    • The six-step loop
    • Determinism and the seed tree
    • The FLUID seam
    • The evidence pack, and what it does not claim
  • Accuracy program

    • The accuracy program: design
    • Accuracy report

Add a journey

Goal: add a second journey to the starter project and see its customers move. A journey and its detector reach a run only through a Module's spec.resources, listed by the Simulation's moduleRefs.

1. Start a project

$ fluxsim init demo
created demo with a small FLUX bundle and its FLUID contract (10 files):
...
$ cd demo

2. Add the signal, detector and treatment

A repeat support call is the new event. The detector fires when two arrive within a day (86400000 ms). The treatment is a callback.

# signal-support.flux.yml
fluxVersion: "0.5.0"
kind: Signal
id: sig-support-call
name: Repeat Support Call Signal
metadata: { owner: { team: growth-lab } }
spec: { envelope: cloudevents/1.0, source: "urn:flux:contact-centre", type: com.telco.support.call_repeated }
# detector-support.flux.yml
fluxVersion: "0.5.0"
kind: Detector
id: det-support-repeat
name: Repeat Support Call Detector
metadata: { owner: { team: growth-lab } }
spec:
  timeWindowMs: 86400000
  pattern: [{ signalRef: sig-support-call }, { signalRef: sig-support-call }]
# treatment-callback.flux.yml
fluxVersion: "0.5.0"
kind: Treatment
id: tr-callback
name: Retention Callback
metadata: { owner: { team: growth-lab } }
spec: { actionType: retention_callback, payloadTemplate: { message: "We will call you back today" } }

3. Add the journey (with a mistake)

The journey moves a customer to a new state when its treatment works. This one names a state, vip, that the taxonomy does not have.

# journey-support.flux.yml
fluxVersion: "0.5.0"
kind: Journey
id: jr-support-callback
name: Support Callback Journey
metadata: { owner: { team: growth-lab } }
spec:
  trigger: { signalRef: sig-support-call }
  intervention: { treatmentRef: tr-callback, action: offer_callback }
  taxonomyRef: jt-subscriber-lifecycle
  personaReactions:
    persona-pragmatic-family: { successProbability: 0.3, outcome: retained, nextState: vip }
$ fluxsim validate .   # exit 1
FLX-3105: bundle does not validate, so its seam cannot be resolved --...
  jr-support-callback: personaReactions['persona-pragmatic-family'].nextState 'vip' is not a state of jt-subscriber-lifecycle
more: fluxsim explain FLX-3105  https://agenticstiger.github.io/flux/engine/reference/errors/FLX-3105.html

The engine's own check at plan time for this is FLX-2302. The validator catches it first. Fix it by using a state from taxonomy.flux.yml. atrisk to active is an allowed transition:

# journey-support.flux.yml
fluxVersion: "0.5.0"
kind: Journey
id: jr-support-callback
name: Support Callback Journey
metadata: { owner: { team: growth-lab } }
spec:
  trigger: { signalRef: sig-support-call }
  intervention: { treatmentRef: tr-callback, action: offer_callback }
  taxonomyRef: jt-subscriber-lifecycle
  personaReactions:
    persona-pragmatic-family: { successProbability: 0.3, outcome: retained, nextState: active }

A state that exists but has no edge from where the customer is does not stop the run. In a test with nextState: churned, only atrisk customers moved, because that is the only state with an edge to churned.

4. Run: nothing happens

$ fluxsim run .
...
emitted payment_recovery_moment: 154 rows (scenario)
run ... complete
$ grep -c jr-support-callback .flux/runs/*/events.ndjson   # exit 1
0

The bundle is valid and the new documents are in it, but the Module does not list them. The run ignores them: still 154 rows, and no event mentions the new journey. Listing a detector under signalRefs fails instead, with resolves to kind Detector, expected Signal. The route is the Module; the engine's error for a Journey or Detector reached any other way is FLX-2301.

5. Wire the Module

# module.flux.yml
fluxVersion: "0.5.0"
kind: Module
id: module-payment-recovery
name: Payment Recovery Module
version: 2.1.3
metadata: { owner: { team: growth-lab } }
spec:
  resources: [sig-payment-aborted, det-payment-aborted-burst, jr-payment-recovery, det-support-repeat, jr-support-callback]
  binds: [{ port: event-envelope, config: { spec: cloudevents/1.0 } }, { port: fluid-contract }]

The Simulation already lists this Module, so it needs no edit. The signal comes in through the detector that names it.

$ rm -rf .flux
$ fluxsim run .
...
emitted payment_recovery_moment: 335 rows (scenario)
run ... complete
$ grep -c jr-support-callback .flux/runs/*/events.ndjson
120

Rows went from 154 to 335: the new detector's firings are rows too. The journey produced 120 transition events.

Last Updated: 11/12/26, 10:41 PM
Prev
Model your customers
Next
Use the FLUID seam