Skip to content

IDP — Classify

Type: idp-classify  ·  Package: IDP Activities v1.20.4  ·  Output: object

Since: v1.7.0

Reads a document and tells which of the types you list it is. It returns the document already read together with the verdict, so IDP — Extract does not have to read it again. And if the file holds several documents stuck together, it splits them into segments to extract each one separately.

IDP — Classify path = content["path"]
projects = ["supplier-invoice", "purchase-order"]
→ output: doc
If condition = doc["recognized"] == false
Log message = "Not one of the types I know: " + doc["documentType"]

The projects parameter takes the names of extraction projects in the environment. Each project declares its document type and a description; that is what the classifier reads to tell them apart. So the same place where you configure what to extract also defines which types need telling apart — no two lists to keep in sync.

The first project in the list governs how the document is read (reading mode, OCR endpoint and credential) and which model credential is used.

  1. Resolves each name in projects in Zoan Cloud (or parses the inline JSON, for CI).
  2. Reads the document with IDP — Load Document, using the first project’s reading settings.
  3. Classifies each page in a single model call (with AI — Extract underneath): its type and whether it starts a new document. If maskPii is on, the page text goes out with personal data masked.
  4. Groups the pages into contiguous segments and works out whether the split can be trusted (splitNeedsReview).
  5. Returns the document read plus the verdict. The log says how many documents it found across how many pages and, if confidence is low, that it should go to the classification station.
ParameterTypeDefaultDescription
pathstring—Path to the document: PDF, PNG, JPEG or TIFF.
projectsstring | List—The types to tell apart: names of extraction projects in the environment. A single one is a legitimate case. For CI it also accepts an inline project-resolve JSON.
ParameterTypeDefaultDescription
modelstring"claude-opus-4-8"The classifier’s model. Empty uses the provider’s default. Classifying is easy compared to extracting: a small model (for example claude-haiku-4-5) is usually plenty and costs less.
dpiint200The dpi the boxes will come back in. Range: 36 to 1200. It travels with the document to IDP — Extract, so you say it once.
pagesstring— (all)Which pages to read, such as "1-3" or "1-3,5". Empty = all of them.
maskPiibooltrueReplaces the personal data in the document text with placeholders before sending it to the model. Since 1.19.0.

These settings are not shown in the activity panel: they are set in the Lectura y modelo (Reading and model) tab of the extraction project in Zoan Cloud, and the activity takes those of the first project in projects.

Project fieldParameterWhat it controls
Model credentialcredentialYour own model key. Empty, the AI included in your plan.
Reading modemodeauto, text or azure-di.
Azure DI endpointendpointURL of your Azure Document Intelligence resource.
Azure DI credentialazureCredentialKey of your Azure Document Intelligence resource. With the endpoint and credential empty, the reading included in your plan.

No credentials: the AI and the reading included in your plan

Section titled “No credentials: the AI and the reading included in your plan”

Credentials are optional. If neither the activity nor the project has them and your Zoan Cloud plan includes AI and IDP, the model and the scan reading go through Zoan’s accounts via Zoan Cloud: the robot works without creating keys, and the usage (tokens and pages) shows up in AI Usage and counts toward what your plan includes. With your own credentials, calls go straight to your providers and Zoan Cloud only records the usage.

With the included reading, a document that does not fit in the page quota left is rejected before it is read, with the figures, and you never get a partial reading presented as complete (see IDP — Load Document).

It is the whole document —the same one IDP — Load Document returns: path, source, dpi, pageCount, text, markdown, lines, pages, words— plus the verdict and the segments:

FieldTypeWhat it is
documentTypestringThe type of the first segment, or unknown.
recognizedbooltrue if at least one segment has a recognised type. The signal for your If: if it is false, do not extract — to quarantine/review.
segmentsListThe logical documents the file holds, each one { pageStart, pageEnd, type, recognized }. Each segment carries its real type. A single-document file comes out as a single segment.
splitNeedsReviewbooltrue when the split is low-confidence (there are unrecognised pages, or it was split into several with no printed mark at all). It is the signal to send the bundle to the classification station.

