# Decisions & approvals

Ask for a verdict — approve, decline, or changes — and let your workflow branch on it without reading labels.

## Decisions & approvals

Plenty of requests exist to get one thing: a yes, a no, or a 'not like that'. The decision question captures that verdict in a shape your automation can branch on directly, without guessing which field held the answer.

<h2 id="why">Why a special question</h2>

<p>
  Every choice already has an <a href="/requests/field-keys#option-keys">option key</a>, so a workflow can branch on any radio. What a
  workflow cannot do is know, across every form that has an approval, which key means "yes": one author's radio says <code>sign_off</code>,
  another's <code>approved</code>.
</p>

<p>
  The <strong>decision question</strong> fixes the names. It is a single-choice question with the field key <code>decision</code>, whose
  three options carry the option keys <code>approve</code>, <code>decline</code> and <code>changes</code>. Its labels stay yours to reword
  and translate; the keys underneath never move. When the recipient picks one, the request ends with an <strong>outcome</strong>. Any radio
  keyed <code>decision</code> whose options carry those three keys counts — the preset just sets them for you.
</p>

<h2 id="insert">Add one to your form</h2>

/</strong> in the editor and pick <strong>Decision</strong> — "Approve, decline, or request changes".',
    },
    {
      title: 'Reword the labels',
      description:
        'You get a question titled "Do you approve?" with the choices Approve, Decline, and Request changes. Rewrite any of them to your own wording — "Sign off", "Reject", "Send back for edits". Translate them like any other content.',
    },
    {
      title: 'Ask why, if you need to',
      description:
        'A verdict alone rarely explains itself. Add a long-text question after it, and show it only for decline and changes with <a href="/building-forms/conditional-logic">conditional logic</a>.',
    },
    {
      title: 'Publish',
      description:
        'Requests created from this published version end with an outcome. Like every field key, decision only exists once the form is published.',
    },
  ]}
/>

> ⚠️ **Only the preset produces an outcome**
> <p>
>     The outcome is read from the question whose field key is <code>decision</code>, and only when the chosen option's key is one of the
>     three. A radio you build by hand with options labelled Approve, Decline and Changes derives exactly those keys, so it works without the
>     preset; a radio with other labels works once you type the three keys in the <a href="/requests/field-keys#option-keys">Keys table</a>.
>   </p>
>   <ul>
>     <li>
>       Delete one of the three options, or retype its key, and publishing warns you: "The decision question is missing an approve, decline or
>       changes option, so requests can complete without an outcome." All three must be there — a decision that can only approve cannot
>       decline.
>     </li>
>     <li>
>       A decision question inside a <a href="/building-forms/repeating-groups">repeating group</a> is an ordinary question and is ignored for
>       the outcome.
>     </li>
>   </ul>

<h2 id="values">The three values</h2>

<p>
  These three values are a public contract, like a field key: an automation, an agent, and a spreadsheet formula all read them.{' '}
  <strong>Add a fourth option and picking it is an ordinary answer, not a verdict</strong> — that request completes with no outcome, rather
  than with a value your receiver has never heard of.
</p>

<h2 id="where">Where the outcome shows up</h2>

```
{
  "id": "evt_...",
  "type": "request.completed",
  "test": false,
  "data": {
    "request": {
      "id": "kd7...",
      "externalId": "run-42",
      "status": "completed",
      "outcome": "changes",
      "context": { "case_id": "CASE-9" }
    },
    "answers": {
      "decision": "changes",
      "reason": "Please split the line items per site."
    }
  }
}
```

<p>
  Branch on <code>data.request.outcome</code>. <strong>status</strong> says whether the request finished; <strong>outcome</strong> says what
  the recipient decided. An expired or canceled request has a status and no outcome, and so does a completed request on a form without a
  decision question.
</p>

<h2 id="agents">From an agent</h2>

<p>
  The MCP tool is <code>editor_insertDecisionQuestion</code>, taking a title and the three labels in the form's language. An agent that
  cannot host a callback endpoint polls <code>request_get</code> instead and reads <code>outcome</code> when the status leaves{' '}
  <code>pending</code>. <a href="/developers/mcp-server#requests">Requests on the MCP server →</a>
</p>

<div class="not-prose grid gap-3 sm:grid-cols-2">
  - [Callbacks & signing](/requests/callbacks) — The full payload and how to verify it.
  - [The Requests page](/requests/managing-requests) — Filter by outcome and follow one request.
  - [Conditional logic](/building-forms/conditional-logic) — Ask for a reason only when it is needed.
  - [Question types](/building-forms/field-types) — Every other question you can ask.
</div>
