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

# ClefClassifier

> ClefClassifier and ClefClient answer classifier questions through Clef, Cloudflare's decision model on Workers AI, in one request.

## Overview

`ClefClassifier` answers [classifier questions](https://docs.pipecat.ai/api-reference/server/classifiers/overview.md) through Clef, Cloudflare's decision model on Workers AI. All the questions about one state go to Clef in one request, and an answer typically comes back in a few hundred milliseconds. Clef comes as two models: `clef`, the default, and `clef-flash` for faster answers.

A `ClefClassifier` asks through a `ClefClient`, which holds the HTTP/2 connection, adds the auth header, retries when Workers AI is busy, and counts tokens. Build the classifier with an account ID and API token to give it a client of its own, or pass a `ClefClient` to share one connection between several classifiers.

## Installation

```bash theme={null}
uv add "pipecat-ai[cloudflare]"
```

## Prerequisites

A Cloudflare account ID and an API token with Workers AI access, usually set as environment variables:

```bash theme={null}
CLOUDFLARE_ACCOUNT_ID=...
CLOUDFLARE_API_KEY=...
```

## Configuration

### ClefClassifier

```python theme={null}
from pipecat.classifiers.cloudflare.clef.classifier import ClefClassifier
```

**account\_id** `str | None` (default: None)

Cloudflare account ID, when the classifier should have a client of its own.

**api\_key** `str | None` (default: None)

Cloudflare API token, when the classifier should have a client of its own.

**client** `ClefClient | None` (default: None)

A client to share with other classifiers. Either `client`, or both
`account_id` and `api_key`, are required.

**model** `str` (default: clef)

The Clef model a client of its own asks: `clef`, or `clef-flash` for faster
answers.

**timeout** `float` (default: 10.0)

Seconds a client of its own waits for an answer before raising
`ClassifierError`.

**name** `str | None` (default: None)

Name of the classifier, as it appears in logs and metrics.

### ClefClient

```python theme={null}
from pipecat.classifiers.cloudflare.clef.client import ClefClient
```

**account\_id** `str` *required*

Cloudflare account ID.

**api\_key** `str` *required*

Cloudflare API token with Workers AI access.

**model** `str` (default: clef)

The Clef model to ask: `clef`, or `clef-flash` for faster answers.

**timeout** `float` (default: 10.0)

Seconds to wait for a reply before raising `ClassifierError`.

**max\_retries** `int` (default: 3)

How many times to retry a request Workers AI refused because it was busy (HTTP
429\), with exponential backoff.

## Usage

### Basic Usage

```python theme={null}
import os

from pipecat.classifiers.base_classifier import YesNoQuestion
from pipecat.classifiers.cloudflare.clef.classifier import ClefClassifier

classifier = ClefClassifier(
    account_id=os.getenv("CLOUDFLARE_ACCOUNT_ID"),
    api_key=os.getenv("CLOUDFLARE_API_KEY"),
)

results = await classifier.yes_no(
    "Hi, you've reached Dana. Leave a message.",
    {"voicemail": YesNoQuestion(instructions="is this a voicemail?")},
)
results["voicemail"].is_yes  # True
```

Most of the time you don't call the classifier yourself: you pass it to a component that asks it, such as [`VoicemailDetector`](https://docs.pipecat.ai/api-reference/server/extensions/voicemail) or [`UIWorker`](https://docs.pipecat.ai/api-reference/server/workers/ui-worker).

### Sharing a Client

Several classifiers can share one `ClefClient`, and with it one connection pool and one token count:

```python theme={null}
from pipecat.classifiers.cloudflare.clef.classifier import ClefClassifier
from pipecat.classifiers.cloudflare.clef.client import ClefClient

client = ClefClient(
    account_id=os.getenv("CLOUDFLARE_ACCOUNT_ID"),
    api_key=os.getenv("CLOUDFLARE_API_KEY"),
)

voicemail = VoicemailDetector(classifier=ClefClassifier(client=client))
```

A client the classifier created is closed in the classifier's `cleanup()`. A shared client is left open, so close it yourself with `await client.close()` when every classifier using it is done.

### Asking About Images

Clef can see images. Pass them as `images=` to `ask()`, `yes_no()`, `choice()` or `score()`, as [`ClassifierImage`](https://docs.pipecat.ai/api-reference/server/classifiers/overview#classifierimage) objects:

```python theme={null}
from pipecat.classifiers.base_classifier import ClassifierImage

image = await ClassifierImage.from_frame(frame)  # e.g. a frame from the user's camera
results = await classifier.yes_no(
    "A frame from the user's camera.",
    {"person": YesNoQuestion(instructions="Is there a person in the frame?")},
    images=[image],
)
```

### Opening the Connection Early

`setup()` opens the connection to Workers AI ahead of the first question, so the first answer does not pay for the TLS handshake. Components that own a classifier, such as `VoicemailDetector`, call it for you. If the connection cannot be opened at setup, a warning is logged and the first question opens it instead.

## ClefClassifier Properties

| Property | Type | Description |
| - | - | - |
| `client` | `ClefClient` | The client this classifier asks through. |
| `model` | `str` | The Clef model the questions go to. |
| `supports_images` | `bool` | Always `True`: Clef can see images. |

## ClefClient Reference

### Properties

| Property | Type | Description |
| - | - | - |
| `model` | `str` | The Clef model the questions go to. |
| `usage` | `ClefUsage` | Tokens used so far over every request, as `input_tokens` and `output_tokens`. |

### Methods

#### connect

```python theme={null}
await client.connect()
```

Opens the connection to Workers AI by asking for the model's schema, which also checks the token and the model name. It connects once: a client shared by several classifiers is connected by each of them, and only the first call sends anything. Raises `ClassifierError` if Workers AI could not be reached or refused the request.

#### close

```python theme={null}
await client.close()
```

Closes the connection pool.

## Metrics

After every call, a `ClefClassifier` reports the time it took as `ProcessingMetricsData` and the tokens Clef used as `LLMUsageMetricsData` through its [`on_metrics`](https://docs.pipecat.ai/api-reference/server/classifiers/overview#on_metrics) event.

## Notes

* **Limits**: a choice question takes at most 255 options, available as `CLEF_MAX_CHOICE_OPTIONS` in `pipecat.classifiers.cloudflare.clef.classifier`. A question with more raises `ClassifierError` before anything is sent.
* **Images**: a call takes up to 4 images, available as `CLEF_MAX_IMAGES` in `pipecat.classifiers.cloudflare.clef.classifier`, of at most 4 MiB each and 8 MiB in all. More than 4 raises `ClassifierError` before anything is sent.
* **Errors**: a rejected request, a busy Workers AI after every retry, an unreachable server, or a reply missing an answer all raise `ClassifierError`. The message carries the reason Cloudflare gave, such as `HTTP 401: Authentication error`.
* **Idle connections** are kept open for 240 seconds, so a gap between questions does not cost a new TLS handshake.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.