RIFF Business Pack Import Architecture Brief
A design brief for shifting new business onboarding left: flexible importers, strict canonical packs, deterministic compiled runtime.
Status: design briefDate: 2026-07-03Source: ~/src/riff
Short Answer
RIFF should not let each company's JSON directly drive the live phone runtime. Add an intermediate canonical layer:
Company JSON / website / CRM export / AI-generated brief
-> importer / normalizer
-> RIFF Business Pack, versioned canonical schema
-> riffc compiler
-> deterministic call artifact
-> runtime
The Principle
The core source of truth should not be "a menu." The source of truth should be business capabilities. A menu is only one projection of capabilities. The same capability can appear in a voice menu, a companion page button, a dynamic returning-caller menu, an intake form, a scheduler action, or a post-call receipt.
Recommended Architecture
External source
- company JSON
- website
- CRM export
- NOC feed
- AI-generated business profile
|
v
Importer / Adapter
|
v
RIFF Business Pack
|
v
riffc
|
v
CallPlan Artifact
|
v
Runtime
Do not rearchitect the live runtime. Keep the deterministic FSM, riffc, typed slots, locked choices, companion surfaces, scheduler offer_ids, preflow audio, and RunRecord gate. Rearchitect the authoring/import layer.
Business Pack Shape
schema_version: riff_business_pack_v0
business:
id: smith_legal
name: Smith Legal Group
timezone: America/Chicago
phone: "+15125550100"
industry: legal
capabilities:
- id: schedule_consultation
kind: calendar_booking
label: Schedule a consultation
aliases: ["book", "appointment", "talk to lawyer"]
- id: start_intake
kind: intake_form
label: Start a new intake
menus:
main_new_caller:
when: "caller.known == false"
items:
- capability: schedule_consultation
dtmf: "1"
- capability: start_intake
dtmf: "2"
slots:
matter_type:
type: enum
options: [family, criminal, injury, housing, estate, business, other]
label: Legal issue
reask: What kind of legal issue is this about?
scheduler:
services:
consultation:
duration_minutes: 30
slot_increment_minutes: 15
min_advance_minutes: 120
What riffc Should Reject
- Menu item points to a missing capability.
- Capability has no voice path.
- Collect slot has no type.
- Required collect slot has no
reask. - Companion form has no voice fallback.
- Booking capability has no scheduler policy.
- Scheduler action does not use
offer_id. - Legal flow lacks disclaimer.
- Emergency route has no handoff.
- Caller-memory menu has no safe fallback.
- PII field is exposed on the companion page without permission.
- Tool action has no timeout/failure path.
- No generated L1 scenario for a menu item.
Vertical Examples
Plumber
Book service visit, emergency leak routing, issue description, existing request, address, urgency, shutoff status, callback number.
Electrician
Outage triage, inspection booking, emergency handoff, breaker status, sparks/smell/shock risk, panel access.
Lawyer
Schedule consultation, start intake, continue matter, leave message, conflict data, deadlines, disclaimers, no legal advice.
Space Channel
Map NOC feed categories into capabilities and content topics, then pre-render audio and companion surfaces.
Fable 5 Ask
RIFF Business Pack v0:
A canonical intermediate schema for importing businesses into RIFF.
It should support plumbers, electricians, lawyers, and content brands.
It must compile into deterministic FSM artifacts, companion surfaces,
scheduler policies, intake forms, pre-rendered audio, and tests.
Core question:
What is the smallest schema that is flexible enough for many businesses
but strict enough that riffc can reject unsafe or incomplete flows before runtime?
Recommended Build Order
- Write the Business Pack schema draft.
- Build a validator that only validates packs, not flows.
- Build a Space Channel importer: NOC JSON -> Business Pack.
- Build a lawyer intake sample pack by hand.
- Build a plumber/electrician sample pack by hand.
- Build pack-to-flow compiler for a small subset: menu, collect, message, schedule.
- Generate companion surfaces from pack output.
- Generate L1 scenarios from every menu item and required slot path.
- Run comparison: hand-authored flow vs pack-generated flow.
- Only then expand the schema.