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

# Clinical data schemas

> JSON schema configuration for medical documentation generation

The `template` property defines the structure of clinical data that SofIA should generate. It must be a complete JSON Schema Draft-07 schema that specifies the fields, types, and validations required for medical documentation.

<Info>
  The `template` prop accepts a **JSON Schema** defining the report structure. Throughout this page, "template" refers to the prop and "schema" refers to the JSON Schema content.
</Info>

<Warning>
  **Note:** This property was previously called `toolsArgs`/`toolsargs`. The legacy name is still supported but deprecated and will be removed in v2.0. Use `template` instead.
</Warning>

## Accessibility (a11y)

If your integration sends a configuration payload (using `template` or legacy `toolsargs`), you can add an `accessibility` variable at the same level to define visual preferences.

Use the property names exactly as shown below (language-agnostic payload keys). For consistency, each option value is an array of accepted labels/aliases.

```json theme={null}
{
  "template": {
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "general_consultation_v1",
    "type": "object",
    "properties": {
      "diagnosis": { "type": "string" }
    }
  },
  "templateid": "general-consultation-v1",
  "accessibility": {
    "text_size": ["Text size", "Font size", "Large text"],
    "color_contrast": ["Color adjustment", "Color contrast", "High contrast mode"],
    "color_inversion": ["Color inversion"],
    "color_filters": ["Color filters", "Color blindness"],
    "bold_text": ["Bold text"],
    "reduce_transparency": ["Reduce transparency"],
    "grayscale": ["Grayscale"]
  }
}
```

<Info>
  **Recommended technical term:** `Accessibility` (a11y). The number `11` represents the letters between `a` and `y`.
</Info>

<Tip>
  Color and contrast options are often grouped under `Visual accommodations` or `Display preferences`.
</Tip>

## How Templates Work

<Steps>
  <Step title="Input">
    The **JSON Schema template** and **conversation context** are provided to the SofIA SDK.
  </Step>

  <Step title="AI Processing">
    The SDK sends the data via **LangGraph Streaming** for AI processing.
  </Step>

  <Step title="Structured Output">
    The AI generates a **structured report** matching the schema, delivered to the EHR/HIS via the `handle-report` callback.
  </Step>
</Steps>

The `template` defines **what** data to extract. SofIA's AI reads the conversation context and fills the schema fields automatically, delivering a structured JSON report that matches your schema.

## Required structure

The schema must include:

* **\$schema**: Reference to the JSON Schema Draft-07 standard
* **title**: Identifier of the clinical document type
* **type**: Must be "object" for structured documents
* **required**: Array with mandatory fields
* **properties**: Detailed definition of each field

<Warning>
  The `template` prop alone does not enable report generation — you must also set `templateid`. Without both props, SofIA operates in chat-only mode: audio transcription and clinical chat remain fully functional, but the generate button is hidden because there is no schema to send to the AI agents for structured data extraction.
</Warning>

## Basic example

```json theme={null}
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "create_clinical_notes/v1",
  "type": "object",
  "required": ["primary_diagnosis"],
  "properties": {
    "primary_diagnosis": {
      "type": "string",
      "description": "Patient's primary diagnosis",
      "source": "your-custom-master"
    },
    "symptoms": {
      "type": "array",
      "description": "List of observed symptoms",
      "items": {
        "type": "string"
      }
    },
    "physical_examination": {
      "type": "object",
      "properties": {
        "blood_pressure": {
          "type": "object",
          "properties": {
            "systolic": {"type": "number", "minimum": 50, "maximum": 250},
            "diastolic": {"type": "number", "minimum": 30, "maximum": 150}
          }
        },
        "heart_rate": {
          "type": "number",
          "description": "Heart rate in beats per minute"
        }
      }
    }
  }
}
```

### Passing templates to the component

**As an HTML attribute** — wrap the JSON in single quotes, use double quotes inside:

