# Extract fields with anchors

Structured extraction whose every value carries a verified anchor.

## When to use it

Extract declared fields and rows with source anchors. Choose static fields or the input-supplied field mode, then define the row grain where relevant. Review missing anchors, unresolved rows, confidence, and coverage rather than accepting an extracted value solely because it is present.

## Add and configure

1. Add **Extract fields with anchors** from the workflow step picker.
2. Give the step a recognisable name and connect its required inputs.
3. Set the options below. Nested names identify fields within an object or a list item.
4. Validate the recipe, inspect the test result, then run it on the intended data.

The step identifier used in the editor’s code view is `extract_anchored`.

## Settings

| Setting | Accepted value | Required | Default | What it controls |
| --- | --- | --- | --- | --- |
| Audit Row Membership (`audit_row_membership`) | boolean | No | false | Opt-in source-anchored membership audit over existing prose row candidates. |
| Concurrency (`concurrency`) | integer; minimum 1; maximum 8 | No | 2 | Maximum items or requests processed concurrently within this step. More concurrency can increase resource use and provider pressure. |
| Emit Manifest (`emit_manifest`) | boolean | No | true | Include the completion manifest used to check the result count and identity. Leave enabled for complete result validation. |
| Fields (`fields`) | list of object; maximum items 50 | No | Not specified | Static field definitions. Choose this mode or resolve the fields from input; the two sources are mutually exclusive. |
| Description (`fields[].description`) | string; maximum characters 1024 | No | "" | Plain-language extraction instructions for this field, including meaning or disambiguation. |
| Name (`fields[].name`) | string; minimum characters 1; maximum characters 128 | Yes | Not specified | Stable field key used to identify the extracted value. |
| Scope (`fields[].scope`) | "per_entity" / "per_document" or null | No | null | Whether this field belongs to each entity row or once to the document. |
| Type (`fields[].type`) | "string" / "number" / "date" / "boolean" | No | "string" | Expected value type. Values must meet this type before they are usable as typed data. |
| Fields From Input (`fields_from_input`) | boolean | No | false | Resolve the field list per run from the step's input records instead of static config (the 'agent proposes a table → accept → auto-populate' flow): the FIRST input record carrying a `fields` key supplies the list, validated by the SAME rules as static config (1..50 entries, FieldSpec name/type/description bounds, duplicate-name refusal). When set, `fields` must be empty/omitted. A missing or invalid input list fails the run with a config-style (invalid_input) error. |
| Group By Field (`group_by_field`) | string | No | "object_key" | Document grouping key. |
| Keep Unverified Values (`keep_unverified_values`) | boolean | No | false | Keep a typed-valid model value as unverified when its quote cannot be found or its value lacks support. These cells have a reason but no verified anchor. Disabled by default. Missing values, invalid types, unreadable sources, provider failures, and unparseable or truncated replies remain errors. |
| Max Calls Per Document (`max_calls_per_document`) | integer; minimum 1; maximum 100 | No | 24 | Hard budget on entity-grain prose enumeration calls per document — batch calls, their re-asks, AND the recovery of a reply the output cap cut (the batch re-run over its two overlapping halves, or the identity round over the same batch) all count; recoveries are bounded by this budget, not reserved against the daily ceiling. An exhausted budget with batches left SURFACES as enumeration_incomplete ('call_cap_reached'), never as a silently complete list. |
| Max Context Chars (`max_context_chars`) | integer; minimum 1000; maximum 500000 | No | 60000 | Maximum source characters supplied in one model prompt. Longer content can be cut at this boundary. |
| Max Entity Rows Per Document (`max_entity_rows_per_document`) | integer; minimum 1; maximum 2000 | No | 500 | Entity-grain cap on enumerated rows per document. Hitting it SURFACES as enumeration_incomplete for that document (the no-silent-caps rule), never as a silently complete list. |
| Max Supplement Calls Per Document (`max_supplement_calls_per_document`) | integer; minimum 1; maximum 100 | No | 16 | Hard call cap for opt-in bounded supplements, including recovery calls. |
| Max Tokens (`max_tokens`) | integer; minimum 64; maximum 16384 | No | 2000 | Maximum tokens in a model reply. A cap that is too small can truncate structured output. |
| Model (`model`) | string | No | "openai:gpt-4.1-mini" | provider:model. |
| Prose Identity First Min Fields (`prose_identity_first_min_fields`) | integer; minimum 2; maximum 50 or null | No | null | Opt-in field-count threshold for enumerating identifiers before cells. |
| Reasoning Effort (`reasoning_effort`) | "minimal" / "low" / "medium" / "high" or null | No | null | Optional reasoning effort, sent only when explicitly set and supported by the selected provider/model. Choose a compatible value; reasoning tokens can consume part of the output token budget, leaving less room for visible structured results. |
| Reconcile Row Entities (`reconcile_row_entities`) | boolean | No | false | OPT-IN. Supported party-grain route P: reconcile enumerated rows against the document's OWN declarations (its schedule/roster of parties, its signature records, its defined terms) before the row cap — a short defined term, a punctuation variant and the uppercase signature form of one party become ONE row, and signature-block roles (the signing officer, the general partner on a `By:` line, the issuer under its own label) are demoted with a citable quote. Every merge, demotion and REFUSAL is disclosed in the manifest's `reconciliation` block. Inert on route T: a mapped, validated grid is the document's own authoritative table. DEFAULT FALSE, deliberately: this handler serves every blueprint that extracts anchored rows, the reconciliation arms are shaped on agreements, and deleting a legitimate party is worse than missing a merge — so a blueprint arms it explicitly once live evidence on ITS documents says it should. False is byte-identical to the behaviour before the reconciler existed. |
| Record Type (`record_type`) | string | No | "extraction" | record_type column stamp for ALL emitted rows. The payload-level record_type discriminates kinds: extracted_field \| extraction_meta. |
| row entity (`row_entity`) | object or null | No | null | The row entity ({label, field_key}) for row_grain='entity' in the STATIC arm; field_key must name one of `fields`. With fields_from_input, the entity rides the SAME per-run input record as `fields` (key `row_entity`) and this must be unset; a run whose carrier declares no row_entity falls back to document grain, byte-identical. |
| Field Key (`row_entity.field_key`) | string; minimum characters 1; maximum characters 128 | Yes | Not specified | Primary field identifying the entity represented by each row. |
| Field Keys (`row_entity.field_keys`) | list of string; minimum items 1; maximum items 50 or null | No | null | Additional field keys used to describe the row entity when supplied. |
| Label (`row_entity.label`) | string; minimum characters 1; maximum characters 128 | Yes | Not specified | Readable row meaning, such as one row per investor. |
| Row Grain (`row_grain`) | "document" / "entity" | No | "document" | What one emitted grid row (and one appended table row) represents. 'document' (default): today's document-scalar contract, byte-identical. 'entity': repeating-group extraction — one row per instance of the declared row entity, emitted as (document x row_index x field) with per-instance anchors. Enumeration is ROUTED: a mappable TABLE-kind segment is parsed deterministically (one row per grid row, the model supplies only a fail-closed header map); prose falls back to a count-committed enumeration ladder with one re-ask and enumeration_incomplete surfacing. |
| Segment Index Field (`segment_index_field`) | string | No | "index" | Segment order field. |
| Segments Per Call (`segments_per_call`) | integer; minimum 1; maximum 50 | No | 6 | Consecutive source segments per model call when enumerating entity rows from prose. Each batch performs its own enumeration and bounded correction; results merge with entity deduplication. This has no effect outside entity-grain prose enumeration. |
| Source Occurrence Hints (`source_occurrence_hints`) | boolean | No | false | Optional literal source navigation for dynamic bounded prose supplements; uses spare context only. |
| Supplement Max Cells Per Call (`supplement_max_cells_per_call`) | integer; minimum 1; maximum 2000 | No | 32 | Row-times-field bound when supplement field batching is enabled. |
| Supplement Max Fields Per Call (`supplement_max_fields_per_call`) | integer; minimum 1; maximum 50 or null | No | null | Opt-in bound on requested fields in each supplement unit. |
| Temperature (`temperature`) | number; minimum 0.0; maximum 2.0 | No | 0.0 | Sampling setting where the model supports it. Fixed-sampling models do not receive this option. |
| Text Field (`text_field`) | string | No | "text" | Segment text field. |
| Timeout Seconds (`timeout_seconds`) | integer; minimum 1; maximum 3600 | No | 120 | Provider-request timeout and per-document retry window; the same setting also bounds the complete step. Allow enough time for all documents and bounded retries, not only a single model call. |

