Skip to content

Apply the workflow to other documents

Run the workflow on an inbox

By the end of this lesson, you can decide which of your own document types the workflow of this course fits, which two layouts need the file setting, and which checks to configure first.

Lesson 6 of 6~10 min

Lessons 1 to 5 used supplier invoices. After the course, we ran the same workflow on five other document types. This lesson summarizes that test. It has no steps to run, because the test documents are not published. Use the results to plan your own forms, then repeat lessons 1 to 3 with your documents.

All issuers and values are invented. The test used one profile, six forms and 31 PDFs and images, with known right values. Each file adds one difficulty that real documents have. Each form had two markers and one or two format rules. No form had field patterns or line patterns. A first measurement was followed by one round of configuration changes.

Document type Files Difficulties
Bank statement, English 5 Paid out and Paid in columns, three pages, an OD overdraft suffix, a statement without transactions, a scan
Bank statement, German 4 S and H instead of minus and plus, booking dates without a year, a period across New Year
Timesheet 5 Hours in a grid of projects and weekdays with empty cells, a ticked “No” check box, a scan
Utility bill, German 5 Meter readings with thousand dots, gas converted from m³ to kWh, a credit printed without a minus, a meter exchange
Certificate of analysis 5 Specifications as ranges or text, results such as < 0.05 and n.d., two pages with 22 parameters, a scan
Leave request 5 Five check boxes for the leave type, approval check boxes, a half day, a hand-filled scan
No form (letters) 2 The letterhead of a form, but no form

Three full runs through the text of the PDF used gpt-5.6-luna (recorded 2026-11-07). In each run, 24 to 26 of 31 documents were right. Certificates of analysis (15 of 15 reads) and utility bills (15 of 15) were right in all three runs. Bank statements were right in 22 of 27 reads, and none of the five other reads published a wrong value. Three of those five were the correct statement without transactions, which went to review (see Allow an empty table). The other two were sign errors that a check caught. After two changes, sign rules in both bank forms and an empty table allowed, all 9 statements were right in two more runs (recorded 2026-11-10).

These parts of the course carried over without a change:

  • The configuration. The same three levels, JSON schema, check expressions and markers worked for all five document types. No PL/SQL was needed.

  • Check expressions. A model read an OD balance as positive and a German S balance as a credit. One check stopped every such error:

    abs(opening_balance + sum_amount - closing_balance) <= 0.005

    The result went to review instead of being published, so no wrong bank statement was published in the three runs. The check found the errors, and rules in the form then removed their cause. These are two of the rules of the English form:

    "rules": [
    "A balance followed by \"OD\" is overdrawn: return it as a negative number. This applies to the opening and the closing balance too.",
    "Each transaction has one amount, in the Paid out or the Paid in column. The text does not show the column: compare the balance before and after the transaction. Paid out is negative, Paid in is positive."
    ]

    The German form got a rule that S (Soll) is negative and H (Haben) is positive. With these rules, no sign was wrong in the two later runs.

  • Markers. No form was matched wrongly in 93 document reads. The two letters with the letterhead of a form matched no form and went to review.

  • A number rule for German documents. One rule in the form, Numbers use German format: "1.234,56" is 1234.56., was enough for decimal commas, the S and H signs and the conversion from m³ to kWh.

  • Scans. The vision model read 11 of 12 scans correctly in the three runs. With the final configuration, all four scans were right in their last two runs.

All the wrong values that the checks did not catch came from two layouts: timesheets and leave requests. The text of a PDF does not keep the layout of the page, and a check cannot recover information that the text does not contain.

  • A grid with empty cells. The row ELM-2201 | 8.0 | 8.0 | | | | 4.0 | | 20.0 becomes the values 8.0, 8.0, 4.0 and 20.0 one after the other in the text, without the empty cells. The model cannot tell that the 4.0 belongs to Saturday. One timesheet stayed wrong with every model that we tried, because its row totals and daily totals fit more than one grid.
  • Check boxes in two columns. The text lists the left column before the right one, so the X of one leave type appears next to another label. A single choice has no second value to compare with, so no check can catch it.

