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

# Extract Data

> Extract structured data from text using AI with a JSON schema

`ai.extract`, Extract structured data from text using AI with a JSON schema

Use `ai.extract` after parsing or collecting text when you need typed JSON back:
invoice fields, contract clauses, email metadata, line items, or classifications
with supporting fields.

Keep the schema as narrow as possible. Enum fields work well for closed choices,
and descriptions should explain business meaning, not just repeat the field
name. For deterministic calculations after extraction, pass the output into
`transform.script` instead of asking the model to do math.

## Grounding and confidence (on by default)

Every extraction also runs a grounding pass: each extracted field is traced
back to the exact place in the input text it came from, and gets a confidence
level. The result lands under a reserved `_grounding` key in the step output,
keyed by field name, so downstream steps can reference it directly:

```yaml theme={null}
# {{ steps.extract-invoice.output.vendor }}                        -> "Acme Corp"
# {{ steps.extract-invoice.output._grounding.vendor.confidence }}  -> "high"
# {{ steps.extract-invoice.output._grounding.vendor.needsReview }} -> false
```

* `high` means the value appears verbatim in the source text, `medium` means it
  matches approximately (formatting or currency drift) or is derived from a
  highlighted source passage through a transformation the model attested (for
  example a date normalized from "January 25, 2016" to "2016-01-25"; the span
  carries `alignment: "match_derived"`), and `low` means no supporting source
  passage could be located (possible OCR error or hallucination).
* Fields at or below the `reviewOn` threshold carry `needsReview: true` and a
  `reason`, so a downstream condition or approval step can route them to a
  human. By default only `low` fields are flagged; set
  `reviewOn: medium_or_low` to also flag approximate and derived matches.
* `source_span` holds the character range of the value in the input text; the
  run view highlights it when you open a field in the Grounding panel.
* Long documents are chunked automatically; no tuning is needed.

The pass uses your workspace default model unless `groundingModel` picks a
different one. When no model is available it falls back to deterministic text
matching and marks the result with `_grounding._degraded: true` instead of
failing the run. Set `grounded: false` to turn grounding off for a step, or
`grounded: true` to make a missing grounding model fail the run instead of
degrading.

Note that grounding confidence measures whether the value is present in the
source text, not whether OCR read the original document correctly. For numeric
cross-checks (for example rate times hours equals gross), add a
`transform.script` step.

```yaml theme={null}
- name: extract-invoice
  type: ai.extract
  with:
    input: "{{ steps.parse.output.text }}"
    schema:
      type: object
      properties:
        vendor:
          type: string
        total:
          type: number
      required: [vendor, total]
```

## Configuration

Configuration goes inside the step's `with:` block.

<ParamField path="input" type="string" required>
  Text content or template expression
</ParamField>

<ParamField path="schema" type="object" required>
  JSON Schema defining the structure to extract

  <Expandable title="schema properties">
    <ParamField path="type" type="string" required />

    <ParamField path="properties" type="record<string, unknown>" required />

    <ParamField path="required" type="array<string>" />
  </Expandable>
</ParamField>

<ParamField path="prompt" type="string">
  Custom prompt template for extraction
</ParamField>

<ParamField path="provider" type="string">
  Provider ID (e.g., "openai-gpt4o")
</ParamField>

<ParamField path="model" type="string">
  Model override
</ParamField>

<ParamField path="maxInputTokens" type="integer">
  Max input tokens. Truncates input text and logs a warning when exceeded. Omit for no limit.
</ParamField>

<ParamField path="grounded" type="boolean">
  Grounding is ON by default: each schema field gets a source span + confidence (high=verbatim, medium=fuzzy, low=ungrounded) under a reserved `_grounding` output key, and fields whose value cannot be located in the source are flagged for human review. Values stay the reliable schema-typed ones. The pass runs through the workspace LLM (any provider) and chunks long documents automatically. Tri-state: unset (default) = on, degrading gracefully to deterministic text alignment (`_grounding._degraded: true`) if no grounding model is available; `true` = strict, the step fails when the grounding model cannot be resolved; `false` = off, no `_grounding` key at all.
</ParamField>

<ParamField path="groundingModel" type="string">
  Provider/model for the grounding pass. Defaults to the workspace default LLM. Any configured provider works; the pass only fails the step when `grounded: true` is set explicitly and no model resolves.
</ParamField>

<ParamField path="groundingExamples" type="array<object>">
  Optional few-shot examples pinning grounding to verbatim source text per field.

  <Expandable title="groundingExamples properties">
    <ParamField path="text" type="string" required />

    <ParamField path="extractions" type="array<object>" required>
      <Expandable title="extractions properties">
        <ParamField path="field" type="string" required />

        <ParamField path="text" type="string" required />
      </Expandable>
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="reviewOn" type="&#x22;medium_or_low&#x22; | &#x22;low_only&#x22;">
  Which grounding confidences set needsReview on a field. Default: low\_only (only fields whose value could not be located in the source). Use medium\_or\_low to also flag approximate and derived matches.
</ParamField>

## Output

Returns `record<string, unknown>`. Extracted structured data matching the provided schema. Unless grounding is disabled (grounded: false), the output also carries a reserved `_grounding` map keyed by field name: `_grounding.&lt;field> = &#123; confidence: high|medium|low, needsReview, reason?, source_span: &#123; start, end, text, alignment } | null }`, plus reserved `_degraded: true` / `_reason` markers when the grounding LLM pass could not run.
