Intent Rules are where you encode deterministic behavior during normal conversation handling. Anything more structured than “answer the question from your knowledge base” lives here: multi-step workflows, conditional escalation, form collection, branching by customer attribute, calling external APIs, and so on. Each Intent Rule is a behavior tree the agent walks when the planner selects it for a customer message. Tree nodes succeed or fail, and that result routes the next node to evaluate. If you’ve configured Actions, Tool nodes in the tree call Actions and bind their outputs to tree variables. Open Rulebook → Intent Rules in the dashboard sidebar. The landing view lists every published rule on the left, with an empty state showing the available node types on the right.
Intent Rules page in the Fini Demo workspace showing published rules such as Request Type Router, Account Perks, Transaction Lookup, and Check Balance, with an empty detail pane prompting the user to select or create an intent rule.
Intent Rule executions are 100% deterministic. Given the same conversation context, a rule produces the same tree walk, the same Tool calls, and the same Reply instructions every time. Determinism is what makes Intent Rules safe to deploy in regulated industries, refunds, account closures, identity verification, claims processing, where unbounded LLM reasoning isn’t acceptable.

What Intent Rules are for

Use Intent Rules for workflows that should run while the agent is handling a customer’s message. They are selected by the planner from the rule’s Description, scoped to assigned agents, and executed as deterministic behavior trees. Intent Rules are separate from Business Rules. Business Rules run from configured business events such as widget escalation; Intent Rules run only when a customer message matches the rule’s intent.

Why a behavior tree

A flat list of “if X then Y” rules works for simple intent routing, but breaks down quickly:
  • A cancellation flow needs to extract a reason, check eligibility, call a billing API, branch on the response, and reply differently in each branch.
  • A refund flow needs to look up the order, validate eligibility, check the policy window, and submit, short-circuiting cleanly at any failure.
  • An address change needs to render a form, validate the input, call the customer’s address-update API, and confirm.
  • A VIP customer override needs to take precedence over several other rules without being copy-pasted into each.
A behavior tree expresses all of that with a small set of composable node types. The tree structure encodes the logic; the nodes encode the work. Production use cases Fini customers handle this way include card delivery and replacement, account cancellations, refund processing, account tier upgrades, address changes, and claims intake. Anything where you’d write a runbook for a human agent maps cleanly to a behavior tree.

Node types

Eight node types, three composite (have children) and five leaf (do work). The legend on the empty Intent Rules page lists them all.

Composite nodes

Composites direct the tree. They evaluate children in order and decide what counts as success or failure for the subtree.

Leaf nodes

Leaves do the work. Each returns success or failure to its parent composite.

How the tree runs

When a relevant message arrives, the runtime walks the tree depth-first from the root. At each node:
  • A Steps parent runs each child in order. The whole Steps fails as soon as one child fails; if all succeed, the Steps succeeds.
  • A Fallback parent runs each child in order. The Fallback succeeds the moment one child succeeds; if all fail, the Fallback fails.
  • A Check evaluates its predicate and returns success or failure.
  • A Read prompts the LLM to extract one or more fields into tree variables. Returns success if extraction populated everything required; otherwise failure.
  • A Tool invokes its configured Action with bound inputs. Returns success on clean response; failure on error.
  • A Reply stages reply instructions for the agent’s composition pass. Always returns success.
  • A Form renders the form in the widget and waits for input. Its children handle validation. Success when input passes validation.

Inactivity follow-ups

