Skip to main content
The output node explicitly controls what data is returned from a flow, allowing you to select from artifacts, transform results, and name outputs.

Basic Usage

import { createFlow, extract, output } from '@docloai/flows';

const flow = createFlow()
  .step('extract', extract({
    provider: vlmProvider,
    schema: invoiceSchema
  }))
  .step('output', output({ name: 'invoice_data' }))
  .build();

Configuration Options

output({
  name: 'result',              // Optional output name
  source: 'extract',           // Select from specific step
  transform: 'pick',           // Transform strategy
  fields: ['id', 'amount']     // Fields to pick
})

Options Reference

OptionTypeDescription
namestringName for this output
sourcestring | string[]Step ID(s) to pull from
transformstringTransform strategy
fieldsstring[]Fields to pick (for ‘pick’ transform)
customTransformfunctionCustom transform function

Selecting Sources

Previous Step (Default)

Without configuration, returns output of previous step:
const flow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('extract', extract({ provider: llmProvider, schema }))
  .step('output', output())  // Returns extract output
  .build();

Specific Step

Select output from a specific step:
const flow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('extract', extract({ provider: llmProvider, schema }))
  .step('output', output({ source: 'parse' }))  // Returns parse output
  .build();

Multiple Steps

Combine outputs from multiple steps:
const flow = createFlow()
  .step('step1', extract({ provider: vlmProvider, schema: schema1 }))
  .step('step2', extract({ provider: vlmProvider, schema: schema2 }))
  .step('output', output({
    source: ['step1', 'step2'],
    transform: 'merge'
  }))
  .build();

Transform Strategies

Pick

Select specific fields from the output:
output({
  transform: 'pick',
  fields: ['invoiceNumber', 'totalAmount', 'date']
})
Input:
{
  "invoiceNumber": "INV-001",
  "totalAmount": 1250,
  "date": "2024-01-15",
  "lineItems": [...],
  "vendor": {...}
}
Output:
{
  "invoiceNumber": "INV-001",
  "totalAmount": 1250,
  "date": "2024-01-15"
}

Merge

Merge multiple sources into one object:
output({
  source: ['header', 'items', 'totals'],
  transform: 'merge'
})

First / Last

Return first or last non-null result:
output({
  source: ['primary', 'fallback'],
  transform: 'first'
})

Custom Transform

Apply a custom transformation function:
output({
  transform: 'custom',
  customTransform: (input, artifacts) => {
    return {
      ...input,
      processedAt: new Date().toISOString(),
      metadata: {
        parseTime: artifacts['parse'].metrics?.ms,
        extractTime: artifacts['extract'].metrics?.ms
      }
    };
  }
})

Named Outputs

Name outputs for identification:
output({ name: 'invoice_extraction_result' })

Use Cases

Clean Output

Remove internal fields:
const flow = createFlow()
  .step('extract', extract({ provider: vlmProvider, schema: fullSchema }))
  .step('output', output({
    transform: 'pick',
    fields: ['id', 'amount', 'date', 'vendor']
  }))
  .build();

Combine with Metadata

Add processing metadata:
const flow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('extract', extract({ provider: llmProvider, schema }))
  .step('output', output({
    transform: 'custom',
    customTransform: (data, artifacts) => ({
      result: data,
      metadata: {
        pageCount: artifacts['parse']?.pages?.length,
        processingTime: Date.now()
      }
    })
  }))
  .build();

Multiple Output Formats

Create different views:
// Full output
const fullFlow = createFlow()
  .step('extract', extract({ provider: vlmProvider, schema }))
  .step('output', output({ name: 'full' }))
  .build();

// Summary output
const summaryFlow = createFlow()
  .step('extract', extract({ provider: vlmProvider, schema }))
  .step('output', output({
    name: 'summary',
    transform: 'pick',
    fields: ['id', 'total', 'status']
  }))
  .build();

Without Provider

The output node doesn’t require an AI provider—it performs local data selection and transformation:
output()  // No provider needed

Next Steps