Skip to main content
Nodes are stateless building blocks that transform document data. Each node performs a specific operation and can be chained together in flows.

Available Nodes

NodeDescriptionProvider
parseConvert documents to DocumentIR using OCR or VLMOCR or VLM
extractExtract structured data matching a JSON SchemaVLM or LLM
splitIdentify document boundaries in multi-doc PDFsVLM
categorizeClassify documents into predefined categoriesVLM
chunkSplit documents into chunks for RAG/embeddingsNone
combineMerge results from parallel processingNone
outputControl which data is returned from a flowNone

Import

All nodes are exported from @docloai/flows:
import {
  createFlow,
  parse,
  extract,
  split,
  categorize,
  chunk,
  combine,
  output
} from '@docloai/flows';

Basic Usage

Nodes are functions that return configured node objects. Use them with createFlow().step():
const flow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('extract', extract({ provider: llmProvider, schema }))
  .build();

const result = await flow.run({ base64: documentData });

Node Types

Provider Nodes

Nodes that require an AI provider to process documents:
  • parse - Requires OCR or VLM provider
  • extract - Requires VLM (for images/PDFs) or LLM (for text)
  • split - Requires VLM provider
  • categorize - Requires VLM provider

Utility Nodes

Nodes that transform data without calling external providers:
  • chunk - Splits DocumentIR into smaller pieces
  • combine - Merges results from parallel operations
  • output - Selects and transforms final output

Common Patterns

Direct VLM Extraction

Fastest path for simple documents:
const flow = createFlow()
  .step('extract', extract({
    provider: vlmProvider,
    schema: invoiceSchema
  }))
  .build();

OCR → LLM Extraction

Most accurate path for text-heavy documents:
const flow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('extract', extract({
    provider: llmProvider,
    schema: invoiceSchema
  }))
  .build();

Split → Process Each

Handle multi-document PDFs:
const flow = createFlow()
  .step('split', split({
    provider: vlmProvider,
    schemas: { invoice: invoiceSchema, receipt: receiptSchema }
  }))
  .forEach('process', (doc) =>
    createFlow()
      .step('extract', extract({
        provider: vlmProvider,
        schema: doc.schema
      }))
  )
  .step('combine', combine())
  .build();

Categorize → Route

Route to different schemas:
const flow = createFlow()
  .step('categorize', categorize({
    provider: vlmProvider,
    categories: ['invoice', 'receipt', 'contract']
  }))
  .conditional('extract', (data) => {
    const schemas = {
      invoice: invoiceSchema,
      receipt: receiptSchema,
      contract: contractSchema
    };
    return extract({
      provider: vlmProvider,
      schema: schemas[data.category] || genericSchema
    });
  })
  .build();

Consensus Support

Most provider nodes support consensus voting for improved accuracy:
const flow = createFlow()
  .step('extract', extract({
    provider: vlmProvider,
    schema: invoiceSchema,
    consensus: {
      runs: 3,
      strategy: 'majority'
    }
  }))
  .build();
See Consensus Voting for details.

Node Execution

Each node execution produces:
  • Output: The transformed data
  • Metrics: Duration, cost, token usage
const result = await flow.run({ base64: pdf });

// Access per-step metrics
result.metrics.forEach(m => {
  console.log(`${m.step}: ${m.ms}ms, $${m.costUSD}`);
});

// Access intermediate outputs
const parseOutput = result.artifacts['parse'];
const extractOutput = result.artifacts['extract'];

Next Steps