Flow YAML Schema
Overview
Section titled “Overview”Flows are defined in YAML files with the .ygtc extension. This reference covers the complete schema.
Top-Level Structure
Section titled “Top-Level Structure”name: string # Required: Flow identifierversion: string # Required: Semantic versiondescription: string # Optional: Human-readable description
nodes: [] # Required: List of nodestriggers: [] # Required: List of triggersvariables: {} # Optional: Flow-level variablesconfig: {} # Optional: Flow configurationNode Schema
Section titled “Node Schema”nodes: - id: string # Required: Unique node identifier type: string # Required: Node type config: object # Type-specific configuration next: string # Optional: Next node ID on_error: string # Optional: Error handler node ID output: string # Optional: Output variable name timeout: number # Optional: Timeout in millisecondsNode Types
Section titled “Node Types”Send a message response.
- id: greet type: reply config: message: string # Message text buttons: [] # Optional: Action buttons attachments: [] # Optional: File attachmentsCall an LLM.
- id: analyze type: llm config: model: string # Model name (e.g., "gpt-4") prompt: string # User prompt system_prompt: string # Optional: System message temperature: number # Optional: 0-2 (default: 1) max_tokens: number # Optional: Max response tokens output_format: string # Optional: "text" or "json" functions: [] # Optional: Function definitionstemplate
Section titled “template”Render a Handlebars template.
- id: format type: template config: template: string # Inline template template_file: string # Or: Path to template file data: object # Optional: Template datascript
Section titled “script”Execute Rhai script.
- id: calculate type: script config: script: string # Inline script script_file: string # Or: Path to script filebranch
Section titled “branch”Conditional branching.
- id: route type: branch config: conditions: - expression: string # Condition expression next: string # Target node if true default: string # Default node if no matchManage session state.
- id: save type: state config: action: string # "get", "set", "delete" key: string # State key value: any # Value (for "set") output: string # Output variable (for "get")Make HTTP requests.
- id: fetch type: http config: method: string # HTTP method url: string # Request URL headers: object # Optional: HTTP headers body: any # Optional: Request body timeout: number # Optional: Timeout in msEmit an event.
- id: notify type: event config: event_type: string # Event type identifier payload: object # Event payloadadaptive-card
Section titled “adaptive-card”Render an Adaptive Card.
- id: show_card type: adaptive-card config: card: string # Card name (from pack) card_json: object # Or: Inline card JSON data: object # Optional: Card datafast2flow
Section titled “fast2flow”Intent routing.
- id: route type: fast2flow config: config_file: string # Path to fast2flow config fallback_to_llm: bool # Optional: Use LLM for ambiguousflow2flow
Section titled “flow2flow”Invoke sub-flow.
- id: call_sub type: flow2flow config: target_flow: string # Flow to invoke pass_context: bool # Optional: Pass current context input: object # Optional: Input datamcp-tool
Section titled “mcp-tool”Execute MCP tool.
- id: query type: mcp-tool config: tool: string # Tool name parameters: object # Tool parametersTriggers
Section titled “Triggers”Trigger Schema
Section titled “Trigger Schema”triggers: - type: string # Trigger type target: string # Target node ID # Type-specific fieldsTrigger Types
Section titled “Trigger Types”message
Section titled “message”Triggered by incoming messages.
- type: message pattern: string # Optional: Regex pattern target: startdefault
Section titled “default”Catch-all trigger.
- type: default target: fallbackTriggered by events.
- type: event event_type: string # Event type to listen for target: handle_eventScheduled trigger.
- type: timer cron: string # Cron expression timezone: string # Optional: Timezone target: scheduled_taskcallback_query
Section titled “callback_query”Button callback (Telegram).
- type: callback_query target: handle_buttonblock_action
Section titled “block_action”Interactive action (Slack).
- type: block_action target: handle_actionVariables
Section titled “Variables”Define flow-level variables:
variables: max_retries: 3 api_url: "https://api.example.com" welcome_message: "Hello!"Access in nodes:
- id: greet type: reply config: message: "{{flow.welcome_message}}"Configuration
Section titled “Configuration”config: timeout: 30000 # Flow timeout in ms retry_policy: max_retries: 3 backoff: exponential logging: level: debugExpression Syntax
Section titled “Expression Syntax”Expressions use a simple DSL:
# Equalityexpression: "intent == 'greeting'"
# Containsexpression: "message contains 'help'"
# Comparisonexpression: "count > 5"
# Logicalexpression: "is_vip && has_order"expression: "status == 'pending' || status == 'processing'"
# Nested accessexpression: "user.profile.tier == 'premium'"Template Variables
Section titled “Template Variables”Available in all string fields:
| Variable | Description |
|---|---|
{{message}} | Current message text |
{{user_id}} | User identifier |
{{channel_id}} | Channel identifier |
{{session_id}} | Session identifier |
{{tenant_id}} | Tenant identifier |
{{state.*}} | Session state values |
{{flow.*}} | Flow variables |
{{entry.*}} | Entry (incoming) context fields |
{{in.*}} | Alias for {{entry.*}} |
Template Context Alias: in and entry
Section titled “Template Context Alias: in and entry”The template context exposes the incoming message data under the entry key. As of the current version, in is supported as an alias for entry, providing a shorter and more intuitive way to reference incoming data in templates.
Both forms are equivalent:
# Using 'entry' (original)- id: echo type: reply config: message: "You said: {{entry.text}}"
# Using 'in' (alias)- id: echo type: reply config: message: "You said: {{in.text}}"The entry key remains fully supported for backwards compatibility. Existing flows that use {{entry.*}} will continue to work without changes. New flows may use either form; in is recommended for brevity.
Complete Example
Section titled “Complete Example”name: customer_serviceversion: "1.0.0"description: Customer service flow with intent routing
variables: support_email: "support@example.com"
nodes: - id: analyze type: llm config: model: "gpt-4" system_prompt: | Classify intent: greeting, order_status, complaint, other Respond JSON: {"intent": "...", "confidence": 0.0-1.0} prompt: "{{message}}" output_format: json output: intent_result next: route
- id: route type: branch config: conditions: - expression: "intent_result.intent == 'greeting'" next: greet - expression: "intent_result.intent == 'order_status'" next: check_order - expression: "intent_result.intent == 'complaint'" next: escalate default: general_help
- id: greet type: reply config: message: "Hello! How can I help you today?"
- id: check_order type: http config: method: GET url: "https://api.example.com/orders/{{order_id}}" next: show_order_status
- id: show_order_status type: template config: template: | Order #{{order.id}} Status: {{order.status}} ETA: {{order.eta}} next: reply_order
- id: reply_order type: reply config: message: "{{formatted_status}}"
- id: escalate type: reply config: message: "I'm sorry to hear that. Connecting you to support..." next: create_ticket
- id: create_ticket type: mcp-tool config: tool: "create_ticket" parameters: subject: "Complaint from {{user_id}}" message: "{{message}}"
- id: general_help type: reply config: message: | I can help you with: - Order status - Returns - General questions
Contact: {{flow.support_email}}
triggers: - type: message target: analyze