YFlow: A YAML-Based Conversational Flow Language
Overview
YFlow is a declarative, YAML‑based language designed to define conversational flows in a structured, readable, and secure way. It allows teams to describe how a conversation progresses—step by step—without writing imperative code.
YFlow focuses on conversation logic, not implementation details.
It focuses on:
Declarative over Imperative - Describe what the flow does, not how
YAML-Native Features - Leverage anchors, aliases, and native multi-line strings
Graph as Data - The flow graph is just structured data, easily transformed
Composability - Build complex flows from simple, reusable pieces
Human & Machine Readable - Clear enough for humans, parse able for tools
Major Changes: Customer v2 JSON → YFlow
This section summarizes the key serialization changes required when transitioning from Customer v2's JSON storage format to YFlow. These changes affect the parser (YFlow → Customer v2 model), emitter (Customer v2 model → YFlow), and the integration resolution layer.
1. Node Identity: UUID → Human-Readable Name
Current (Customer v2 JSON): Every node has a system-generated UUID as its identity (noded). Some nodes also have a separate display name (e.g., Agent nodes have a name field).
Target (YFlow): The node name (YAML map key) is the identifier. There are no UUIDs in the flow model — names are the primary and only identity. This is the same model as variables in a programming language: the name is the reference.
Naming Rules:
Names must be unique within the flow
Any case is allowed (snake_case, camelCase, PascalCase, etc.)
Spaces are allowed — use YAML quotes: "Main Agent": 1–64 characters
Names with spaces require quotes in next: references too: next: "Main Agent"
Auto-Generated Name Convention (Emitter — Customer v2 → YFlow):
The emitter uses snake_case when auto-generating names from existing Customer v2 data:
Node Type
Name Source
Example
Start
Always start
start
End
end or end_N if multiple
end, end_1
Agent
Existing name field (slugified to snake_case)
main_agent
Menu
Existing name field (slugified to snake_case)
main_menu
Say
say_N (sequential)
say_1, say_2
API
{integration}_{method} from integration/method names
banking_api_get_balance
Transfer
transfer_N or slugified label
transfer_to_sales
Tools
{agent_name}_tools or tools_N
main_agent_tools
Branch
branch_N or descriptive name
check_balance
Set
set_N or descriptive name
set_defaults
Handling Nodes That Already Have Names:
Agent and Menu nodes already store a name field in Customer v2. The emitter slugifies this to snake_case (e.g., "Main Agent" → main_agent).
If two nodes produce the same slug, append _N suffix (main_agent, main_agent_2).
API nodes derive their name from the integration and method identifiers, not from UUIDs.
Say, Transfer, End nodes that have no name in Customer v2 get auto-generated sequential names.
Name as Identity (Parser — YFlow → Customer v2):
The node name is the identity. No UUIDs are generated or stored.
All next: references use names directly — no resolution step needed.
Name uniqueness is enforced within the flow at parse time.
Reporting, analytics, and debugging all use the human-readable name.
2. API Parameters: Variables and Constants
YFlow APIs support variables and constants as parameters to drive conversational behavior in a controlled, secure, and predictable manner. These parameters define what data is available to a flow and how it may be used during evaluation.
Current ( Customer v2 JSON): The requestVariables field maps parameter names to variable names (bare strings). There is no support for constant values — every parameter must be a variable reference.
Target (YFlow): The params: field supports both {variable} references and literal constants (strings, numbers, booleans).
Customer v2 Enhancement Required: Extend requestVariables (or add a parallel field) to distinguish variable references from constants. The parser/emitter must handle both directions:
Direction
`{variable}` param
Constant param
Export (YFlow → Customer v2)
Strip braces, add to variable map
Store as constant (new Customer v2 capability)
Import ( Customer v2 → YFlow)
Wrap in {...}
Emit as bare value
3. Integration Resolution: Optional UUIDs in YFlow
YFlow supports optional UUID‑based integration resolution to flexibly connect conversational flows with external systems, actions, or integrations—without tightly coupling flows to specific implementations.
This mechanism allows flows to remain portable, secure, and environment‑agnostic.
Problem: The runtime resolves API and MCP integrations by UUID only. Integration display names can change. YFlow needs human-readable names for portability, but UUIDs for runtime performance.
Solution: YFlow includes both human-readable names and optional UUID fields (integration_id, method_id, connection_id). The *_id fields are:
Optional — absent in exported/shared YFlow files (portable between environments)
Resolved at save time — when a flow is saved, the resolver populates *_id fields from the integration service
Used at load time — runtime reads *_id fields directly (no lookup needed)
API Node:
An API Node in YFlow represents a declarative interaction point where a conversational flow invokes an external API through a resolved integration. It defines what data is sent, what response is expected, and how the conversation proceeds—without embedding execution logic or code.
Tools/MCP Node:
A Tools / MCP Node in YFlow represents a controlled invocation of an external tool or MCP (Model Context Protocol) capability within a conversational flow. It allows YFlow to safely leverage specialized tools (e.g., retrieval, computation, orchestration, or AI‑assisted functions) without exposing the flow to executable code or system‑level access.
Lifecycle:
Operation
`*_id` fields
Behavior
Save
Absent or stale
Resolver looks up names → populates UUIDs → stores YFlow with IDs
Save
Present and valid
Stored as-is (no lookup needed)
Load
Present
Runtime uses UUIDs directly — no integration service call
Load
Absent
Resolver looks up names → populates UUIDs (fallback)
Export
Stripped
Emit names only — portable YFlow for sharing
Import
Absent
Resolver looks up names → populates UUIDs → save
Error Handling
Error handling in YFlow is explicit, deterministic, and declarative. Rather than relying on exceptions, try/catch blocks, or hidden runtime behavior, YFlow requires all error paths to be clearly modeled in the flow definition.
This ensures failures are safe, observable, and intentional.
Import/Save: If an integration name cannot be resolved, fail with a clear error: "Unknown integration: banking_api".
Load: If a *_id UUID is present but no longer valid (deleted integration), fall back to name lookup. If name also fails, report error.
Export: Always strip *_id fields — exported YFlow is environment-independent.
Last updated
Was this helpful?