---
description: Upload, list, and manage documents in AI Search instances using the Items Workers binding.
title: Workers binding
image: https://developers.cloudflare.com/og-docs.png
---

[Skip to content](#main-content)

> Documentation Index  
> Fetch the complete documentation index at: https://developers.cloudflare.com/ai-search/llms.txt  
> Use this file to discover all available pages before exploring further.

# Workers binding

Last updated Sep 1, 2026|Copy as Markdown| [View as Markdown](https://0285ca83.previews.developers.cloudflare.com/ai-search/api/items/workers-binding/index.md)| [Agent setup](https://0285ca83.previews.developers.cloudflare.com/agent-setup/)

[Workers](https://0285ca83.previews.developers.cloudflare.com/workers/) provides a serverless execution environment that allows you to create new applications or augment existing ones. Use a [Workers binding](https://0285ca83.previews.developers.cloudflare.com/workers/runtime-apis/bindings/) to upload, list, and manage documents in your AI Search instances from a Cloudflare Worker. Access the Items API through the `items` property on an instance handle.

Note

The Items API uploads files to an instance's built-in storage. For more details, refer to [Built-in storage](https://0285ca83.previews.developers.cloudflare.com/ai-search/configuration/data-source/built-in-storage/).

## Configure the binding

To use AI Search with Workers, you must create an AI Search binding. You create bindings by updating your [Wrangler configuration](https://0285ca83.previews.developers.cloudflare.com/workers/wrangler/configuration/). AI Search provides two types of bindings:

- Namespace binding: `ai_search_namespaces`
- Instance binding: `ai_search`

### Namespace binding

Access all instances within a [namespace](https://0285ca83.previews.developers.cloudflare.com/ai-search/concepts/namespaces/). You can get, create, list, and delete instances at runtime.

```jsonc
{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "compatibility_date": "2026-03-27",
  "ai_search_namespaces": [
    {
      "binding": "AI_SEARCH",
      "namespace": "my-namespace"
    }
  ]
}
```

```toml
compatibility_date = "2026-03-27"

[[ai_search_namespaces]]
binding = "AI_SEARCH"
namespace = "my-namespace"
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `binding` | string | Yes | The variable name available on `env`. For example, `"AI_SEARCH"` makes it accessible as `env.AI_SEARCH`. |
| `namespace` | string | Yes | The [namespace](https://0285ca83.previews.developers.cloudflare.com/ai-search/concepts/namespaces/) to bind to. A `default` namespace is created automatically for every account. If the namespace does not exist, Wrangler creates it on deploy. |
| `remote` | boolean | No | Set to `true` for local development with `wrangler dev`. |

### Instance binding

Bind directly to a single instance in the `default` namespace. Use this when you know which instance you need at deploy time.

```jsonc
{
  "$schema": "./node_modules/wrangler/config-schema.json",
  "compatibility_date": "2026-03-27",
  "ai_search": [
    {
      "binding": "MY_SEARCH",
      "instance_name": "my-instance"
    }
  ]
}
```

```toml
compatibility_date = "2026-03-27"

[[ai_search]]
binding = "MY_SEARCH"
instance_name = "my-instance"
```

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `binding` | string | Yes | The variable name available on `env`. For example, `"MY_SEARCH"` makes it accessible as `env.MY_SEARCH`. |
| `instance_name` | string | Yes | The name of the AI Search instance. Must exist in the default namespace at deploy time. |
| `remote` | boolean | No | Set to `true` for local development with `wrangler dev`. |

## Methods

The Items API methods are available on both the `ai_search_namespaces` and `ai_search` bindings. With the namespace binding, call methods on the handle returned by `get()`. With the instance binding, call methods directly on the binding (for example, `env.MY_SEARCH.items.upload()`).

The examples below use the namespace binding.

```ts
const instance = env.AI_SEARCH.get("my-instance");
```

### `items.upload()`

Uploads a document for indexing. Returns immediately. The document is queued for processing.

```ts
// Upload from a string
await instance.items.upload(
	"faq.md",
	"# FAQ\n\nQ: How do I reset my password?\nA: Go to Settings > Security...",
);

// Upload from an ArrayBuffer
const pdfResponse = await fetch("https://example.com/guide.pdf");
const pdfBuffer = await pdfResponse.arrayBuffer();
await instance.items.upload("guide.pdf", pdfBuffer);

// Upload from a ReadableStream
await instance.items.upload("doc.txt", request.body);
```

#### Upload with metadata

Attach [custom metadata](https://0285ca83.previews.developers.cloudflare.com/ai-search/configuration/indexing/metadata/) to a document for filtering in search queries. Custom metadata fields must be defined on the instance first using the [update()](https://0285ca83.previews.developers.cloudflare.com/ai-search/api/instances/workers-binding/#update) method or at creation time.

```ts
await instance.items.upload("guide.pdf", pdfBuffer, {
	metadata: {
		category: "onboarding",
		language: "en",
		version: "2.0",
	},
});
```

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | Yes | The filename for the uploaded document. Used as the item key. |
| `content` | ReadableStream, ArrayBuffer, or string | Yes | The document content. Maximum file size is 4 MB. Pass a string for plain text or markdown, an `ArrayBuffer` for binary files, or a `ReadableStream` for streaming uploads. |
| `options.metadata` | Record\<string, string> | No | Custom metadata key-value pairs to attach to the item. Use for filtering in search queries. Maximum 5 fields per instance. |

#### Response

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | The unique item identifier. |
| `key` | string | The filename or key of the item. |

### `items.uploadAndPoll()`

Uploads a document and polls until processing completes or the timeout is reached. Use this when you need to search the document immediately after upload.

```ts
// Wait for a specific document to finish indexing before searching
const item = await instance.items.uploadAndPoll(
	"handbook.txt",
	handbookContent,
);
console.log(`handbook.txt status: ${item.status}`); // "completed"

// Now search across all uploaded documents
const results = await instance.search({
	messages: [{ role: "user", content: "password reset policy" }],
});
```

#### Parameters

Same as [`items.upload()`](#parameters), with additional polling options:

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `options.pollIntervalMs` | number | No | How often to check the item status, in milliseconds. Defaults to `1000`. |
| `options.timeoutMs` | number | No | Maximum time to wait for processing to complete, in milliseconds. Defaults to `30000`. |

#### Response

Returns the full item object after polling completes:

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | The unique item identifier. |
| `key` | string | The filename or key of the item. |
| `status` | string | The processing status: `queued`, `running`, `completed`, `error`, `skipped`, `outdated`. |
| `chunks_count` | number | Number of chunks created from the document. |
| `file_size` | number | Size of the uploaded file in bytes. |
| `metadata` | object | Item metadata including `filename`, `folder`, and `timestamp`. |
| `source_id` | string | The source identifier (for example, `builtin` for uploaded files). |
| `created_at` | string | Timestamp of when the item was created. |
| `last_seen_at` | string | Timestamp of when the item was last seen during indexing. |

### `items.list()`

Returns a paginated list of items in the instance.

```ts
const { result, result_info } = await instance.items.list();

for (const item of result) {
	console.log(`${item.key} (${item.status})`);
}
// result_info.total_count contains the total number of items
```

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `page` | number | No | The page number to return. Defaults to `1`. |
| `per_page` | number | No | The number of items per page. Defaults to `20`. Maximum `50`. |
| `status` | string | No | Filter by processing status: `queued`, `running`, `completed`, `error`, `skipped`, or `outdated`. |
| `sort_by` | string | No | Sort order for items: `status` (default) or `modified_at`. |
| `search` | string | No | Search items by text content. |
| `source` | string | No | Filter by source identifier (for example, `builtin` for uploaded files). |

#### Response

| Field | Type | Description |
| --- | --- | --- |
| `result` | array | Array of item objects. |
| `result[].id` | string | The unique item identifier. |
| `result[].key` | string | The filename or key of the item. |
| `result[].status` | string | The processing status: `queued`, `running`, `completed`, `error`, `skipped`, `outdated`. |
| `result[].chunks_count` | number | Number of chunks created from the document. |
| `result[].file_size` | number | Size of the uploaded file in bytes. |
| `result[].metadata` | object | Item metadata including `filename`, `folder`, and `timestamp`. |
| `result[].source_id` | string | The source identifier (for example, `builtin` for uploaded files). |
| `result[].created_at` | string | Timestamp of when the item was created. |
| `result[].last_seen_at` | string | Timestamp of when the item was last seen during indexing. |
| `result_info` | object | Pagination metadata. |
| `result_info.count` | number | Number of items in the current page. |
| `result_info.total_count` | number | Total number of items in the instance. |
| `result_info.page` | number | The current page number. |
| `result_info.per_page` | number | Items per page. |

### `items.delete()`

Deletes an item and its indexed chunks.

```ts
await instance.items.delete("item-id-123");
```

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `itemId` | string | Yes | The unique identifier of the item to delete. |

#### Response

Returns `void`. Throws an error if the item does not exist.

### `items.get()`

Returns a handle to a specific item for retrieving its status or downloading the original file.

#### `items.get().info()`

Returns the status and metadata of a specific item.

```ts
const itemInfo = await instance.items.get("item-id-123").info();
```

##### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `itemId` | string | Yes | The unique identifier of the item. |

##### Response

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | The unique item identifier. |
| `key` | string | The filename or key of the item. |
| `status` | string | The processing status: `queued`, `running`, `completed`, `error`, `skipped`, `outdated`. |
| `chunks_count` | number | Number of chunks created from the document. |
| `file_size` | number | Size of the uploaded file in bytes. |
| `metadata` | object | Item metadata including `filename`, `folder`, and `timestamp`. |
| `source_id` | string | The source identifier (for example, `builtin` for uploaded files). |
| `created_at` | string | Timestamp of when the item was created. |
| `last_seen_at` | string | Timestamp of when the item was last seen during indexing. |

#### `items.get().download()`

Downloads the original source file for an item.

```ts
const file = await instance.items.get("item-id-123").download();
// file.body is a ReadableStream
```

##### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `itemId` | string | Yes | The unique identifier of the item. |

##### Response

| Field | Type | Description |
| --- | --- | --- |
| `filename` | string | The original filename. |
| `contentType` | string | The MIME type of the file (for example, `application/pdf`). |
| `size` | number | The file size in bytes. |
| `body` | ReadableStream | A readable stream of the file contents. |

Was this helpful?

YesNo

## On this page

[![](https://0285ca83.previews.developers.cloudflare.com/_astro/logo.te5VL_aD.svg)Docs](https://0285ca83.previews.developers.cloudflare.com/)

```json
{"@context":"https://schema.org","@type":"TechArticle","@id":"https://developers.cloudflare.com/ai-search/api/items/workers-binding/#page","headline":"Workers binding · Cloudflare AI Search docs","description":"Upload, list, and manage documents in AI Search instances using the Items Workers binding.","url":"https://developers.cloudflare.com/ai-search/api/items/workers-binding/","inLanguage":"en","image":"https://developers.cloudflare.com/og-docs.png","dateModified":"2026-09-01","publisher":{"@type":"Organization","name":"Cloudflare","description":"One platform for your apps, agents, and workforce. Build, secure, and scale without managing infrastructure","url":"https://www.cloudflare.com/","sameAs":["https://github.com/cloudflare","https://www.linkedin.com/company/cloudflare","https://x.com/cloudflare"],"logo":{"@type":"ImageObject","url":"https://developers.cloudflare.com/logo.svg"},"address":{"@type":"PostalAddress","streetAddress":"101 Townsend St","addressLocality":"San Francisco","addressRegion":"CA","postalCode":"94107","addressCountry":"US"},"contactPoint":[{"@type":"ContactPoint","contactType":"Customer Support","url":"https://support.cloudflare.com/","availableLanguage":["English"]},{"@type":"ContactPoint","contactType":"Sales","url":"https://www.cloudflare.com/contact/","availableLanguage":["English"]}]},"isPartOf":{"@type":"WebSite","@id":"https://developers.cloudflare.com/#website","name":"Cloudflare Docs","url":"https://developers.cloudflare.com/"}}
```
