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

# Approval flows

> Design approval flows in Ravenna with templates, sequential and parallel rounds, dynamic approvers like the requester's manager, and workflow timeouts.

Most approval processes fail in the same way: they are correct on paper and slow in practice, so people route around them. This playbook builds flows that are fast in the common case and strict only where strictness pays.

<Info icon="list-check">
  **Prerequisites:** the [Day one](/guides/day-one/overview) track. Approvals attach to tickets, so you need forms and a channel first.
</Info>

<Callout icon="link" color="#6B7280">For a worked department example, see [purchase approvals](/guides/playbooks/finance/purchase-approvals) for threshold routing, [access provisioning](/guides/how-to/setting-up-access-provisioning) for risk tiers, and the [deal desk](/guides/playbooks/revops/deal-desk) for approvals optimized for speed</Callout>

## The model in one paragraph

Adding approvers to a ticket creates a **round**. Each round has a policy that decides when it is satisfied. Rounds run in **stages**: everything in a stage activates together, and the next stage starts only once the current one is fully decided. An **approval template** is a saved set of rounds you apply to a ticket, usually automatically.

<Steps>
  <Step title="Pick the right policy per round">
    | Policy           | Satisfied when                           | Use it for                                              |
    | ---------------- | ---------------------------------------- | ------------------------------------------------------- |
    | Any can approve  | The first approver approves              | A team where anyone authorized can decide. Most rounds. |
    | All must approve | Every approver approves                  | Genuine consensus, such as a security and legal pair.   |
    | Threshold        | A set number approve, for example 2 of 5 | Committee reviews with a quorum.                        |

    A decline in any round declines the ticket immediately, whichever policy is set.

    Default to **Any can approve**. Reaching for **All must approve** is how a two-hour approval becomes a four-day one, because it is gated on whoever is on holiday.

    <Callout icon="link" color="#6B7280">Learn more about [approval policies](/documentation/tickets/approvals/rounds#approval-policies)</Callout>
  </Step>

  <Step title="Run independent reviews in parallel">
    Sequential rounds only make sense when a later approver needs the earlier decision. A manager sign-off and a security review are independent, so they should run at the same time.

    In the round editor, drag one round onto another to merge them into a single stage. An inline indicator shows which rounds are parallel, and the unlink icon splits them apart. Rounds that are already active or decided are locked in place.

    Each round in a stage still enforces its own policy. The stage clears when every round in it is approved.

    <Callout icon="link" color="#6B7280">Learn more about [running rounds in parallel](/documentation/tickets/approvals/rounds#run-rounds-in-parallel)</Callout>
  </Step>

  <Step title="Save it as a template">
    Once a flow works, turn it into a template so it applies the same way every time. A software access template might look like this:

    | Stage | Round              | Policy           | Approvers           |
    | ----- | ------------------ | ---------------- | ------------------- |
    | 1     | Manager approval   | Any can approve  | Requester's manager |
    | 2     | Security review    | All must approve | Security team       |
    | 2     | IT prep            | Any can approve  | IT administrators   |
    | 3     | Executive sign-off | Any can approve  | Department head     |

    Stage 2 starts only after stage 1 clears, and its two rounds run together.

    <Callout icon="link" color="#6B7280">Learn more about [approval templates](/documentation/tickets/approvals/templates)</Callout>
  </Step>

  <Step title="Use dynamic approvers instead of names">
    Hard-coded approver lists rot. Role-based approvers resolve when the template is applied:

    * **Ticket requester**, for acknowledgment steps
    * **Requester's manager**, resolved by cascading through an app-scoped integration, then your organization HRIS, then your identity provider, using the first source that knows the answer
    * **Requester's skip-level manager**, strictly two levels up, for escalated sign-off

    Skip-level resolution is deliberately strict. If the direct manager has no manager of their own, the role is unresolved rather than falling back to the direct manager, because falling back would defeat the point of the escalation.

    For the two manager roles, if nothing resolves, Ravenna substitutes the ticket's workspace admins so the round is never left empty.

    <Callout icon="link" color="#6B7280">Learn more about [dynamic approvers](/documentation/tickets/approvals/templates#dynamic-approvers)</Callout>
  </Step>

  <Step title="Let cheap requests skip the expensive rounds">
    One template can cover a whole family of requests using **skip conditions** on individual rounds. A condition describes when the round is *not* needed, which is the opposite of how most people write it the first time. To require Finance sign-off only above 5,000, give the Finance round the condition `amount <= $5,000`. Small purchases match it and skip the round, large ones do not match and collect the approval.

    Two things to know:

    * Conditions are evaluated once, when the template is applied. Editing the ticket afterwards does not retroactively skip or unskip a round.
    * If every round is skipped for a given ticket, the approval status is set to **Approved** automatically.

    <Callout icon="link" color="#6B7280">Learn more about [skip conditions](/documentation/tickets/approvals/templates#skip-conditions)</Callout>
  </Step>

  <Step title="Keep the requester out">
    By default, the requester is removed from every approval round on their own ticket, including when they would be pulled in through an approver group. Group expansion happens first, then the requester is stripped, and this applies from the sidebar, the rounds UI, workflows, and forms alike.

    The workspace setting **Allow requester as approver** turns that off. Leave it off unless you have a specific reason, such as an acknowledgment round where the requester confirming is the point.

    <Callout icon="link" color="#6B7280">Learn more about [workspace approval settings](/documentation/tickets/approvals/overview#workspace-settings)</Callout>
  </Step>

  <Step title="Approve where people already are">
    Approvers get a Slack DM with the ticket and Approve and Decline buttons, and updates post back to the ticket thread so the team sees movement. On Microsoft Teams the same request arrives as an Adaptive Card in chat.

    If your workspace requires biometric verification, the Slack buttons redirect to the web app to verify identity before recording the decision.

    Nobody has to open Ravenna to approve something, and that fact alone is usually what makes an approval process survive.

    <Callout icon="link" color="#6B7280">Learn more about [where to approve and decline](/documentation/tickets/approvals/overview#where-to-approve-and-decline)</Callout>
  </Step>

  <Step title="Handle the approver who never replies">
    In a workflow, the **Wait for Approval** action pauses until the rounds resolve or the timeout expires, then branches two ways: **On Approved** and **On Declined**. The default wait is three days, and it accepts values like `1h`, `2d`, `1w`, or `Forever`.

    There is no timeout branch, and this is the part people get wrong. **On Declined** fires on an explicit decline only, so when the timeout expires with nobody having decided, neither branch matches and the run ends there. Build the silent-approver path out of a [reminder policy](/documentation/tickets/reminders) plus a **Reminder Expired** workflow, which is where you remind, reassign to a backup approver, or close the request as expired. Without that, a silent approver is indistinguishable from a lost request.

    <Callout icon="link" color="#6B7280">Learn more about [Wait for Approval](/documentation/automate/workflows/triggers-actions#ticket-actions)</Callout>
  </Step>
</Steps>

## Where teams get this wrong

<AccordionGroup>
  <Accordion title="All must approve everywhere">
    It is the slowest option and rarely the required one.
  </Accordion>

  <Accordion title="Sequential rounds that did not need to be">
    If the second approver does not need the first decision, run them in parallel.
  </Accordion>

  <Accordion title="Named approvers in templates">
    People change roles. Use dynamic approvers.
  </Accordion>

  <Accordion title="No timeout branch">
    Build the escalation path when you build the flow, not after the first complaint.
  </Accordion>

  <Accordion title="Approvals on everything">
    Every gate that adds no real judgment teaches people that gates are noise.
  </Accordion>
</AccordionGroup>

## Next

<CardGroup cols={2}>
  <Card title="Access provisioning setup" icon="key" href="/guides/how-to/setting-up-access-provisioning" horizontal>
    Connect approval templates to access policies.
  </Card>

  <Card title="SLAs and business hours" icon="timer" href="/guides/playbooks/slas-and-business-hours" horizontal>
    Measure how long approvals actually take.
  </Card>
</CardGroup>


## Related topics

- [Purchase approvals](/guides/playbooks/finance/purchase-approvals.md)
- [Approval templates](/documentation/tickets/approvals/templates.md)
- [Employee onboarding](/guides/playbooks/hr/employee-onboarding.md)
- [Deal desk](/guides/playbooks/revops/deal-desk.md)
- [Contract review](/guides/playbooks/legal/contract-review.md)