A Reply node can schedule a follow-up while the conversation remains Waiting for customer and no new customer message arrives. Turn on Follow up after inactivity, then choose a delay: 12 hours, 24 hours, 48 hours, 72 hours, or 7 days. Under Then, choose Send a follow-up reply or Perform an external action. Reply mode generates one concise follow-up from the current conversation history and the agent’s prompt guidelines. Action mode runs the selected Action without sending a customer-facing reply. For an external action, select the action and configure its inputs. Input values are captured when the wait starts, not looked up again when the delay ends. The action picker excludes actions that require unsupported automatic context bindings; automatic bindings are limited to conversation source and user attributes. Delayed action outputs are not available as new tree variables for subsequent steps. Use inactivity follow-ups when the workflow should nudge the customer after the agent has already asked for missing information or confirmation. For example, after a cancellation flow asks for the account email, a follow-up can remind the customer to send it before the rule can continue.
Follow-up replies are generated from the existing conversation. They should continue the thread, not introduce new offers, policy changes, dates, amounts, or actions that the customer did not already receive.
Fini cancels the scheduled reply or action if the customer sends another message, the conversation is resolved, or the conversation is escalated to a human agent before the delay elapses. Follow-ups are sent through the same connected conversation thread for supported integrations, including Zendesk, Intercom, Gorgias, Front, HubSpot, LiveChat, Slack, Salesforce, Microsoft 365, and Deskpro. Combined, this is enough to express most workflow logic. Two patterns you’ll write often:
  • Intent gate then sequence: a Steps at the root, with a Check as the first child gating the workflow on intent. If the Check fails, the Steps short-circuits and the rule does nothing on this message. If the Check passes, the rest of the Steps runs.
  • Try, fall back, ask: a Fallback whose first child is a Steps (try the primary workflow), and whose second child is a Reply asking the customer for missing information when the primary workflow fails.

How rules get selected

A single agent can have many rules attached. When a customer message arrives, Fini runs a Planning step first: the LLM reads the message and routes it to the rule whose Description best matches the customer’s intent.
  • If a rule is selected, its tree executes.
  • If no rule matches the message, the agent falls through to its default behavior, answering from the knowledge base, asking a clarifying question, or staying silent depending on the Reply Behavior configuration.
  • If a rule executes but stages a Reply, the Reply is what the customer sees. If a rule executes but stages no Reply (e.g., the rule’s only outcome was an internal Tool call), the agent falls through to default reply composition.
The Description is the routing signal. Multiple rules with overlapping Descriptions confuse the selector and cause mis-routes, keep each rule’s Description tight and intent-specific. The AI Steps trace shows which rule the Planner picked on every conversation, so you can verify routing is working.

Inside a Check

A Check node uses the same condition builder as Reply Behavior. You compose predicates over four field categories and the runtime evaluates them. Operators: the same 15 documented in Reply Behavior → Operators, Equals, Not Equals, comparison operators, Contains, Date Before/After, In/Not In, Is Null/Not Null, Is Empty/Not Empty. Predicates inside a group are joined with AND; condition groups are joined with OR.

Tree variables

Tree variables are the values that flow through a rule as it executes. They come from three places:
  • Read nodes extract them from the conversation (e.g., a reason string).
  • Tool nodes populate them with the outputs of an Action (e.g., confirmationId, refundAmount).
  • Form nodes populate them when the customer submits the form (one variable per field).
Once populated, they’re available to every node downstream in the same tree. Reference them by name in:
  • Check predicates: pick the variable from the field dropdown alongside System fields, Tag Groups, and User Attributes.
  • Reply text: interpolate with ${variableName} (e.g., Your refund of ${refundAmount} has been processed.).
  • Tool inputs: bind variables to the Action’s input fields.
Scope and lifetime: tree variables live for the duration of one tree walk. They don’t persist across messages or conversations, each new message starts a fresh execution with no carry-over. What happens on short-circuit: if a Steps short-circuits because a Check failed, any tree variables populated up to that point are discarded. Nothing downstream can reference them.

Observability: the AI Steps trace

Every conversation Fini processes is fully traceable. Open any conversation in the Inbox and look at the AI Steps panel on the right, it shows the complete execution trace for that conversation, including the rule that ran (if any) and every node within it.
AI Steps panel showing the execution trace for a single conversation. Sections labeled Planning, Executed Rule (expanded), Generate Answer, Input Tag Selection, and Output Tag Selection. The Executed Rule section lists every node that ran in order, each with a green or red status dot, the node title, and a colored pill indicating node type (Read, Check, Tool, Reply). Failed nodes are visible alongside successful ones to show exactly where Fallbacks moved on to the next sibling.
This is why Rulebook is trustworthy in production. Every step the agent took, every value it extracted, every API call it made, every reply it composed, all of it is recorded and inspectable per conversation. You can show stakeholders exactly what happened. You can audit decisions retroactively. You can debug failing rules with surgical precision. What the trace shows:
  • Every node that ran, in order, including failed ones. Failure isn’t hidden; it’s how you see why a Fallback walked past one child to the next, or why a Steps short-circuited.
  • Each node’s status, green dot for success, red dot for failure.
  • Each node’s type pill, Read / Check / Tool / Reply / Form, so you can match the trace back to the tree visually.
  • Read outputs, Tool inputs and outputs, and Reply instructions are inspectable (click into the node row to expand).