```html theme={null}
<sofia-sdk
  template='{"$schema":"http://json-schema.org/draft-07/schema#","type":"object","properties":{"diagnosis":{"type":"string"}}}'
></sofia-sdk>
```

**Programmatically (recommended for complex schemas)** — set via JavaScript:

```javascript theme={null}
const sofia = document.querySelector('sofia-sdk');
sofia.template = mySchemaObject;
// Or as string:
sofia.setAttribute('template', JSON.stringify(mySchemaObject));
```

## Clinical coding sources

There are two ways to get standardized clinical codes into a field:

1. **Set the field's `source` to a master.** A *master* is a controlled terminology or code catalog that Omniloy maintains for your account. The `source` value links the field to that master, so SofIA normalizes the extracted value against it.
   Need coding against **your own data** — a custom catalog, an internal code set, or a specialty terminology? [Contact support@omniloy.com](mailto:support@omniloy.com): the Omniloy team provisions the **custom master** for your account and gives you the `source` value to use. A custom `source` only works once its master has been created for your account.
2. **Ask for the terminology in the field `description`** — e.g. `"Primary diagnosis with its ICD-10 code"`. SofIA's agents apply the requested coding during extraction even without a `source`. This is handy for one-off coding requests where a dedicated master isn't needed.

## Specialized fields

### Medical terminology sources

