Documentation Index
Fetch the complete documentation index at: https://docs.corti.ai/llms.txt
Use this file to discover all available pages before exploring further.
/documents/sections and /documents/templates API. See Create a Section for the full endpoint mechanics.Why schema is the headline feature
outputSchema on a section does two things at once:
- Declares the shape of what the LLM is allowed to emit — a string, a number, a structured object with named fields, an array of objects, and so on. The model is steered to fit this shape.
- Drives the rendering of that output via format strings (
fieldFormat,itemFormat) so the rendered Markdown/text matches your downstream consumer — an EHR field, a structured pipeline, a free-text note block.
Node types at a glance
outputSchema is one of five node types, discriminated by type. The table lists each type and the fields you can set; bold fields are required, the rest are optional.
type | Use when | Required | Optional |
|---|---|---|---|
string | Free prose, single labels, fixed phrases | type | description, default, enum, pattern |
number | Measurements, counts, scores | type | description, default, enum, minimum, maximum |
boolean | Yes/no facts (e.g. “fasting?”) | type | description, default |
array | Lists of any node type | type, items | description, itemFormat, minItems, maxItems |
object | Structured blocks with named fields | type | description, fields[], fieldFormat |
items can itself be any node — including another array or object. That’s the lever for everything below.
Field reference — what each option does
Most fields are technically optional, butdescription is strongly recommended on every node — it doubles as a prompt to steer the LLM, not just metadata.
Common to all node types
| Field | Purpose |
|---|---|
type | The discriminator. One of string, number, boolean, array, object. Always required. |
description | Prompt text the model sees when generating this part of the output. Optional but strongly recommended — this is your main lever to clarify what this specific node should contain, in addition to the section’s instructions.contentPrompt. |
String-specific
| Field | Purpose |
|---|---|
default | Fallback string if the model has nothing to emit for this node. |
enum | A closed set of allowed values. The model must pick one of these strings. |
pattern | A regular expression the output should match. The model is steered toward emitting a string that conforms (e.g. ^\d{2,3}/\d{2,3}$ for a blood-pressure value). Not a hard validator — pair with enum/description for stricter control. |
Number-specific
| Field | Purpose |
|---|---|
default | Fallback numeric value when nothing applies. |
enum | Closed set of allowed numeric values. |
minimum / maximum | Plausible range bounds. Acts as a prompt anchor as well as validation. |
Boolean-specific
| Field | Purpose |
|---|---|
default | Fallback true/false when the source material is silent. |
Array-specific
| Field | Purpose |
|---|---|
items (required) | The schema for each element. Can be any node type — string, number, object, even another array. |
itemFormat | Per-item rendering. bullet (default), numbered, plain, or a custom string containing {item} (e.g. "Rp. {item}"). |
minItems / maxItems | Bounds on the number of items the model may emit. |
Object-specific
| Field | Purpose |
|---|---|
fields[] | The fixed set of fields the object contains. Each entry requires key, description, and value (any node type). |
fieldFormat | Single unified format string controlling how the object is rendered. Two modes — pick one per object: (a) Per-field iteration with generic {key} and {value} placeholders (e.g. "{key}: {value}\n" for inline subheadings, "{key}\n{value}\n" for block subheadings, "**{key}**: {value}\n" for bold Markdown). The template is applied to every field. (b) Custom layout with specific field-key placeholders that match defined fields[] (e.g. "{test}: {result} ({status})"). The format string is rendered once with all fields substituted. |
Composing schemas — quick reference
| Pattern | Shape | Use for |
|---|---|---|
string | One line of prose | HPI, Chief Complaint, single-paragraph Assessment |
string + enum | One value from a closed set | Triage acuity, urgency, disposition |
number + minimum/maximum | Constrained measure | Vital values, scores, counts |
array of string + itemFormat | Repeating short items | Diagnoses, Medications, Plan items |
array of object (free title) | Dynamic key/value rows | Objective findings, Diagnostic results, Physical Exam |
array of object (enum’d title) | Constrained-key rows | Review of Systems with standardized domains |
object + fieldFormat per-field iteration ({key} / {value}) | Fixed-subheading block, optionally with per-field style rules | Pre-op screening, OT Activity & Participation, pain assessment, fixed-form SOAP-style blocks |
object + fieldFormat custom layout (literal text + {fieldKey} placeholders) | Sentence-template scaffold | Referral letter, discharge letter, any note with fixed phrasing around variable content |
object + fieldFormat custom layout with escaped {{ }} | Layout with literal braces in output | EHR placeholder scaffolds, mixed-type test rows, structured discharge summaries |
Where schema interacts with the rest of the prompt
The model receives, in priority order:- Section
instructions—contentPrompt,writingStylePrompt,miscPrompt. - Template-level instructions —
instructions.prompton the parent template (when used in a template). - Schema-level guidance — every
description,enum,pattern,default,minimum,maximum,minItems,maxItemsyou supply on theoutputSchema.
instructions.contentPrompt for the overall section content/scope; use schema descriptions for field-specific behavior.
Applying a schema to a Corti Standard section
A common pattern is: keep a Corti Standard section’s full prompt machinery (heading, contentPrompt, writingStylePrompt, miscPrompt) but swap its outputSchema for one of the patterns above — e.g. take the curated corti-hpi prompts and emit a structured object for an EHR pipeline.
Two ways to do this:
- Fork the Standard (persistent).
POST /documents/sectionswithinheritFromId: <standard-section-uuid>and onlygeneration.outputSchemain the body. Everything else is inherited. See Corti Standards — overrideoutputSchema. - Override per call (ephemeral). Submit the new
outputSchemainsidetemplateRef.overrides.sections[].generation.outputSchemaonPOST /documents. See Guided Synthesis — Path 2 and Customization Cookbook — Recipe 2.
outputSchema overrides are wholesale — whatever you submit fully replaces the parent’s schema; partial schemas are not merged. When the change is structural (e.g. string → object/array), consider overriding writingStylePrompt in the same request so the parent’s wording rules don’t conflict with the new shape.
Related
Create a Section
Corti Standards
Worked clinical examples
The patterns below are pulled from real Corti standard sections — adapted so you can copy/paste them into your ownPOST /documents/sections request, lift specific fields, or reference them as a parent via inheritFromId.
Each example shows the full outputSchema (you’d wrap it in the standard name/language/generation.instructions/generation.outputSchema envelope from Create a Section).
Example 1 — Fixed subheadings with explicit 'not discussed' vs 'nil' defaults
Example 1 — Fixed subheadings with explicit 'not discussed' vs 'nil' defaults
Not discussed. When the patient explicitly denied something, render Nil. Don’t let the model invent in-between phrases like “patient denies anything noteworthy.”Pattern: object with fieldFormat: "{key}\\n{value}\\n" (per-field iteration), fixed fields[], per-field default, and explicit guidance in each field’s description for the negation rule.fieldFormat: "{key}\n{value}\n" — per-field iteration):Example 2a — Dynamic organ-system labels (free)
Example 2a — Dynamic organ-system labels (free)
title string field (no enum) and a content string field, joined via fieldFormat: "{title}: {content}". The model creates as many entries as needed.Example 2b — Constrained organ-system labels (enum)
Example 2b — Constrained organ-system labels (enum)
title field’s string node carries an enum of allowed values.Example 3 — Structured test results with measures and free-text findings
Example 3 — Structured test results with measures and free-text findings
result string that the model formats consistently (number + unit, or status placeholder for non-numeric studies), plus a typed status enum and a free-text findings field. Numeric typing is preserved per-test through the description instructions; the rendered line stays clean regardless of test type.result is always non-empty, so there’s no double-space gap, and the rendered line works for quantitative labs and imaging studies alike.Example 4 — Prefixes and standard phrasings via `itemFormat`
Example 4 — Prefixes and standard phrasings via `itemFormat`
Rp., and a separate dictation block where every utterance begins with a standard “Pt reports:” header.Pattern: custom itemFormat on the array. The {item} placeholder is the rendered item; everything else around it is literal text.{key}/{value} levers exist on objects via fieldFormat (e.g. "**{key}**: {value}") for Markdown-bold headings, or "## {key}\n{value}" for full Markdown headings.Example 5 — EHR placeholders that survive verbatim
Example 5 — EHR placeholders that survive verbatim
{treatment_shared_motherhood_ivf} — for an EHR system to substitute downstream. The LLM must not generate or paraphrase these; they’re scaffolding for the EHR, not content.Pattern: bake the placeholders directly into fieldFormat as literal text, escaping the curly braces. fieldFormat parses {fieldKey} as a variable substitution; doubled {{ and }} are escapes that render as a single literal { and } in the output. Any clinician-authored content goes into a normal field that is substituted.fieldFormat:- A single
{fieldKey}substitutes the value of that field. - A doubled
{{renders as a literal{in the output;}}renders as a literal}.
{treatment_var} in the output (single braces around a placeholder name), write {{treatment_var}} in the format string — that’s {{ (literal {) + treatment_var (literal text, no substitution because there’s no matching field) + }} (literal }).To emit literal {<value-of-field_1>} (literal braces around a substituted value), write {{{field_1}}} — that’s {{ + {field_1} + }}.To emit double-brace placeholders like {{treatment_var}} literally (Mustache/Handlebars style), each output brace needs its own escape: write {{{{treatment_var}}}} in the format string.{plan_notes}; the EHR placeholders pass through as literal text because their braces are escaped. No extra fields and no enum tricks needed.Example 6 — Different writing styles per subheader via field `description`
Example 6 — Different writing styles per subheader via field `description`
instructions.writingStylePrompt sets the global default; each field’s description carries the local style rule for that subheader. The model reads both and applies the field-level rule where the two disagree.description is enough vs. when to split into multiple sections. Use this pattern when the styles are contrasts within a coherent section that always renders as one block (e.g. a pain assessment). When the subheaders are large enough to be reused independently across templates — or have meaningfully different contentPrompt rules — it’s cleaner to promote each into its own section in the template instead.Example 7 — OT Activity & Participation (ICF-style fixed subcategories)
Example 7 — OT Activity & Participation (ICF-style fixed subcategories)
object + fieldFormat: "{key}\\n{value}\\n" (per-field iteration) + fixed fields[] with a per-field default of "Not assessed". This is the OT-clinic equivalent of the pre-op screening pattern in Example 1.default is "Not assessed". Downstream consumers see a stable structure across encounters.Example 8 — Standard phrases combined with LLM-generated content
Example 8 — Standard phrases combined with LLM-generated content
object + fieldFormat with full sentences containing {field} placeholders. The fixed phrases are just literal text in the format string; each {field} is substituted with model-generated content from fields[].