How to debug a rule with AI Steps:
  1. Find a conversation where the rule should have fired (or shouldn’t have).
  2. Open AI Steps. Look at Planning first, did the LLM route to this rule’s Description? If not, the Description needs tightening.
  3. If the rule did fire, look at Executed Rule: read the trace top to bottom. Find the first red dot. That’s where the rule short-circuited.
  4. Click into the failing node to see what value it had. A Check on customerId failing means customerId wasn’t populated, work upstream to find out why.
You’ll come back to this trace constantly while building Rulebook rules. It’s the answer to “why did the agent do that?” and “why didn’t it do this?” on every conversation.

Anatomy of a rule

A rule has four pieces, all visible in the rule editor. Rules also have draft and published states (covered below in Publishing and assignment).
Selected Intent Rule in the Fini Demo workspace showing the Request Type Router rule details, assigned bots, and behavior tree editor pane.
The Description field is how the LLM selects which rule to run. If your description is vague (“Handles billing stuff”), the LLM will mis-route messages to the wrong rule or skip yours entirely. Write descriptions as if you were teaching the LLM the rule’s trigger: “Use this rule when the customer wants to cancel their subscription. The query could look like: ‘cancel my subscription,’ ‘I want to close my account,’ or ‘stop charging me.’” Concrete example phrases dramatically improve selection accuracy.

Creating a rule

Two creation paths sit at the top of the Intent Rules page.

Generate with AI

The fastest way to a working draft. Click Generate with AI (the sparkles button), describe what you want in natural language and/or upload a workflow diagram, and the LLM produces a complete tree you can refine.
Generate with AI modal with two input sections: a Behavior Instructions textarea with placeholder 'Paste your SOP text or describe the desired behavior...', and an Upload Workflow Diagram dropzone accepting PNG, JPG, JPEG, or PDF up to 10MB. Helper text below: 'Provide behavior instructions, upload a workflow diagram, or both. At least one is required.'
Two inputs, at least one required:
  • Behavior Instructions: paste an SOP, write a description of the workflow, or both. The more concrete and step-numbered the better. “When the customer asks to cancel: (1) extract their reason, (2) verify their account, (3) call the cancel API, (4) confirm with the refund amount.”
  • Upload Workflow Diagram: drag in a PNG / JPG / JPEG / PDF up to 10MB. Flowcharts, decision trees, and even hand-drawn whiteboard photos work. The model reads the diagram and translates branches into Fallbacks, sequences into Steps.
What you can expect from the generated draft:

Create Rule manually

For when you know exactly what tree you want. Click + Create Rule: then build out the tree node by node.
1

Set the title and description

Title shows up in the sidebar; description tells the LLM when to fire this rule (so write it with example trigger phrases, see the warning above).
2

Build the tree

The empty state starts with a single root Steps node. Click + Add step to insert children. Each new node has a configuration panel where you set its predicate (Check), prompt (Read, Reply), Action (Tool), and so on.
3

Assign agents

Pick the agents this rule applies to under Assigned Bots. A rule with no agents assigned never runs.
4

Test before publishing

Use the test panel to walk an example conversation through the tree, see Testing a rule below.
5

Save the draft

Save commits the draft. Drafts never run on live conversations; only published rules do.
6

Publish

Promote the draft to live. From the next conversation onward, assigned agents will execute the rule.

Refining an existing rule

The Refine option (visible when a published rule is open) lets you describe changes in natural language, “also handle the case where the customer mentions a billing dispute”, and the LLM proposes a new tree incorporating your changes. Review the diff, accept, save. Refining is faster than the manual editor for sweeping changes; the manual editor is faster for targeted ones. Use Generate-with-AI for initial drafts, Refine for big-picture changes, and the manual editor for small adjustments.

A worked example: cancellation flow

