> ## Documentation Index
> Fetch the complete documentation index at: https://docs.usefini.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Reply Rules

> Decide when your agent posts a direct reply, leaves an internal note, or stays silent, using conditions on integration, channel, conversation state, attributes, and tags.

Reply Rules decide what your agent does on each incoming conversation: reply directly to the customer, leave an internal note for your team, or stay silent. Rules live in one place and apply across every integration you've connected. A *"stay silent when a human is already on it"* rule covers Zendesk, Intercom, Front, and any other channel at the same time.

<Frame>
  <img src="https://mintcdn.com/fini/zctNPVP1t-q6dPqV/images/en/automations/reply-behavior/cards.png?fit=max&auto=format&n=zctNPVP1t-q6dPqV&q=85&s=e03819a01086c002f544cece4b6dec7d" alt="Reply Rules page showing the No Reply, Internal Comment, and Direct Reply cards. Each card carries an icon, status pill, condition count, description, and enable toggle." width="1680" height="1050" data-path="images/en/automations/reply-behavior/cards.png" />
</Frame>

<Tip>
  For a walkthrough showing how Reply Behavior interacts with Attributes, Actions, and Rulebook end-to-end, see [End-to-end: cancellation flow](/en/walkthroughs/cancellation-flow).
</Tip>

## Product location

Open **Rulebook → Reply Rules** in the dashboard sidebar. This docs page covers only Reply Rules. Intent Rules and Business Rules have their own pages.

## The three reply types

The page shows three cards, one per reply type. Each card is independent, you can configure rules on all three, just one, or none.

| Reply type | Subtitle in the UI | Visible to |
| - | - | - |
| **No Reply** | Bot will not respond to the customer. | Nobody, no message is posted. |
| **Internal Comment** | Bot adds an internal note visible only to your team. | Your team only. |
| **Direct Reply** | Bot sends a response directly to the customer. | Customer and your team. |

Terminology for the internal note varies by integration, *Internal Note* in Zendesk and Intercom, *Internal Comment* in Front, *Case Comment* in Salesforce. The behavior is the same: customer-invisible.

### When multiple cards match

The three cards evaluate independently, a single conversation can match conditions on more than one. When that happens, the **stricter behavior wins**, in this priority order:

1. **No Reply**, highest priority. If a conversation matches a No Reply condition, the agent stays silent, even if Internal Comment or Direct Reply conditions would also match.
2. **Internal Comment**, wins over Direct Reply. If a conversation matches both an Internal Comment and a Direct Reply rule, the agent posts internally instead of publicly.
3. **Direct Reply**, the default. Fires only when no higher-priority card matches.

The principle: **picking a stricter behavior is always a safe override.** You don't have to engineer mutually exclusive conditions, layer broad rules with narrower overrides.

For example: a broad Direct Reply rule applies normally; a narrower Internal Comment rule overrides it for sensitive topics; a No Reply rule overrides everything else when a human is on the conversation.

## When answer generation fails

On supported integration channels, an unrecoverable model failure during planning, knowledge search, input-tag selection, or answer generation changes the outcome to an internal failure note and human escalation instead of sending the failure text as a customer reply. A **No Reply** decision remains silent. Failure in output-tag selection alone does not trigger this fallback after a valid answer has been generated.

The destination depends on the integration's handoff support. Slack has no provider-side transfer path for this fallback: Fini records the no-reply outcome rather than posting the failure text into the channel. Inspect the conversation in [Inbox](/en/testing/inbox) when investigating a missing reply.

## What you can match on

Inside each card, the condition builder offers fields from three categories. The dropdown organizes them, System fields at the top, then your Tag Groups, then your User Attributes.

<Frame>
  <img src="https://mintcdn.com/fini/zctNPVP1t-q6dPqV/images/en/automations/reply-behavior/condition-fields.svg?fit=max&auto=format&n=zctNPVP1t-q6dPqV&q=85&s=0247dec2668771ee7b393317bf487b57" alt="Field picker dropdown inside the condition builder, showing three categorized sections. SYSTEM contains Integration Provider, Channel, Human Agent Assigned, Escalated Conversation. TAG GROUPS contains the active tag groups (e.g. Type of Issue, Sentiment, Product Area, Knowledge Gap). USER ATTRIBUTES contains the custom fields returned by the User Attributes API (e.g. plan, accountTier, signupDate)." width="720" height="620" data-path="images/en/automations/reply-behavior/condition-fields.svg" />
</Frame>

### System fields

Always available. Resolved before any AI classification happens.