For these forms, set "model_input": "file". ADM still finds the form with the markers on the text. Then it sends the PDF to the vision_model of the profile.

{
"markers": ["Brightline Staffing Ltd", "^WEEKLY TIMESHEET$"],
"model_input": "file"
}

We measured the eight PDFs of the timesheet and leave forms twice with each setting. The schema, the checks, the rules and the model (gpt-5.6-luna) did not change (2026-11-09).

model_input Right of 8 Prompt tokens for each document Median seconds
text 6, then 4 about 650 2.7
file 8, then 8 about 1850 4.2

The timesheet that was wrong with every model and with reasoning in the text route was right in both runs with the file. The leave request whose X landed next to the wrong label was also right in both runs.

Two runs of eight documents show the effect on the cases that failed. They are not an error rate. The file costs about 2.8 times the prompt tokens and takes about 1.5 seconds more for each document. Set it only on the forms that need it.

The setting needs a vision_model whose provider can read a PDF, and it cannot be combined with a line pattern. Only PDFs and images are sent. See Read the values from the file for the conditions and the limits.

One bank statement had no transactions in the period. The model read it correctly in every run, and every run sent it to review with the issue no line items, because a result without line items is an issue by default. The document type key allow_empty_line_items turns that rule off. Sums of an empty table are null, so write the check with nvl:

{
"allow_empty_line_items": true,
"checks": [
{"name": "opening + transactions = closing",
"expr": "abs(opening_balance + nvl(sum_amount, 0) - closing_balance) <= 0.005"}
]
}

With this setting, the statement without transactions was right in two model runs and did not go to review. A closing balance that is wrong by 1 is still found. See Documents without line items.

Setting Use it when
checks Always. A check that compares printed values with each other turns a wrong value into a review.
json_schema The model puts values in the wrong place. Follow the structure of the paper, including printed totals.
markers Another form or a letter matches. Add a line that only this form has, such as a title.
rules The document uses a format that the model can misread, for example German numbers.
model_input The layout carries meaning: grids with empty cells, check boxes.
allow_empty_line_items An empty table is a valid document.
text_model, vision_model measure with p_model shows that another model is right more often.

A document type is easier to check when its values are printed twice. The bank statements had a balance that must add up, and no wrong value was published. The leave request had one check box for each answer, and through the text 5 of its 15 reads published a wrong value. For a field without a second printed value, such as a check box or a name, decide whether a stronger model, the file, or a review is the better choice.

On the weak forms, a stronger model also helped. gpt-5.6 and gpt-5-mini read all five leave requests right through the text. p_think changed one or two results on gpt-5.6-luna. These runs used few documents, so measure a model on your own forms before you choose it.

The same document with the same configuration changed between right and wrong across runs. The totals moved by two documents of 31 with no change to the configuration. Measure each configuration at least twice before you compare two of them.

  • A form must match exactly once. Test new markers against the letters of the same issuer.
  • A scan without a vision model or OCR goes to review, because there is no text to read.
  • A Word document that matches a form with "model_input": "file" goes to review. So does a file larger than max_file_bytes.
  • If the account of the provider has no credits, every document becomes FAILED with a sentence for the reviewer, and nothing is published. The details are in the debug log.
  • Each document type has at least one check that compares printed values with each other.
  • The test set has real documents of each form, with a scan if you receive scans.
  • measure shows no MISSED in at least two runs.
  • Forms with grids or check boxes read the file, or you accept that they go to review.
  • A vision model or OCR is configured, if scans arrive.
  • Someone owns the tag extraction-review, because these documents wait for a person.

The 31 documents are invented, and the layouts are clean generated PDFs and simulated scans, not faxes or phone photos. All runs used one model family, gpt-5.6-luna unless stated, so other models give other numbers. The rules, the empty-table setting and the switch to the file came from failures on these same documents. So the final results show that the configuration works for these documents. They are not an error rate for new documents of the same kind. The scans were read by the vision model; an OCR provider was not part of the test.