Point a field at a custom master with `source` (provisioned by Omniloy — see [Clinical coding sources](#clinical-coding-sources)). You can also drive the coding from each field's `description`, as shown below. Replace `"your-custom-master"` with the `source` value Omniloy gives you:

```json theme={null}
{
  "diagnosis": {
    "name": "diagnosis",
    "type": "array",
    "items": {
      "type": "object",
      "required": [
        "code",
        "name"
      ],
      "properties": {
        "code": {
          "type": "string",
          "description": "Diagnosis code using the ICD-10 and being as specific as possible with the provided information."
        },
        "name": {
          "type": "string",
          "description": "Diagnosis name using the ICD-10."
        },
        "description": {
          "type": "string",
          "description": "Justification or description of the diagnosis using the ICD-10."
        }
      }
    },
    "source": "your-custom-master",
    "description": "List the diagnosis/diagnoses determined during this medical consultation, including name, description (justification), and ICD-10 code if applicable. If no diagnosis is explicitly stated, suggest the most likely possibilities based on the conversation."
  }
}
```

### Structured vital signs

```json theme={null}
{
  "vital_signs": {
    "type": "array",
    "description": "Patient's vital signs",
    "items": {
      "type": "object",
      "required": ["parameter", "value"],
      "properties": {
        "parameter": {
          "type": "string",
          "enum": ["Systolic Blood Pressure", "Diastolic Blood Pressure", "Heart Rate", "Temperature", "O2 Saturation"]
        },
        "value": {"type": "number"},
        "unit": {"type": "string"},
        "measurement_date": {"type": "string", "format": "date-time"}
      }
    }
  }
}
```

## Supported data types

### Basic types

* **string**: Free or controlled text
* **number**: Numeric values (integers or decimals)
* **boolean**: True/false values
* **array**: Lists of elements
* **object**: Complex nested structures

### Advanced validations

```json theme={null}
{
  "age": {
    "type": "number",
    "minimum": 0,
    "maximum": 150,
    "description": "Patient age in years"
  },
  "email": {
    "type": "string",
    "format": "email",
    "description": "Contact email address"
  },
  "birth_date": {
    "type": "string",
    "format": "date",
    "description": "Birth date (YYYY-MM-DD)"
  },
  "gender": {
    "type": "string",
    "enum": ["Male", "Female", "Other", "Not specified"],
    "description": "Patient gender"
  }
}
```

## Technical limitations

* **Maximum size**: 100 KB per schema
* **Depth**: Maximum 10 nesting levels
* **Complexity**: Avoid overly complex schemas that may affect performance

## Best practices

### Detailed descriptions

Provide clear and specific descriptions for each field:

```json theme={null}
{
  "description": "Primary diagnosis according to established clinical criteria, using ICD-10 terminology when possible"
}
```

### Appropriate validations

Implement validations that reflect clinical reality:

```json theme={null}
{
  "weight": {
    "type": "number",
    "minimum": 0.5,
    "maximum": 500,
    "description": "Patient weight in kilograms"
  }
}
```

### Flexible structures

Design schemas that allow for clinical variability:

```json theme={null}
{
  "medications": {
    "type": "array",
    "items": {
      "type": "object",
      "required": ["name"],
      "properties": {
        "name": {"type": "string"},
        "dose": {"type": "string"},
        "frequency": {"type": "string"},
        "administration_route": {"type": "string"}
      }
    }
  }
}
```

## Property Customization

### The `isConfigurable` property

**Default value:** `true` (all fields are configurable by default)

When `isConfigurable` is `true` (default), the healthcare professional can edit the generated field value in the SofIA interface before finalizing the report. Set to `false` for fields that should be generated but not editable.

**Configurable field (default behavior):**

```json theme={null}
{
  "treatment_plan": {
    "isConfigurable": true,
    "type": "string",
    "description": "Recommended treatment plan"
  }
}
```

**Non-configurable field:**

```json theme={null}
{
  "diagnosis": {
    "isConfigurable": false,
    "name": "diagnosis",
    "type": "array",
    "items": {
      "type": "object",
      "required": [
        "code",
        "name"
      ],
      "properties": {
        "code": {
          "type": "string",
          "description": "Diagnosis code using the ICD-10 and being as specific as possible with the provided information."
        },
        "name": {
          "type": "string",
          "description": "Diagnosis name using the ICD-10."
        },
        "description": {
          "type": "string",
          "description": "Justification or description of the diagnosis using the ICD-10."
        }
      }
    },
    "description": "List the diagnosis/diagnoses determined during this medical consultation, including name, description (justification), and ICD-10 code if applicable. If no diagnosis is explicitly stated, suggest the most likely possibilities based on the conversation."
  }
}
```

## Debugging your template

### Enable debug mode

Add `debug="true"` to the SofIA component to enable detailed console logging. All SDK logs are prefixed with `[Sofia SDK]`, making them easy to filter in browser DevTools.

```html theme={null}
<sofia-sdk
  debug="true"
  apikey="your-api-key"
  userid="user_12345"
  patientid="patient_67890"
  templateid="your-template-id"
  template='{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "title": "Clinical Notes",
    "type": "object",
    "properties": {
      "diagnosis": {"type": "string", "description": "Primary diagnosis"}
    },
    "required": ["diagnosis"]
  }'
></sofia-sdk>
```

<Tip>
  In your browser DevTools Console, use the filter `[Sofia SDK]` to isolate SDK logs from other application output.
</Tip>

### Template validation checklist

Before debugging in the browser, verify these five points:

1. **Valid JSON Schema** — includes `"$schema": "http://json-schema.org/draft-07/schema#"` header
2. **Both `template` and `templateid` are present** — the generate button only appears when both are provided
3. **`properties` defined with at least 1 field** — an empty `properties` object results in chat-only mode
4. **Schema size under 100KB** — larger schemas are rejected
5. **`required` fields match existing properties** — any mismatch causes validation errors

### Console log reference

When `debug="true"` is enabled, these are the key messages related to templates and report generation:

| Console message                                       | Meaning                                                           | Action                                                                                           |
| ----------------------------------------------------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------ |
| `[Sofia SDK] Settings - Template loaded: {n} fields`  | Template was parsed successfully with `n` fields                  | None — this is the expected success message                                                      |
| `[Sofia SDK] Settings - Template validation failed`   | Template JSON is malformed or missing required schema keys        | Check JSON syntax and ensure `$schema`, `type`, and `properties` are present                     |
| `[Sofia SDK] Settings - Using fallback template`      | Local template was invalid; SDK fell back to server-side template | Fix the local `template` prop — check for syntax errors or invalid field types                   |
| `[Sofia SDK] API - Report generation started`         | User clicked Generate; processing has begun                       | None — wait for completion or failure                                                            |
| `[Sofia SDK] API - Report generation completed`       | Report was generated and delivered to `handleReport`              | Verify the data in your `handleReport` callback                                                  |
| `[Sofia SDK] API - Report generation failed: {error}` | Report generation encountered an error                            | Check the error message for details (`configError`, `authError`, `apiError`, or `settingsError`) |

### Common issues

<AccordionGroup>
  <Accordion title="Generate button doesn't appear">
    **Symptom**: The SofIA component loads in chat-only mode — no generate button is visible.

    **Cause**: The generate button requires both `template` and `templateid` to be present and valid. If either is missing or if the template has zero parseable fields, `hasTemplateConfig` evaluates to `false` and the button is hidden.

    **Solution**:

    1. Verify both `template` and `templateid` attributes are set on the component
    2. Enable `debug="true"` and look for `Template loaded: {n} fields` — if `n` is 0 or the message doesn't appear, the template is invalid
    3. Validate that `template` contains at least one property inside `properties`
  </Accordion>

  <Accordion title="handleReport returns an empty object">
    **Symptom**: The `handleReport` callback fires but the report object is `{}` or contains only empty values.

    **Cause**: The template fields don't match the conversation context. SofIA extracts data based on what was discussed — if the conversation doesn't contain information relevant to your template fields, those fields will be empty.

    **Solution**:

    1. Ensure the conversation covers topics related to your template fields before clicking Generate
    2. Check that field `description` values are clear and specific — vague descriptions lead to poor extraction
    3. Enable `debug="true"` and verify `Report generation completed` appears (not `failed`)
  </Accordion>

  <Accordion title="handleReport returns partial data">
    **Symptom**: Some fields in the report are populated but others are missing or null.

    **Cause**: The AI could only extract data for fields that were discussed in the conversation. Fields marked as `required` in your schema are prioritized, but optional fields may be omitted if the conversation doesn't contain relevant information.

    **Solution**:

    1. Review which fields are missing — do they correspond to topics discussed in the conversation?
    2. Add more specific `description` values to help the AI identify relevant information
    3. Consider marking critical fields as `required` in your schema
  </Accordion>

  <Accordion title="Template falls back to server defaults">
    **Symptom**: The generated report uses a different structure than your local template. In debug mode, you see `Using fallback template`.

    **Cause**: The SDK couldn't parse your local `template` prop. It attempts three parsing strategies (JSON.parse, prefix removal, Function eval) — if all fail, it falls back to the server-configured template for your `templateid`.

    **Solution**:

    1. Validate your template JSON at [jsonlint.com](https://jsonlint.com)
    2. Ensure the template is passed as a valid JSON string, not a JavaScript object
    3. Check for special characters or encoding issues in the template string
    4. In debug mode, look for `Template validation failed` for specific error details
  </Accordion>
</AccordionGroup>

## Verifying handleReport output

Use the following pattern to inspect the report data in your browser console:

```javascript theme={null}
function handleReport(report) {
  // Log the full report for debugging
  console.log('[My App] Report received:', JSON.stringify(report, null, 2));

  // Compare report keys with expected template fields
  const expectedFields = ['primary_diagnosis', 'symptoms', 'physical_examination'];
  const receivedFields = Object.keys(report);
  const missingFields = expectedFields.filter(f => !receivedFields.includes(f));

  if (missingFields.length > 0) {
    console.warn('[My App] Missing fields:', missingFields);
  }

  // Process the report in your application
  // ...
}
```

<Tip>
  Use `JSON.stringify(report, null, 2)` for a formatted view of the report object. This makes it easier to spot missing or unexpected values compared to the default `console.log` output.
</Tip>

For more debugging tools and how to read SDK logs, see [Troubleshooting — Debugging and Logging](/sofia/en/sdk/troubleshooting#debugging-and-logging).
