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

# Protocols SDK

> @embeddables/protocols — navigate a medical intake protocol and evaluate eligibility from form answers

## Overview

Protocols drives medical intake navigation: it walks the visitor through a protocol's questions, decides which one to show next, and evaluates whether they can continue or are eligible. It reads answers from [Forms](/sdks/forms/overview) — set up Forms first, then Protocols uses those answers as the visitor moves through the flow.

Protocols also needs [Core](/sdks/core/overview), like every other SDK. Answers are linked by each field's `protocolFieldId` in your form setup.

The walkthrough below covers install and wiring. When you need the full instance API, the React hook, or the protocol contract, open the [reference](/sdks/protocols/reference).

## How it fits together

* **Core** initializes once, as it does for every SDK.
* **Forms** must be set up **before** Protocols — Protocols reads form answers; it does not create forms.
* A form field opts into protocol reads by declaring a `protocolFieldId` — supported on `text`, `email`, `boolean`, `select`, and `multiselect` fields (not `number` or `json`, which `em build` rejects). Protocol logic reads that value with `getValueByProtocolFieldId`.
* When two forms declare the same `protocolFieldId`, the later form in the array wins.

<Warning>
  In React, list Forms before Protocols in your `modules` setup (as in the example below). If Forms
  is missing, Protocols cannot start.
</Warning>

## Implementation

### Install

<CodeGroup>
  ```bash npm theme={null}
  npm install @embeddables/core @embeddables/forms @embeddables/protocols
  ```

  ```bash pnpm theme={null}
  pnpm add @embeddables/core @embeddables/forms @embeddables/protocols
  ```

  ```bash yarn theme={null}
  yarn add @embeddables/core @embeddables/forms @embeddables/protocols
  ```
</CodeGroup>

Install [Core](/sdks/core/overview) and [Forms](/sdks/forms/overview) first, then add Protocols.

### Connect a protocol

Connect a ready-made one from the catalog with the [Embeddables CLI](/get-started/em-cli#protocols):

```bash theme={null}
em protocol connect <protocol-id>
```

This downloads the protocol into your project and builds it into `embeddables/_dist`. Import it from there and pass it to `initProtocol` (JavaScript) or `protocols({ protocols })` (React).

### Set up

With the protocol connected and Forms set up, pick your setup:

<Tabs>
  <Tab title="React">
    Follow the example below: enable Forms, then Protocols, in the same `modules` list. Form schemas
    live on `config.forms` from `embeddables/_dist`. Import your protocol from `_dist` after
    `em protocol connect` — the CLI does not plug it in automatically.

    ```tsx lines theme={null}
    import { EmbeddablesProvider } from '@embeddables/core/react'
    import { forms as formsModule } from '@embeddables/forms/react'
    import { protocols, useProtocol } from '@embeddables/protocols/react'
    import { config } from './embeddables/_dist'
    import { myProtocol } from './embeddables/_dist/protocols/my-protocol'

    function IntakeQuestion() {
      const { question, continueStatus, goToNextQuestion } = useProtocol({
        protocolId: 'my-protocol',
      })

      return (
        <div>
          <p>{question?.text}</p>
          <button
            type="button"
            disabled={continueStatus?.status !== 'can_continue'}
            onClick={() => goToNextQuestion()}
          >
            Continue
          </button>
        </div>
      )
    }

    export function App() {
      return (
        <EmbeddablesProvider
          config={{ ...config, publishableKey: 'pk_sandbox_<your-key>' }}
          modules={[
            formsModule(),
            protocols({ formIds: Object.keys(config.forms), protocols: [myProtocol] }),
          ]}
        >
          <IntakeQuestion />
        </EmbeddablesProvider>
      )
    }
    ```

    `formIds: Object.keys(config.forms)` composes every generated form; pass a narrower list if only some
    forms carry `protocolFieldId`s the protocol reads.

    `useProtocol` tracks the current question and whether the visitor can continue. See the
    [reference](/sdks/protocols/reference#react-hook) for the full hook and navigation helpers.

    <Note>
      After you connect a protocol, you still pass it explicitly in `protocols({ protocols: [...] })`, as
      in the example — `em build` does not choose the protocol for you.
    </Note>
  </Tab>

  <Tab title="JavaScript">
    Initialization is two steps: `initProtocols({ core })` validates Core and returns a client, then `.initProtocol({ protocol, forms })` binds your initialized form instances into a `ProtocolInstance`.

    Your form schemas — including each field's `protocolFieldId` — are generated by the [Embeddables CLI](/get-started/em-cli) (`em build`) into `embeddables/_dist`. Spread `config` into Core so schemas register under `config.forms`; import the protocol from `_dist` rather than writing schemas by hand.

    ```typescript lines theme={null}
    import { initEmbeddables } from '@embeddables/core'
    import { initForms } from '@embeddables/forms'
    import { initProtocols } from '@embeddables/protocols'
    import { config } from './embeddables/_dist'
    import { myProtocol } from './embeddables/_dist/protocols/my-protocol'

    const core = initEmbeddables({
      ...config,
      publishableKey: 'pk_sandbox_<your-key>',
    })

    const formsClient = initForms({ core })

    const instance = initProtocols({ core }).initProtocol({
      protocol: myProtocol,
      forms: core.getFormIds().map((formId) => formsClient.getForm({ formId })),
    })

    const firstId = instance.getFirstQuestionId()
    const continueStatus = instance.getContinueStatus(firstId)
    const eligibility = instance.isEligible()
    ```

    Pass every initialized form to `initProtocol` once — instance methods never take a form-data argument, and they read the forms' current values on every call.

    <Note>
      `protocolFieldId` is a **Forms** concept: it lives on each form field in your Embeddables
      config and is emitted by the CLI into `embeddables/_dist`. The protocol never defines form
      schemas — it only reads values by `protocolFieldId`. See [Forms](/sdks/forms/overview) for how
      schemas are generated.
    </Note>
  </Tab>
</Tabs>

<Info>
  Need the full instance API, the React hook, protocol-agnostic helpers, or the `Protocol` contract?
  See the [reference](/sdks/protocols/reference).
</Info>