Pass it as-is to IDP — Extract in its document parameter and the file is not read again.

It splits files that hold several documents

Section titled “It splits files that hold several documents”

A supplier sends a single PDF with the invoice, the purchase order, the delivery note and attachments, all stuck together. IDP — Classify classifies each page: its type and whether it starts a new document. A boundary opens when the type changes, when the model detects a start (letterhead, a new header, a field that only appears on page 1) or when the printed mark “page 1 of N” appears. With that it groups the pages into contiguous segments, each with its real type.

For Each items = doc["segments"] itemVariable = segment
IDP — Extract document = doc
project = segment["type"]
pages = segment["pageStart"] + "-" + segment["pageEnd"]

When the split isn’t clear: the classification station

Section titled “When the split isn’t clear: the classification station”

Splitting several documents of the same type stuck together with no mark is ambiguous. When confidence is low, IDP — Classify flags it with splitNeedsReview = true. In that case, instead of extracting blindly, you send the bundle to the classification station with Documents — Send Bundle to Classification, a person confirms the boundaries and types, and Documents — Take Confirmed Bundles hands them back for extraction.

If condition = doc["splitNeedsReview"] == true
then:
Documents — Send Bundle to Classification path = file, reference = file,
segments = doc["segments"], document = doc,
pages = doc["pages"], dpi = 200
Continue

The classifier’s enum always includes that value, and it is not a detail.

Without an honest way out, the model picks the least bad type on the list — because the schema forces it to pick one. And a wrong document classified as good is the expensive failure: grounding does not catch it, because it verifies that the text is in the document, not that the document is the one you think. A purchase order has numbers that look like invoice numbers, and they would come out located and with high confidence.

“Is this an invoice, yes or no?” is the most common question in a single-type queue. With one project, the enum is ["supplier-invoice", "unknown"] — and that second option is what makes the question meaningful.

Because what to do with a document that doesn’t belong is a playbook decision. An activity that decides on its own not to do its job hides the control flow, and it also prevents classifying once and routing to the right project — which is the real case of a queue with mixed documents.

Classifying costs a short call: the pages go in, the verdict and segments come out. Extracting costs one call per document with every field, and a much longer answer.

In a reference measurement on a 3-page document, classifying cost about $0.003 and extracting about $0.041. Discarding before extracting saves 95% of the cost of a wrong document — and keeps plausible but false data out of your system.

Classify what arrives in an invoice queue and extract only what is recognised:

IDP — Classify path = content["path"]
projects = ["supplier-invoice"]
model = "claude-haiku-4-5"
→ output: doc
If condition = doc["recognized"] == false
Queue Set Transaction Status item = item status = "successful"
output = { "discarded": true, "type": doc["documentType"] }
Continue
IDP — Extract document = doc
project = "supplier-invoice"
→ output: res
Log message = "Fields to review: " + toString(res["reviewFields"])
MessageCause and fix
'projects' is required. / 'projects' is empty; there is nothing to tell apart.No project was given.
Extraction project '…' does not exist in this environment. Create it in the portal.A name in projects matches no project in the environment. Check the name in Document processing.
'…' is a project name but there is no Zoan Automation runtime to resolve it. Run the playbook from Zoan Automation, or pass an inline project JSON for CI.The run has no Zoan Cloud (for example, from the command line). Run it from Zoan Cloud or from the Designer with a session.
Zoan Cloud could not resolve the extraction project '…' (…): …Zoan Cloud answered with an error while looking up the project. Retry.
File not found. / Invalid page range '…'. … / 'dpi' must be between 36 and 1200. Received: …Reading errors: see IDP — Load Document.
The document has N pages and M are left in your plan's quota this month. … / The reading asks for N pages and M are left in your plan's quota this month. …The document (or the pages range) does not fit in the page quota. Full messages in IDP — Load Document.
The AI usage included in your plan for this month has been reached. Use your own credential or upgrade the plan.The included AI usage is spent. Set your own credential on the project or upgrade the plan.
Choose a credential or turn on the AI included in your plan.Neither the project nor the activity has a credential and your plan does not include AI.
The classifier did not return an answer.The model returned no classification. Retry.