> ## 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.

# Separate Documents

> Separate a concatenated batch (one big scan) into typed document instances using an LLM. Consumes ai.parse output and a type taxonomy; discovers an unknown number of documents in any order and emits per-document page ranges + text + type, ready for type-specific ai.extract via control.parallel_map. The inverse of ai.split.

`ai.segment`: Separate a concatenated batch (one big scan) into typed document instances using an LLM. Consumes ai.parse output and a type taxonomy; discovers an unknown number of documents in any order and emits per-document page ranges + text + type, ready for type-specific ai.extract via control.parallel\_map. The inverse of ai.split.

## Configuration

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

<ParamField path="input" type="string" required>
  Template expression resolving to ai.parse output, e.g. "\{\{ steps.parse.output }}"
</ParamField>

<ParamField path="documentTypes" type="array<object>" required>
  The document-type taxonomy. The LLM tags each detected document with one of these names, or the reserved "unknown" type when none fit.

  <Expandable title="documentTypes properties">
    <ParamField path="name" type="string" required>
      Type label returned in documents\[].type (e.g. "timesheet", "deal-memo")
    </ParamField>

    <ParamField path="description" type="string">
      What this document type looks like, headings, layout, vocabulary, and the cues that mark its FIRST page. Fed to the LLM for both boundary detection and typing.
    </ParamField>
  </Expandable>
</ParamField>

<ParamField path="rules" type="string">
  Optional natural-language rules appended to the system prompt.
</ParamField>

<ParamField path="provider" type="string">
  Provider ID from eigenpal.config.yaml. Falls back to the tenant default LLM provider when omitted.
</ParamField>

<ParamField path="windowTokenBudget" type="integer">
  Override the per-window token ceiling. Defaults to env SPLIT\_WINDOW\_TOKEN\_BUDGET or 20000.
</ParamField>

## Output

<ResponseField path="summary" type="object" required>
  Batch-level escalation summary: labelled vs unlabelled counts + docs needing review.

  <Expandable title="summary properties">
    <ResponseField path="total" type="integer" required>
      Total documents discovered.
    </ResponseField>

    <ResponseField path="labelled" type="integer" required>
      Documents assigned a known taxonomy type.
    </ResponseField>

    <ResponseField path="unlabelled" type="integer" required>
      Documents the segmenter could not label (type "unknown"), escalate to a human.
    </ResponseField>

    <ResponseField path="lowConfidence" type="integer" required>
      Documents with low boundary/type confidence.
    </ResponseField>

    <ResponseField path="byType" type="record<string, integer>" required>
      Per-type document counts.
    </ResponseField>

    <ResponseField path="needsReview" type="array<object>" required>
      Documents to escalate to a human operator, with the reason for each.

      <Expandable title="needsReview properties">
        <ResponseField path="index" type="integer" required />

        <ResponseField path="type" type="string" required />

        <ResponseField path="page_range" type="array<integer>" required />

        <ResponseField path="reason" type="&#x22;unlabelled&#x22; | &#x22;low_confidence&#x22;" required />

        <ResponseField path="notes" type="string" required />
      </Expandable>
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField path="documents" type="array<object>" required>
  Documents discovered in the batch, in page order. The full batch is covered.

  <Expandable title="documents properties">
    <ResponseField path="index" type="integer" required>
      0-based position of this document in the batch
    </ResponseField>

    <ResponseField path="type" type="string" required>
      Chosen type name from the taxonomy, or "unknown"
    </ResponseField>

    <ResponseField path="page_range" type="array<integer>" required>
      \[startIndex, endIndex] inclusive, 0-based page indices
    </ResponseField>

    <ResponseField path="confidence" type="&#x22;low&#x22; | &#x22;medium&#x22; | &#x22;high&#x22;" required>
      LLM confidence at the boundary + type. Coarse enum (low | medium | high).
    </ResponseField>

    <ResponseField path="notes" type="string" required>
      LLM justification for the boundary, useful for debugging
    </ResponseField>

    <ResponseField path="evidence" type="object">
      Structured start evidence, parse this instead of regexing over `notes`.

      <Expandable title="evidence properties">
        <ResponseField path="start_heading_text" type="string | null">
          Verbatim heading/title text the LLM cited as the document start
        </ResponseField>

        <ResponseField path="start_page" type="integer | null">
          Page where the start appears
        </ResponseField>
      </Expandable>
    </ResponseField>

    <ResponseField path="text" type="string" required>
      Joined per-page content for this document, ready for downstream ai.extract
    </ResponseField>

    <ResponseField path="pages" type="array<object>" required>
      Raw per-page records covered by this document, in page order.

      <Expandable title="pages properties">
        <ResponseField path="pageIndex" type="integer" required />

        <ResponseField path="text" type="string" required />

        <ResponseField path="pageName" type="string" />

        <ResponseField path="source" type="&#x22;anchored&#x22; | &#x22;inferred&#x22;" required />
      </Expandable>
    </ResponseField>

    <ResponseField path="pages_anchored" type="array<integer>" required>
      Pages with direct LLM boundary evidence
    </ResponseField>

    <ResponseField path="pages_inferred" type="array<integer>" required>
      Pages assigned by deterministic continuity fill
    </ResponseField>
  </Expandable>
</ResponseField>