The canonical rule that handles “I want to cancel” end-to-end.
How this runs:
  1. The root Steps runs children in order. The first child is the intent Check. If the LLM didn’t classify the message as a cancellation, the Check fails, the Steps short-circuits, and the rule does nothing on this message, exactly the behavior you want.
  2. If the intent matches, the next child runs: a Read extracting the customer’s reason into a tree variable.
  3. The second Check verifies the customer is identified (customerId is not null). If it fails, the rule stops here, see the recovery-path note below.
  4. The Tool calls the configured Cancel Subscription Action. Its outputs (confirmationId, refundAmount, effectiveDate) become tree variables.
  5. The final Reply stages a confirmation message with those variables interpolated. The reply composition pass writes it in the agent’s voice.
Graceful recovery for missing customer ID: If you want the rule to ask for the customer’s email when it’s missing instead of silently stopping, wrap the Check: customerId Is Not Null and its downstream nodes in a Fallback that has a second child:
The Fallback tries the first child. If customerId is missing, the Check fails, the Steps fails, and the Fallback moves to the second child, the Reply asking the customer for their email. This is the canonical “try the primary path; fall back if it doesn’t apply” pattern. This is the same flow described in Actions → A worked example; the Action is the Tool node here, and the rest of the work (intent matching, extraction, conditional gating, reply composition) lives in the Rulebook tree.
For an end-to-end walkthrough showing how this rule connects User Attributes, Actions, Reply Behavior, and the Inbox trace, see End-to-end: cancellation flow.

A worked example: address change with Form

Forms collect typed input from the customer with built-in validation. A canonical Form rule:
How Form nodes work:
  • The Form node renders a structured form in the widget. The customer fills it in and submits.
  • Field types (String, Number, Date, etc.) drive input validation.
  • Form Error children let you raise custom validation errors that flag a specific field. The form re-renders showing the error message; the customer corrects and resubmits.
  • A successful submission populates tree variables (one per field). Downstream Tool / Check / Reply nodes can reference those variables with ${field_name}.
Use Form whenever you need structured, typed input from the customer, addresses, phone numbers, dates of birth, account verification details. Forms are also the right tool when you need a record that the customer provided this specific input (forms appear in the conversation transcript as a structured artifact).

Chaining Tools

Tool outputs become tree variables, available downstream. A multi-Tool Steps lets you compose action chains:
If either Check fails, the Steps short-circuits and the rule stops. Wrap the whole Steps in a Fallback, and add a Reply child as the Fallback’s second branch, to handle the denial path with an explanation:
Tool I/O is typed. Action inputs and outputs declare their types (String, Number, Boolean, Date, Object). Tree variables inherit those types. A Check on a Number output uses numeric operators (Greater Than); a Check on a String uses Equals or Contains. Type mismatches surface at design time, not runtime.

Read vs Check vs Reply: when to use which

These are the three most common leaves and easy to confuse. A short discriminator: Reads populate. Checks verify. Replies emit.

Testing a rule

Rulebook gives you two testing surfaces before a rule affects production conversations: generated scenarios for checking every likely branch, and a manual test run for replaying one conversation or custom context.

Suggested scenarios

When a saved version or draft flow is open, the editor derives Suggested scenarios from the behavior tree. Each scenario groups related outcomes, shows the expected path through the nodes, and marks the likely terminal outcome: reply, form, stop, or continue. Open a scenario and click Try to test that path. The dialog has two modes:
  • Try conversation: edit a small simulated conversation history and run the path with those messages.
  • Check scenario: skip message simulation and ask Fini to check the generated path using the scenario’s starting values.
Both modes let you edit the generated input and runtime context before running the check. The result shows whether the run reached the expected terminal node, the values used for the run, and the same node-level execution trace you see in production.
Use Suggested scenarios for branch coverage. They are generated from the rule’s tree, so they surface paths that are easy to miss when you only replay one known conversation.

Manual test run

Every rule also has a ▶ Test Run button that opens a side panel for running the tree against a sample input, without affecting production conversations.
Test Run panel with two input tabs (Conversation Link selected, Custom JSON available), an input field labeled 'Paste conversation link...', and a black Run Test button below.
Two ways to provide input:
  • Conversation Link: paste a URL to a real conversation from your Inbox. The runtime replays the rule against that conversation’s full context (messages, integration provider, channel, tag groups, attributes). Use this to verify the rule behaves correctly on conversations you’ve already seen.
  • Custom JSON: paste a JSON object describing the conversation context. Use this for synthetic edge cases, testing what happens when a User Attribute is null, when a tag group has a specific value, when the customer message contains a particular phrase.
