Skip to content

Guided-flow activation — operator playbook

How to turn on a guided flow for a real tenant. The engine, the config UI, the billing tile, and the Stripe reporter all ship inert — this is the checklist that activates them. Design: ADR-0169 (engine), ADR-0170 (billing).

Activation has two orthogonal switches — you can flip one without the other:

Switch What it does Needed for
A. Entitlement — the guidedFlows feature flag Lets a persona’s flow spec actually run Any live flow (free pilot or paid)
B. Billing — the Stripe meter + env var Turns completed flows into invoice line items Charging for it

A free pilot = switch A only. A paid tenant = A + B. The flow runs on A; completions are recorded to the audit trail regardless (so you can backfill billing later — the reporter reads history).


Step 1 — Enable the entitlement (switch A)

Section titled “Step 1 — Enable the entitlement (switch A)”

guidedFlows is off on every plan by default. Enable it per-tenant with a feature_flags override, then purge the KV cache (flags cache for 300s under ff:{tenantId}).

Terminal window
# Set CLOUDFLARE_ACCOUNT_ID=25b5fba80388bf85bd9adb9001458c5e for prod.
# 1. Override the flag for the tenant (updated_at is NOT NULL — include it):
wrangler d1 execute puccha-db-<env> --remote --command \
"INSERT INTO feature_flags (tenant_id, key, value, updated_at)
VALUES ('<tenantId>', 'guidedFlows', 'true', unixepoch())
ON CONFLICT(tenant_id, key) DO UPDATE SET value='true', updated_at=unixepoch()"
# 2. Purge the cached flags. They cache for 300s in the KV_SESSIONS namespace
# (binding KV_SESSIONS; the id is in apps/app/wrangler.<env>.toml):
wrangler kv key delete "ff:<tenantId>" --namespace-id <KV_SESSIONS-id> --remote

(Or just wait 300s for the cache to expire.)

Recommended for Business+ tenants only (the packaging tier, ADR-0168). Nothing stops you enabling it on a lower plan for a pilot; the entitlement is orthogonal to the plan.

To disable later: set the override value='false' (or delete the row) and purge the cache.

Step 2 — Configure the flow on a persona (no SQL)

Section titled “Step 2 — Configure the flow on a persona (no SQL)”

Self-serve in the console — no database work:

  1. Open /c/{slug}/personasAdd persona (or Edit an existing one).
  2. Under Custom instructions, toggle Enable guided flow.
  3. Set What it builds (draft kind), add the details to collect (slot keys + whether each is required), and a max turns cap.
  4. Save. The card shows an amber Guided flow badge.

Slot keys matter: the model is constrained to the exact keys you declare (that constraint is what makes flows reliably reach completion — see ADR-0169 / the slot-key fix). Name them plainly (use_case, team_size, dates, budget).

Make it the tenant’s default persona (or the one bound to the channel visitors hit) so the flow actually runs for them.

Step 3 — (Paid only) wire billing (switch B)

Section titled “Step 3 — (Paid only) wire billing (switch B)”

Skip this for a free pilot. To charge per completed flow:

  1. Stripe meter + price — follow stripe-setup.md Meter 4 — Guided-flow add-on (event_name = puccha_guided_flow, Sum aggregation). Create a metered Price on that meter at the agreed per-flow ฿ rate (a founder decision — there is no default in code).
  2. Attach the price to the tenant’s subscription as an added subscription item (the guided-flow price is not auto-attached at checkout like the base plan; add it to the sub of each add-on tenant).
  3. Set the env var (per env): wrangler secret put STRIPE_METER_EVENT_GUIDED_FLOWpuccha_guided_flow. Until this is set the reporter logs no_meter_event_name and skips — no charge.
  4. (Optional) add the ฿ figure to PLAN_META so the billing tile shows the rate.

Billing runs end-of-period: the monthly usage-reporter cron (1st @ 01:00 UTC) counts the previous month’s flow.completed events and reports one meter event per tenant.

  1. It runs: as a visitor, open the tenant’s widget (or /c/{slug}/flow-test on non-prod), start the flow, answer the elicited slots. On completion a Draft card renders (title + your-details + tap options).
  2. It recorded: the conversation’s metadata.flow.status is delivered and a flow.completed audit row exists:
    SELECT count(*) FROM audit_log
    WHERE action='flow.completed' AND tenant_id='<tenantId>'
    AND ts >= strftime('%s','now','start of month');
  3. It shows: the count appears on /c/{slug}/billingCurrent period usageGuided flows completed.
  4. It bills (paid only): spot-check via the admin-authenticated GET /api/cron/usage-reporter (scopes to your tenant). ⚠️ This also reports real resolution/API overage for your tenant — it is idempotent, but don’t run it casually on prod. The returned summary carries a flowAddon count.

The invoiced quantity for any period must equal the audit count — the audit trail is the source of truth (no separate counter):

SELECT count(*) FROM audit_log
WHERE action='flow.completed' AND tenant_id='<tenantId>'
AND ts >= <periodStartUnix> AND ts < <nextPeriodStartUnix>;

Compare against the Stripe meter events (Stripe → Billing → Meters → Guided-flow add-on → Events) for the same window.

  • Stop a flow without losing the persona: edit the persona → toggle Enable guided flow off (sends flow: null).
  • Revoke the entitlement: set the guidedFlows override to false and purge the KV cache. Any persona flow spec goes inert immediately.
  • Stop billing but keep flows running (free): unset STRIPE_METER_EVENT_GUIDED_FLOW.