| Field | What it captures |
| - | - |
| **Integration Provider** | The integration the conversation came from, e.g. `zendesk`, `intercom`, `front`. Use to scope rules to a specific channel surface. |
| **Channel** | The channel within the integration, e.g. `email`, `chat`. Useful when one integration carries multiple channel types. |
| **Human Agent Assigned** | `True` if a human teammate is currently assigned to the conversation, `False` otherwise. The standard field for "don't let the agent talk over a human." |
| **Escalated Conversation** | `True` if the conversation has been escalated to a human (via the agent's escalation path or a manual handoff). |

### Tag Groups

Every tag group configured for this account appears in the dropdown, General Tags, Errors, Type of Issue, Sentiment, and any custom groups you've built. Match against the tag values the model applies (e.g. *Type of Issue equals `disputes`*, *Sentiment equals `negative`*).

See [Tags](/en/configuration/tags) for how groups and their tag values are configured.

### User Attributes

Every attribute returned by your User Attributes API appears here, plan tier, signup date, country of residence, package name, whatever your endpoint exposes. Use these to match on properties of *who* the customer is, not what the conversation is about.

See [Attributes](/en/api-reference/attributes) for how the attribute chain is configured.

<Tip>
  Tag Group rules wait for classification; System and User Attribute rules don't. Tag values are populated by the model after it reads the conversation, so a rule like *Sentiment equals negative → No Reply* only fires once tagging completes. Rules on Integration Provider, Channel, Human Agent Assigned, Escalated Conversation, and User Attributes resolve immediately on receipt of the conversation.
</Tip>

## Operators

Each predicate has an operator that controls how the field is compared against the value. The dropdown offers fifteen operators covering single-value comparisons, list membership, date ranges, and presence checks.

| Operator | What it does | Common use |
| - | - | - |
| **Equals** / **Not Equals** | Exact match on a single value. | The default. Most predicates use these. |
| **Greater Than** / **Less Than** | Numeric comparison. | Numeric attributes, *credit score \< 600*, *days since signup > 30*. |
| **Greater Than or Equal To** / **Less Than or Equal To** | Inclusive numeric comparison. | Same as above but inclusive of the boundary value. |
| **Contains** | Substring match within a string field, or value present in a multi-value field. | Free-text fields, or tag groups configured as multi-select. |
| **Date Before** / **Date After** | Date comparison, parsing the value as a date. | Date-typed attributes, *signupDate Date Before 2026-01-01*. |
| **In** / **Not In** | Value matches *any* of a list of options (or none of them). | Multiple acceptable values for one field, *Type of Issue In disputes, refunds, chargebacks*. |
| **Is Null** / **Is Not Null** | The field is missing entirely (or is present). | Detecting when an attribute hasn't been populated yet. |
| **Is Empty** / **Is Not Empty** | The field is present but the value is empty (or non-empty). | Distinguishing *"never fetched"* from *"fetched but blank"*. |

<Tip>
  The **In** operator is what *"or check items in a list"* (the link to the right of each condition group) creates, a single predicate that matches multiple values. Use it instead of writing three separate OR'd groups when the values differ only in the right-hand side.
</Tip>

## Building a rule

Click a card to expand it. The conditions builder uses two levels of grouping: **predicates inside a group are joined with AND; groups are joined with OR.**

<Frame>
  <img src="https://mintcdn.com/fini/zctNPVP1t-q6dPqV/images/en/automations/reply-behavior/card-expanded.png?fit=max&auto=format&n=zctNPVP1t-q6dPqV&q=85&s=ebb78abc17868c29b9c9b297c0bd270e" alt="Reply Rules page in the Fini Demo workspace with No Reply, Internal Comment, and Direct Reply expanded to show their condition groups, enabled states, and save controls." width="1680" height="1050" data-path="images/en/automations/reply-behavior/card-expanded.png" />
</Frame>

<Frame>
  <img src="https://mintcdn.com/fini/zctNPVP1t-q6dPqV/images/en/automations/reply-behavior/condition-builder.svg?fit=max&auto=format&n=zctNPVP1t-q6dPqV&q=85&s=60d5fb0d886f87a0b1559eaf0d8828c0" alt="Expanded card showing two condition groups separated by an OR divider. The first group has IF Integration Provider Equals zendesk, AND Human Agent Assigned Equals True. The second group has IF Type of Issue In disputes, refunds, AND Sentiment Equals negative. Each group has Add another check and 'or check items in a list' affordances, and at the bottom is an Add alternative condition button." width="1000" height="640" data-path="images/en/automations/reply-behavior/condition-builder.svg" />
</Frame>

<Steps>
  <Step title="Pick the card">
    Click the card for the behavior you want to trigger (No Reply / Internal Comment / Direct Reply). The card expands to show the conditions builder.
  </Step>

  <Step title="Add predicates to the first condition group">
    Under **When should this check pass?**, each `IF` / `AND` row is a predicate. Pick a field, pick the operator (typically *Equals*), and pick or type the value. All predicates in a group must be true for the group to match, they're joined by AND.
  </Step>

  <Step title="Add an alternative group (OR)">
    Click **+ Add alternative condition** at the bottom. A new group appears below an **OR** divider. The card matches if *any* group matches, within each group, *all* predicates still have to match.
  </Step>

  <Step title="Enable the card">
    Toggle the switch in the card's top-right to on. The card needs at least one complete condition before it can be enabled.
  </Step>

  <Step title="Save">
    Saving commits the rule. Unsaved edits prompt a confirmation if you navigate away.
  </Step>
</Steps>

## Example rules

Five patterns drawn from common configurations. The Conditions column shows what goes in the condition builder; OR-joined condition groups are stacked with an **OR** divider between them.

| Pattern | Card | Conditions | Effect |
| - | - | - | - |
| **Stay silent when a human is on the conversation** | No Reply | `Human Agent Assigned Equals True` | The agent never replies on conversations a teammate has already picked up. |
| **Stay silent on escalated Zendesk conversations** | No Reply | `Integration Provider Equals zendesk` AND `Human Agent Assigned Equals True`<br />**OR**<br />`Integration Provider Equals zendesk` AND `Escalated Conversation Equals True` | On Zendesk, the agent stays out of the conversation either when a human is assigned *or* when the conversation has been escalated. This is the exact pattern visible in the screenshot above. |
| **Internal note instead of direct reply on refunds** | Internal Comment | `Type of Issue Equals refunds` | When the agent classifies a conversation as a refund issue, it drafts a note for the team rather than replying to the customer. |
| **No reply for Enterprise accounts** | No Reply | `plan Equals enterprise`<br />*(assuming your User Attributes API exposes a `plan` field)* | Every Enterprise customer goes straight to a human; the agent doesn't engage. |
| **Block specific channels** | No Reply | `Integration Provider Equals zendesk` AND `Channel Equals chat`<br />**OR**<br />`Integration Provider Equals slack` | The agent stays silent on Zendesk chat and all Slack channels. Useful when piloting on email only. |

## Why a rule isn't firing

<AccordionGroup>
  <Accordion title="The card isn't enabled" icon="toggle-off">
    Saving conditions does not auto-enable the card. The toggle in the card's top-right must be on. Look for the green `Enabled` pill next to the card's name.
  </Accordion>

  <Accordion title="A higher-priority card matched first" icon="layer-group">
    No Reply beats Internal Comment beats Direct Reply. If the conversation matches both the card you expected and a stricter one, the stricter card wins. Open the suspect conversation in the Inbox and check whether a No Reply or Internal Comment rule fired instead of the Direct Reply you were testing.
  </Accordion>

  <Accordion title="A Tag Group condition is waiting on classification" icon="clock">
    Rules that reference a Tag Group only fire once the model has tagged the conversation. If you're testing on a brand-new conversation that hasn't been classified yet, the rule won't appear to fire. Open the conversation in the Inbox and check the **AI Steps** panel under Output Tag Selection to confirm the tag was applied.
  </Accordion>

  <Accordion title="A User Attribute condition references a missing field" icon="circle-question">
    User Attributes come from your User Attributes API. If the field name in your condition doesn't match what the API returns (typo, casing mismatch, attribute not yet added to the chain), the predicate evaluates to false. Check [Configuration → Attributes](/en/api-reference/attributes) to confirm the field is configured and returning a value.
  </Accordion>

  <Accordion title="The Integration Provider value is wrong" icon="plug">
    Integration Provider values are exact strings (`zendesk`, `intercom`, `front`, etc.), case matters. If the predicate uses *Zendesk* but the system stores *zendesk*, the rule won't match. The condition builder's dropdown shows the canonical values.
  </Accordion>

  <Accordion title="A predicate row was left incomplete" icon="circle-exclamation">
    A predicate with no value selected evaluates to false, which can prevent its group from matching. Walk through each row in the expanded card and confirm every field, operator, and value is filled in.
  </Accordion>
</AccordionGroup>

## Related

<CardGroup cols={2}>
  <Card title="Tags" icon="tag" href="/en/configuration/tags">
    Configure the tag groups whose values you reference in Reply Behavior conditions.
  </Card>

  <Card title="Attributes" icon="id-card" href="/en/api-reference/attributes">
    Define the User Attributes API chain that exposes customer fields for matching.
  </Card>

  <Card title="Rulebook" icon="bolt" href="/en/automations/rulebook">
    Once Reply Behavior decides the agent should reply, the Rulebook decides *how*, which flow, which actions, which response template.
  </Card>

  <Card title="Inbox" icon="inbox" href="/en/testing/inbox">
    Audit Reply Behavior decisions by opening a conversation and reading the **AI Steps** panel to see which fields matched.
  </Card>
</CardGroup>


## Related topics

- [API overview](/en/api-reference/overview.md)
- [Update reply rule](/en/api-reference/update-reply-rule.md)
- [Get reply rules](/en/api-reference/get-reply-rules.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.