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

# Confirm component

> Ask for one explicit confirm-or-deny decision in the transcript.

## Abstract

Use `confirm` for a consequential binary decision. The two named roles keep confirmation and denial semantics explicit even when the labels are task-specific.

## Preview

<Note>
  TODO: add the real iOS lane capture from `/tmp/relay-component-confirm.png`. This slot intentionally has no fabricated screenshot.
</Note>

## Wire example

```json theme={null}
{
  "send": {
    "conversation_id": "cnv_01JZC7K4RQ",
    "parts": [{
      "type": "data",
      "data": {
        "kind": "confirm",
        "prompt": "Cancel Tuesday's reservation?",
        "confirm": { "id": "yes", "label": "Cancel", "style": "danger" },
        "deny": { "id": "keep", "label": "Keep it" }
      }
    }]
  },
  "stored_part": {
    "part_index": 0,
    "type": "data",
    "data": {
      "kind": "confirm",
      "prompt": "Cancel Tuesday's reservation?",
      "confirm": { "id": "yes", "label": "Cancel", "style": "danger" },
      "deny": { "id": "keep", "label": "Keep it" },
      "fallback": "Cancel Tuesday's reservation?\n1. Cancel\n2. Keep it"
    }
  },
  "tap_result": {
    "parts": [{
      "type": "data",
      "data": {
        "origin": {
          "kind": "data_action",
          "message_id": "msg_01JZM7Q9VN",
          "part_index": 0,
          "option_id": "yes",
          "source_kind": "confirm"
        },
        "option_id": "yes",
        "label": "Cancel"
      }
    }],
    "fallback_text": "Cancel"
  }
}
```

## Schema table

| Field      | Type        | Required | Notes                    |
| ---------- | ----------- | -------- | ------------------------ |
| `kind`     | `"confirm"` | Yes      | Selects this renderer    |
| `prompt`   | string      | No       | Up to 1,024 characters   |
| `confirm`  | option      | Yes      | Confirmation role        |
| `deny`     | option      | Yes      | Denial role              |
| `fallback` | string      | No       | Synthesized when omitted |

Confirm and deny use the [common option fields](/components#common-option-fields), except `description` is not accepted. Their IDs must differ.

## Examples per state

| State                    | Repository artifact                           |
| ------------------------ | --------------------------------------------- |
| Send request             | `examples/components/confirm-send.json`       |
| Canonical stored message | `examples/components/confirm-stored.json`     |
| Tap-result user message  | `examples/components/confirm-tap-result.json` |

## Constraints

| Violation                            | Result                |
| ------------------------------------ | --------------------- |
| Missing `confirm` or `deny`          | `422 invalid_request` |
| Duplicate role IDs                   | `422 invalid_request` |
| Prompt over 1,024 characters         | `422 invalid_request` |
| Invalid option label, style, or URL  | `422 invalid_request` |
| Message targets a group conversation | `422 invalid_request` |

## iOS rendering notes

Render `ComponentConfirm` as a role-styled pair at message width. Keep short labels side by side, then stack the options for accessibility Dynamic Type or longer labels. Use Relay's danger red for destructive confirmation, keep the denial neutral, and apply the shared selected, disabled, in-flight, and retry states.

## See also

* [Message components](/components)
* [Agent permission request](/components/agent_permission_request)
* [Buttons](/components/buttons)