The test panel shows the execution trace as it runs: which nodes evaluated, which passed, which failed, which variables they populated. Same format as the AI Steps trace you’ll use in production.
Test before publishing. A rule mis-routed by a vague description, or a Check that references a User Attribute that isn’t populated yet, will fail silently in production. Suggested scenarios and manual test runs surface both before customers see them.

Publishing and assignment

The sidebar splits rules into Drafts and Published Rules. Drafts are works in progress, edit freely; they don’t affect live conversations. Published Rules run on real customer messages for their assigned agents. Save commits draft edits without publishing. Publish promotes the draft and starts running the rule live. To roll back, edit the draft and re-publish, or delete the rule. Published rules show Unpublished changes only when the draft is newer than the live version. Older drafts are labeled as outdated drafts. They stay available in version history, but opening Edit on the live rule starts from the published version instead of silently resuming outdated content. You can duplicate a published rule (rules in the list with a (copy) suffix are duplicates) to experiment with variants while leaving the original running.

Assigning rules to agents

Every rule has an Assigned Bots list. Only conversations on those agents trigger the rule. A rule with no agents assigned doesn’t run. A single rule can be assigned to multiple agents, e.g., a VIP customer override that applies across every support agent in the workspace. A single agent can have multiple rules attached, see How rules get selected for how the LLM picks one.

How Rulebook interacts with Reply Behavior

These are two different decision layers:
  • Reply Behavior decides whether the agent responds on a conversation, direct reply, internal comment, or stay silent.
  • Rulebook decides how the agent responds when it does, which workflow runs, which Actions to call, what the reply contains.
They evaluate in that order: If Reply Behavior decides No Reply: no Rulebook tree runs at all. If Reply Behavior decides Direct Reply or Internal Comment: the matching Rulebook rule (if any) executes and its Reply nodes inject instructions into the response composition. This means you can use Reply Behavior as a hard gate (“never engage when a human is on the conversation”) and Rulebook for nuanced behavior on the conversations where the agent is engaging.

Why a rule isn’t firing

Only published rules run on live conversations. Open the rule and publish it.
A rule with no entries in Assigned Bots never runs. Open the rule and select the agents it should apply to.
The LLM uses the Description to decide whether to invoke a rule. A vague description (“Handles billing things”) misses messages it should catch. Rewrite the description with concrete example trigger phrases, see the warning under Anatomy of a rule. Confirm in the Inbox’s Planning section whether the LLM routed to your rule.
Your tree probably has a Check near the root that gates the whole branch on an intent or attribute. Open the conversation in the Inbox and look at the AI Steps trace, find the first red dot. That’s where the rule short-circuited.
The LLM read the conversation but didn’t find the value the Read was asking for. Either the customer didn’t provide it, or the extraction prompt isn’t clear enough. Two fixes: tighten the Read’s instructions, or wrap the Read in a Fallback whose second child is a Reply asking the customer for the missing info.
Actions live at the workspace level and are referenced by ID from Tool nodes. If an Action is deleted or its input/output schema changes, every Tool node referencing it breaks. Confirm the Action still exists and its schemas still match.
If a Check references a Tag Group before classification has completed, or a User Attribute that wasn’t fetched (Use in Rulebooks off), the Check fails. Verify the field is available at the point in the tree where the Check sits, Tag Groups in particular are populated after the model has read and tagged the conversation.
If Reply Behavior routed the conversation to No Reply: no Rulebook tree runs. Check the Reply Behavior conditions to confirm the conversation isn’t matching a silence rule.

Deletion

Deleting a rule removes both its draft and published versions. The action is irreversible; the confirmation dialog calls this out. Agents previously assigned to the rule lose access immediately.
Before deleting a published rule, check whether other rules reference its outputs or whether downstream automation depends on its Reply behavior. Deletion is immediate and uncoupled, there’s no warning about downstream dependencies.

Actions

Configure the external APIs that Tool nodes invoke. Actions are workspace-level; Rulebook references them.

Reply Behavior

Decide whether the agent responds at all. Reply Behavior gates run before Rulebook trees.

Tags

Configure the tag groups whose values Check nodes can reference.

Attributes

Define the User Attribute chain that exposes customer fields to Check and Tool nodes.

Inbox

Open any conversation and read the AI Steps trace to see exactly how a rule executed.

Test Suite

Run a rule against a curated set of conversations as a regression test before publishing changes.