# 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.

#### &#x20;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:

<table data-header-hidden><thead><tr><th valign="top"></th><th valign="top"></th><th valign="top"></th></tr></thead><tbody><tr><td valign="top">Node Type</td><td valign="top">Name Source</td><td valign="top">Example</td></tr><tr><td valign="top">Start</td><td valign="top">Always start</td><td valign="top">start</td></tr><tr><td valign="top">End</td><td valign="top">end or end_N if multiple</td><td valign="top">end, end_1</td></tr><tr><td valign="top">Agent</td><td valign="top">Existing name field (slugified to snake_case)</td><td valign="top">main_agent</td></tr><tr><td valign="top">Menu</td><td valign="top">Existing name field (slugified to snake_case)</td><td valign="top">main_menu</td></tr><tr><td valign="top">Say</td><td valign="top">say_N (sequential)</td><td valign="top">say_1, say_2</td></tr><tr><td valign="top">API</td><td valign="top">{integration}_{method} from integration/method names</td><td valign="top">banking_api_get_balance</td></tr><tr><td valign="top">Transfer</td><td valign="top">transfer_N or slugified label</td><td valign="top">transfer_to_sales</td></tr><tr><td valign="top">Tools</td><td valign="top">{agent_name}_tools or tools_N</td><td valign="top">main_agent_tools</td></tr><tr><td valign="top">Branch</td><td valign="top">branch_N or descriptive name</td><td valign="top">check_balance</td></tr><tr><td valign="top">Set</td><td valign="top">set_N or descriptive name</td><td valign="top">set_defaults</td></tr></tbody></table>

#### 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.

```
    // Current  Customer v2 — variables only    
    requestVariables: {    
      "accountId": "account_number",     // variable reference    
      "accountType": "account_type"      // variable reference    
      // No way to pass action: "update" as a constant    
    }    
```

Target (YFlow): The params: field supports both {variable} references and literal constants\
(strings, numbers, booleans).

```
# YFlow — mixed variables and constants    
    params:    
      accountId: '{account_number}' # Variable reference    
      accountType: '{account_type}' # Variable reference    
      action: 'update' # String constant    
      version: 2 # Numeric constant    
      includeDetails: true # Boolean constant    
```

Customer v2 Enhancement Required: Extend requestVariables (or add a parallel field) to distinguish\
variable references from constants. The parser/emitter must handle both directions:

<table data-header-hidden><thead><tr><th valign="top"></th><th valign="top"></th><th valign="top"></th></tr></thead><tbody><tr><td valign="top">Direction</td><td valign="top">`{variable}` param</td><td valign="top">Constant param</td></tr><tr><td valign="top">Export (YFlow →  Customer v2)</td><td valign="top">Strip braces, add to variable map</td><td valign="top">Store as constant (new  Customer v2 capability)</td></tr><tr><td valign="top">Import ( Customer v2 → YFlow)</td><td valign="top">Wrap in {...}</td><td valign="top">Emit as bare value</td></tr></tbody></table>

#### 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. &#x20;

```
    - get_balance:    
        type: api    
        integration: banking_api # Human-readable (always present)    
        integration_id: 'a1b2c3d4-...' # Optional — resolved UUID    
        method: get_account_balance # Human-readable (always present)    
        method_id: 'e5f6g7h8-...' # Optional — resolved UUID    
        params:    
          accountId: '{account_number}'    
```

#### 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.

```
     - customer_tools:    
        type: tools    
        tools:    
          - connection: my_mcp_server # Human-readable (always present)    
            connection_id: 'i9j0k1l2-...' # Optional — resolved UUID    
            tools:    
              - get_customer    
              - update_customer    
```

#### Lifecycle:

<table data-header-hidden><thead><tr><th valign="top"></th><th valign="top"></th><th valign="top"></th></tr></thead><tbody><tr><td valign="top">Operation</td><td valign="top">`*_id` fields</td><td valign="top">Behavior</td></tr><tr><td valign="top">Save</td><td valign="top">Absent or stale</td><td valign="top">Resolver looks up names → populates UUIDs → stores YFlow with IDs</td></tr><tr><td valign="top">Save</td><td valign="top">Present and valid</td><td valign="top">Stored as-is (no lookup needed)</td></tr><tr><td valign="top">Load</td><td valign="top">Present</td><td valign="top">Runtime uses UUIDs directly — no integration service call</td></tr><tr><td valign="top">Load</td><td valign="top">Absent</td><td valign="top">Resolver looks up names → populates UUIDs (fallback)</td></tr><tr><td valign="top">Export</td><td valign="top">Stripped</td><td valign="top">Emit names only — portable YFlow for sharing</td></tr><tr><td valign="top">Import</td><td valign="top">Absent</td><td valign="top">Resolver looks up names → populates UUIDs → save</td></tr></tbody></table>

#### 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.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.ixhello.com/ixhc2/technical-specifications/yflow-a-yaml-based-conversational-flow-language.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
