> ## 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.

# Hybrid Client

> Execute flows locally with cloud configuration and observability

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

```bash theme={null}
pnpm add @doclo/client @doclo/flows @doclo/providers-llm
```

## Initialization

```typescript theme={null}
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

| Option                  | Type               | Default                | Description                       |
| ----------------------- | ------------------ | ---------------------- | --------------------------------- |
| `apiKey`                | `string`           | Required               | Doclo API key                     |
| `baseUrl`               | `string`           | `https://app.doclo.ai` | Base URL for the API              |
| `convexUrl`             | `string`           | Same as baseUrl        | URL for data operations           |
| `timeout`               | `number`           | `300000`               | Request timeout in ms             |
| `providers`             | `ProviderRegistry` | Required               | Map of provider refs to instances |
| `promptRegistryOptions` | `object`           | -                      | Remote prompt registry config     |
| `schemaRegistryOptions` | `object`           | -                      | Remote schema registry config     |

## Mode 1: Pull from Cloud

Fetch a flow definition from the cloud and execute it locally with your providers:

```typescript theme={null}
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

| Option              | Type                         | Default    | Description                    |
| ------------------- | ---------------------------- | ---------- | ------------------------------ |
| `version`           | `string`                     | Latest     | Flow version to execute        |
| `observabilityMode` | `'stream' \| 'batch-at-end'` | `'stream'` | When to send events            |
| `flushIntervalMs`   | `number`                     | `5000`     | Flush interval for stream mode |
| `includeInputs`     | `boolean`                    | `false`    | Include inputs in events       |
| `includeOutputs`    | `boolean`                    | `false`    | Include outputs in events      |
| `metadata`          | `object`                     | -          | Custom metadata for execution  |

## Mode 2: Local + Observability

Build flows entirely locally but send execution data to the cloud dashboard:

```typescript theme={null}
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

| Option              | Type                         | Default        | Description                    |
| ------------------- | ---------------------------- | -------------- | ------------------------------ |
| `flowId`            | `string`                     | `'local-flow'` | Flow ID for dashboard tracking |
| `flowVersion`       | `string`                     | -              | Version for tracking           |
| `observabilityMode` | `'stream' \| 'batch-at-end'` | `'stream'`     | When to send events            |
| `flushIntervalMs`   | `number`                     | `5000`         | Flush interval for stream mode |
| `includeInputs`     | `boolean`                    | `false`        | Include inputs in events       |
| `includeOutputs`    | `boolean`                    | `false`        | Include outputs in events      |

## Remote Registries

Access cloud-managed prompts and schemas:

```typescript theme={null}
// 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:

```typescript theme={null}
// 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:

```typescript theme={null}
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`:

```typescript theme={null}
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:

```typescript theme={null}
// 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:

```typescript theme={null}
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

<CardGroup cols={2}>
  <Card title="DocloClient" icon="cloud" href="/cloud/client">
    Cloud-only execution
  </Card>

  <Card title="Observability" icon="chart-line" href="/sdk/advanced/observability">
    Execution monitoring
  </Card>
</CardGroup>
