Add a FLOW section to a hotel booking agent, giving it structured steps that guide users through a reservation process. By the end, you know how to:
- Define a flow with named steps and transitions
- Use GATHER to collect information from users
- Add conditional branching with ON_INPUT and ON_RESULT
- Handle tool call results within flow steps
- Implement validation and correction patterns
Prerequisites
What You’ll Build
A hotel booking agent with a FLOW section that walks users through structured steps: entering a destination, selecting dates, searching for hotels, choosing a room, entering guest details, and confirming the booking. Each step collects specific information before moving forward. The agent is the same kind of agent you built in the first tutorial — you are simply adding structured steps via a FLOW block.
Create hotel_booking.agent.abl and start with the agent definition and tools:
Step 2: Add a FLOW Section
Add the FLOW block to give the agent structured steps. Any agent can include a FLOW section — it does not change the type of agent, it just adds a step-by-step structure to the conversation:
The steps list declares the order of steps. Each step name maps to a definition below. The first step in the list is the default entry point.
Step 3: Add the Welcome Step
Within a flow, each step can set REASONING: false to follow exact rules without LLM reasoning, or REASONING: true to use the LLM for that step. Since agents reason by default, REASONING: true is the default for flow steps — you only need to set REASONING: false explicitly when you want deterministic, non-LLM behavior. The RESPOND block sends a message to the user. THEN transitions to the next step.
Add the destination, dates, and guest count steps:
GATHER collects one or more pieces of information from the user. Each field specifies:
- name — The variable name to store the value
- required — Whether the field must be provided
- type — The expected data type (string, number, date, email, phone)
- prompt — The question shown to the user
When a step has multiple GATHER fields, the Runtime collects them in a natural conversational flow. Users can provide multiple values in a single message.
Add the hotel search step with result handling:
The CALL keyword executes a tool with session variables as arguments. ON_SUCCESS runs when the tool returns data, and ON_FAIL runs when it fails. The response template uses Handlebars syntax ({{#each}}, {{name}}) to render dynamic data.
Add the hotel selection step with input validation:
ON_INPUT provides conditional branching based on what the user enters. Each branch has:
- IF — A condition to evaluate against the input
- SET — Variable assignments (optional)
- RESPOND — A message to send (optional)
- THEN — The next step to transition to
The ELSE branch catches any input that doesn’t match the preceding conditions.
Step 7: Collect Guest Details
The type: email declaration tells the Runtime to validate the input as an email address. If the user provides an invalid format, the Runtime re-prompts automatically.
Step 8: Confirm and Complete the Booking
Nested CALL inside ON_INPUT executes the tool only when the user confirms. The special step name COMPLETE ends the session. Failed bookings loop back to the confirmation step.
Step 9: Add the Completion Condition
Step 10: Test the Complete Flow
Open the Chat panel and walk through the booking:
- The agent greets you and asks for a destination
- Enter “Paris” — the agent asks for dates
- Enter check-in and check-out dates — the agent asks for guest count
- Enter “2” — the agent searches for hotels and shows results
- Enter a hotel number — the agent asks for guest details
- Provide name, email, and phone — the agent shows a summary
- Type “confirm” — the booking completes
Open the Traces panel to see each step as a separate trace span. The flow transitions appear as arrows between steps.
Complete Agent Definition
What You Learned
- The FLOW block adds structured steps to any agent for step-by-step conversations
- GATHER collects typed information from users with prompts and validation
- REASONING: false makes a step follow exact rules without LLM reasoning; REASONING: true (the default) uses the LLM
- CALL executes tools with session variables as arguments
- ON_SUCCESS and ON_FAIL handle tool results
- ON_INPUT provides conditional branching based on user input
- SET assigns values to session variables
- THEN transitions to the next step; THEN: COMPLETE ends the session
- Handlebars templates (
{{variable}}, {{#each}}) render dynamic data in responses
Next Steps
When building flows, use REASONING: true on steps where you want the LLM to handle edge cases naturally. Reserve REASONING: false for deterministic validation and branching logic.