> ## Documentation Index
> Fetch the complete documentation index at: https://docs.doclo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Categorize Node

> Classify documents into predefined categories using VLM

The `categorize` node uses VLM to classify documents into one of your predefined categories, enabling conditional routing in flows.

## Basic Usage

```typescript theme={null}
import { createFlow, categorize, extract } from '@doclo/flows';
import { createVLMProvider } from '@doclo/providers-llm';

const vlmProvider = createVLMProvider({
  provider: 'google',
  model: 'google/gemini-2.5-flash',
  apiKey: process.env.OPENROUTER_API_KEY!,
  via: 'openrouter'
});

const flow = createFlow()
  .step('categorize', categorize({
    provider: vlmProvider,
    categories: ['invoice', 'receipt', 'contract', 'other']
  }))
  .conditional('extract', (data) => {
    switch (data.category) {
      case 'invoice':
        return extract({ provider: vlmProvider, schema: invoiceSchema });
      case 'receipt':
        return extract({ provider: vlmProvider, schema: receiptSchema });
      default:
        return extract({ provider: vlmProvider, schema: genericSchema });
    }
  })
  .build();

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

## Configuration Options

```typescript theme={null}
categorize({
  provider: vlmProvider,           // Required: VLM provider
  categories: ['invoice', 'receipt', 'contract'],  // Required: Category list
  additionalPrompt: '...',         // Custom categorization instructions
  consensus: { runs: 3 },          // Multi-run voting for accuracy
  reasoning: { enabled: true }     // Extended thinking
})
```

### Options Reference

| Option                   | Type              | Description                               |
| ------------------------ | ----------------- | ----------------------------------------- |
| `provider`               | `VLMProvider`     | Required. VLM provider for classification |
| `categories`             | `string[]`        | Required. List of valid categories        |
| `additionalPrompt`       | `string`          | Custom categorization instructions        |
| `consensus`              | `ConsensusConfig` | Multi-run voting configuration            |
| `reasoning`              | `object`          | Extended reasoning options                |
| `promptRef`              | `string`          | Reference to prompt asset                 |
| `promptVariables`        | `object`          | Variables for prompt rendering            |
| `additionalInstructions` | `string`          | Extra instructions for the prompt         |

## Output

The categorize node outputs:

```typescript theme={null}
{
  input: DocumentIR | FlowInput;  // Original input (passed through)
  category: string;               // Matched category
}
```

## Conditional Routing

The main use case for categorize is routing documents to different extraction schemas:

```typescript theme={null}
const flow = createFlow()
  .step('categorize', categorize({
    provider: vlmProvider,
    categories: ['invoice', 'receipt', 'contract']
  }))
  .conditional('extract', (data) => {
    const schemas: Record<string, object> = {
      invoice: invoiceSchema,
      receipt: receiptSchema,
      contract: contractSchema
    };

    return extract({
      provider: vlmProvider,
      schema: schemas[data.category] || genericSchema
    });
  })
  .build();
```

## Custom Instructions

Provide guidance for categorization:

```typescript theme={null}
categorize({
  provider: vlmProvider,
  categories: ['invoice', 'receipt', 'quote', 'purchase_order'],
  additionalInstructions: `
    - Invoices have "Invoice" in the header and show amounts due
    - Receipts show "Paid" or "Payment Received"
    - Quotes contain pricing but no payment due
    - Purchase orders have "PO Number" and request goods/services
  `
})
```

## With Parsed Documents

Categorize works with both raw documents and parsed DocumentIR:

```typescript theme={null}
// Direct categorization (VLM)
const directFlow = createFlow()
  .step('categorize', categorize({
    provider: vlmProvider,
    categories: ['invoice', 'receipt']
  }))
  .build();

// Parse first, then categorize
const parsedFlow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('categorize', categorize({
    provider: vlmProvider,
    categories: ['invoice', 'receipt']
  }))
  .build();
```

## Consensus Voting

Improve classification accuracy with multiple runs:

```typescript theme={null}
categorize({
  provider: vlmProvider,
  categories: ['invoice', 'receipt', 'contract'],
  consensus: {
    runs: 3,
    strategy: 'majority'
  }
})
```

## Extended Reasoning

Enable for documents that are difficult to classify:

```typescript theme={null}
categorize({
  provider: vlmProvider,
  categories: ['invoice', 'receipt', 'contract'],
  reasoning: {
    enabled: true,
    effort: 'medium'
  }
})
```

## Example: Multi-Type Document Processing

```typescript theme={null}
const documentProcessor = createFlow()
  .step('categorize', categorize({
    provider: vlmProvider,
    categories: [
      'invoice',
      'receipt',
      'bank_statement',
      'tax_form',
      'unknown'
    ]
  }))
  .conditional('process', (data) => {
    switch (data.category) {
      case 'invoice':
        return extract({ provider: vlmProvider, schema: invoiceSchema });
      case 'receipt':
        return extract({ provider: vlmProvider, schema: receiptSchema });
      case 'bank_statement':
        return extract({ provider: vlmProvider, schema: bankStatementSchema });
      case 'tax_form':
        return extract({ provider: vlmProvider, schema: taxFormSchema });
      default:
        // Return basic metadata for unknown documents
        return extract({
          provider: vlmProvider,
          schema: {
            type: 'object',
            properties: {
              title: { type: 'string' },
              date: { type: 'string' },
              summary: { type: 'string' }
            }
          }
        });
    }
  })
  .build();
```

## Next Steps

<CardGroup cols={2}>
  <Card title="extract" icon="code" href="/sdk/nodes/extract">
    Extract data after categorization
  </Card>

  <Card title="Flows" icon="diagram-project" href="/sdk/flows">
    Learn about conditional routing
  </Card>
</CardGroup>