## Inputs and outputs

| Direction | Port | Content | Required | Multiple records |
| --- | --- | --- | --- | --- |
| Inputs | `in` | records | Yes | Yes |
| Outputs | `out` | records | Yes | Yes |

## Effects, testing, and recovery

Calls a model and can consume model budget.

The declared preview behaviour is to execute this step. Reads, processing, or model usage can therefore be real. Read [dry runs](/docs/workflows/dry-runs) before using a preview with live connections.

No duplicate-prevention key is declared for this step. Do not assume that manually repeating the step is free of repeated effects.

## Example: One row of invoice fields per document

Step settings:

```json
{
  "fields": [
    {
      "description": "The invoice identifier as printed",
      "name": "invoice_number"
    },
    {
      "description": "Amount due incl. tax",
      "name": "total",
      "type": "number"
    },
    {
      "name": "issued_on",
      "type": "date"
    }
  ],
  "model": "openai:gpt-4.1-mini"
}
```

Input records:

```json
[
  {
    "index": 0,
    "object_key": "invoices/inv-0042.pdf",
    "text": "Invoice INV-0042"
  },
  {
    "index": 1,
    "object_key": "invoices/inv-0042.pdf",
    "text": "Issued 2026-09-01. Total due: 1,250.00 EUR"
  }
]
```

## Example: One row per investor (entity grain) on a reasoning model

Step settings:

```json
{
  "fields": [
    {
      "name": "investor",
      "scope": "per_entity"
    },
    {
      "name": "shares",
      "scope": "per_entity",
      "type": "number"
    },
    {
      "name": "closing_date",
      "scope": "per_document",
      "type": "date"
    }
  ],
  "max_tokens": 8000,
  "model": "openai:gpt-5-mini",
  "reasoning_effort": "low",
  "row_entity": {
    "field_key": "investor",
    "label": "investor"
  },
  "row_grain": "entity"
}
```

## Example: Fields supplied per run, keeping typed unverified values

Step settings:

```json
{
  "fields_from_input": true,
  "keep_unverified_values": true
}
```

Input records:

```json
[
  {
    "fields": [
      {
        "description": "Renewal period",
        "name": "renewal_term"
      }
    ]
  },
  {
    "index": 0,
    "object_key": "invoices/inv-0042.pdf",
    "text": "Invoice INV-0042"
  },
  {
    "index": 1,
    "object_key": "invoices/inv-0042.pdf",
    "text": "Issued 2026-09-01. Total due: 1,250.00 EUR"
  }
]
```

## Check the result

Inspect the selected run’s status, counts, errors, and output records. An empty collection can be a valid result, and a completed step can contain per-record failures where the step defines that behaviour. Check the next step’s expected record shape before publishing or delivering the result.
