Skip to main content
The DocloHybridClient enables hybrid execution modes that combine local processing power with cloud management and observability.

Use Cases

  • Config Pull: Pull flow definitions from the cloud, execute locally with your own providers
  • Local + Observability: Build flows locally, send execution metrics to the cloud dashboard
  • Cost Optimization: Use your own API keys for LLM providers while maintaining cloud visibility

Installation

pnpm add @doclo/client @doclo/flows @doclo/providers-llm

Initialization

import { DocloHybridClient } from '@doclo/client';
import { createVLMProvider } from '@doclo/providers-llm';
import { createOCRProvider } from '@doclo/providers-datalab';

const client = new DocloHybridClient({
  apiKey: process.env.DOCLO_API_KEY!,
  providers: {
    vlm: createVLMProvider({
      provider: 'google',
      model: 'gemini-2.5-flash',
      apiKey: process.env.GOOGLE_API_KEY!
    }),
    ocr: createOCRProvider({
      provider: 'reducto',
      apiKey: process.env.REDUCTO_API_KEY!
    })
  }
});

Configuration Options

OptionTypeDefaultDescription
apiKeystringRequiredDoclo API key
baseUrlstringhttps://app.doclo.aiBase URL for the API
convexUrlstringSame as baseUrlURL for data operations
timeoutnumber300000Request timeout in ms
providersProviderRegistryRequiredMap of provider refs to instances
promptRegistryOptionsobject-Remote prompt registry config
schemaRegistryOptionsobject-Remote schema registry config

Mode 1: Pull from Cloud

Fetch a flow definition from the cloud and execute it locally with your providers:
const result = await client.runHybrid<InvoiceData>('flow_invoice', {
  base64: documentBase64
});

console.log('Output:', result.output);
console.log('Cost:', result.metrics.totalCost);
console.log('Duration:', result.metrics.duration, 'ms');

Hybrid Run Options

OptionTypeDefaultDescription
versionstringLatestFlow version to execute
observabilityMode'stream' | 'batch-at-end''stream'When to send events
flushIntervalMsnumber5000Flush interval for stream mode
includeInputsbooleanfalseInclude inputs in events
includeOutputsbooleanfalseInclude outputs in events
metadataobject-Custom metadata for execution

Mode 2: Local + Observability

Build flows entirely locally but send execution data to the cloud dashboard:
import { createFlow, parse, extract } from '@doclo/flows';

// Build flow locally
const flow = createFlow()
  .step('parse', parse({ provider: ocrProvider }))
  .step('extract', extract({
    provider: vlmProvider,
    schema: invoiceSchema
  }))
  .build();

// Execute with cloud observability
const result = await client.runLocal(flow, input, {
  flowId: 'my-invoice-flow',
  flowVersion: '1.0.0'
});

// View execution in cloud dashboard
console.log('Execution ID:', result.executionId);

Local Run Options

OptionTypeDefaultDescription
flowIdstring'local-flow'Flow ID for dashboard tracking
flowVersionstring-Version for tracking
observabilityMode'stream' | 'batch-at-end''stream'When to send events
flushIntervalMsnumber5000Flush interval for stream mode
includeInputsbooleanfalseInclude inputs in events
includeOutputsbooleanfalseInclude outputs in events

Remote Registries

Access cloud-managed prompts and schemas:
// Get schema from cloud
const invoiceSchema = await client.schemas.getLatest('invoice');

// Get specific version
const v1Schema = await client.schemas.get('invoice', '1.0.0');

// Get prompt
const extractionPrompt = await client.prompts.get('extraction', '1.0.0');

Preloading Assets

For better performance, preload assets before execution:
// Preload multiple schemas
await client.schemas.preload(['invoice@1.0.0', 'receipt@1.0.0']);

// Preload prompts
await client.prompts.preload(['extraction@1.0.0']);

Creating Observability Manually

Create a cloud observability config to wire into flows manually:
const observability = client.createObservability('my-flow', {
  flowVersion: '1.0.0',
  mode: 'stream',
  flushIntervalMs: 5000,
  includeInputs: true,
  includeOutputs: true
});

// Use with a locally built flow
const flow = createFlow({ observability })
  .step('extract', extract({ provider, schema }))
  .build();

Result Type

Both runHybrid and runLocal return a HybridFlowResult:
interface HybridFlowResult<T = unknown> {
  output: T;              // The flow output
  metrics: {
    totalTokens: number;  // Total tokens used
    totalCost: number;    // Cost in USD
    duration: number;     // Duration in ms
    stepsCompleted: number;
  };
  executionId: string;    // For cloud tracking
  traceId: string;        // For distributed tracing
}

Access the Cloud Client

The underlying DocloClient is available for direct cloud operations:
// Access cloud client
const flowInfo = await client.cloud.flows.get('flow_abc123');

// List flows
const flows = await client.cloud.flows.list();

Provider Registry

The provider registry maps provider references (used in cloud flow definitions) to local provider instances:
const client = new DocloHybridClient({
  apiKey: process.env.DOCLO_API_KEY!,
  providers: {
    // These keys match the providerRef in your cloud flow definitions
    'gemini-flash': createVLMProvider({
      provider: 'google',
      model: 'gemini-2.5-flash',
      apiKey: process.env.GOOGLE_API_KEY!
    }),
    'reducto': createOCRProvider({
      provider: 'reducto',
      apiKey: process.env.REDUCTO_API_KEY!
    })
  }
});
If a flow references a provider not in your registry, execution will fail with a clear error message.

Next Steps