Docs

#Glossary

A running reference for the terms used across these docs. Most map to a field on a decision or a policy.

#Adapter

The small package that wires Ratifia into a specific engine, e.g. @ratifia/adapter-inngest. It exposes awaitApproval and translates between the engine's pause/resume primitive and a Ratifia decision. One adapter per engine; the rest of Ratifia is engine-agnostic. Adapters are one door of three: agents use the MCP server and everything else the REST API. See caller.

#Approver

A person who can decide, not just an email. An approver carries channels (how we reach them) and methods (which surfaces they can bind a verdict on), each with its own verification state of pending, verified, or failed. email and inbox verify on registration; slack and docusign must be proven first. Only verified approvers count toward a quorum on that surface, which is why an unsatisfiable policy is rejected at save time. Managed in the dashboard under Approvers.

#awaitApproval

The adapter call you add inside your own workflow function to pause for a human: flowplane.awaitApproval(ctx, config). It opens a decision and lets the engine park the run until that decision resolves. Ratifia is a step in your path, not the orchestrator. Its equivalents on the other doors: request_decision + await_decision over MCP, and POST /v1/worker/decisions

  • polling over the API.

#Caller

Whatever asked for the decision: an agent over the MCP server, your own code over the REST API, or a durable workflow through an adapter. Ratifia never runs the caller's work; it only tracks the decision and hands the verdict back. Recorded on the decision as engine.

#Channel

A single mechanism for reaching an approver: email, slack, discord, phone, sms, or webhook. Email, Slack, and Discord are wired today; phone, sms, and webhook are the declared model. See how a person is reached.

#Context

Everything the reviewer sees on a decision: the headline prompt plus structured Present blocks (fields, ai_output, diff, tool_call, text). Context is what makes a Ratifia approval AI-native: the reviewer judges the actual action, not a bare yes/no. See the HITL guide.

#Decision

The root object. A human approval requested at a point in a run, keyed by the caller's run: engine + externalRunId + stepRef. It carries the context, the assignee/approvers, the quorum thresholds, the SLA, the surface, and the verdict, which lives on the decision and nowhere else. Status: PENDING → APPROVED | REJECTED | EXPIRED.

#Engine

The engine field on a decision: which kind of caller opened it, and therefore how it waits. Either mcp (an agent, blocking on await_decision), api (your own code, polling), or inngest (a durable workflow via the adapter, where Ratifia fires the engine's resume event; temporal / trigger planned). Ratifia runs on top of whichever it is and never executes your steps.

#Escalation

Walking an approver's channels in order as the SLA deadline nears, rather than notifying all at once. Not available: approvers are notified at once, and the only timed follow-up is the reminder.

#External run id

The caller's identifier for the run a decision sits on (externalRunId): the engine's run id for a workflow, or whatever an agent or API caller minted. It's how a resolved decision is correlated back to the thing that asked.

#Gate

The decision of whether a human is needed at all, made by the caller with required (default true, so a human is always asked). If it resolves "not required," the request returns approvalNeeded: false (awaitApproval returns immediately) and the run continues without parking.

#Inbox

The reviewer-first dashboard, and the home surface. It lists decisions awaiting a human, sorted by SLA urgency, each with its context. Approving or rejecting here resolves the decision and releases the caller.

#Outbox

The durable, idempotent delivery queue (notification_outbox). Notifications and reminders are written here, then delivered by a sweeper, so a channel outage never drops an ask, and nothing is delivered twice.

#Policy

An org-scoped set of approval defaults: assignee, approver group + quorum, and surface. Referenced by its key, a permanent slug, when opening a decision, so the caller inherits who approves and how they approve. Its name and description are editable labels. Written from two places, both keyed by (org, key) and both rejected if the quorum can never be met: the dashboard under Policies, or the API for the same fields from your own tooling.

#Quorum

The M-of-N approval rule. approvalsRequired approve votes resolve APPROVED; rejectionsRequired reject votes resolve REJECTED (reject-wins by default). Votes dedupe by voter.

#Reminder

A one-time nudge sent to the assignee as the SLA deadline nears, via the outbox.

#SLA

The decision's deadline (timeoutAt). The decisions sweeper sends a reminder as it nears and auto-expires the decision if it passes. The caller sees the reject branch (EXPIRED), so nothing wedges.

#Step ref

The logical id of the gate within a run (stepRef, e.g. human_review) where a decision was requested. Part of the decision's key.

#Surface

How the approver records the binding verdict. inbox (click), email (signed action-link), slack (yes/no buttons), and discord (Approve/Reject buttons) are live today. docusign is a signed envelope with legal weight; api is roadmap. Independent of how the person was notified: you can be reached one way and approve another. A signed surface is how a high-stakes decision is committed, not how it was announced.

#Verdict

The recorded outcome of a decision: approve / reject, plus who decided, when, and any note. It lives on the decision row and is the single source of truth; resolving it releases the caller.