> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.runtype.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.runtype.com/_mcp/server.

# Using vector steps

Use vector steps to index text by meaning and to search it later. A Flow uses three steps for this:

* **Generate Embedding**: Converts text into an embedding, a list of numbers that represents the meaning of the text.
* **Store Vector**: Saves embeddings in a vector store.
* **Vector Search**: Embeds a query and returns the stored items that are most similar to it.

Each step can use one of three vector stores. The following table compares them:

| Vector store              | Where vectors live                                                 | Setup                                              |
| ------------------------- | ------------------------------------------------------------------ | -------------------------------------------------- |
| **PostgreSQL (pgvector)** | On your Records. Each embedding is attached to an existing Record. | None                                               |
| **Cloudflare Vectorize**  | In a Vectorize index in your Cloudflare account                    | Add a configuration in **Settings > Integrations** |
| **Weaviate**              | In a Weaviate collection                                           | Add a configuration in **Settings > Integrations** |

This page covers **PostgreSQL (pgvector)** and **Cloudflare Vectorize**. For Weaviate, see [Weaviate (vector search)](/user-guide/integrations/weaviate-vector-search).

## Before you begin

Make sure that you have the following:

* A Flow to add the steps to. For more information, see [Creating and editing flows](/user-guide/flows/creating-and-editing-flows).
* For **PostgreSQL (pgvector)**, the Records that you want to make searchable. **Store Vector** adds embeddings to existing Records. It doesn't create Records.
* For **Cloudflare Vectorize**, a Vectorize index and a configuration for it in **Settings > Integrations**, under **Vector Databases**.

## Choose one embedding model

A search compares the query embedding with the stored embeddings, so both must come from the same model. Pick one model in the **using** list of **Generate Embedding** and select the same model in **Vector Search**. The default in both steps is `text-embedding-3-small`.

With **PostgreSQL (pgvector)**, **Vector Search** matches only Records that were embedded with the selected model. A model mismatch returns no results and no error.

## Generate embeddings

To add a Generate Embedding step, follow these steps:

1. In the Flow editor, click the **+** control where you want to add the step. The step picker opens.
2. Select **Generate Embedding**.
3. In **Generate embedding for**, enter the text or a template such as `{{document_text}}`.
4. In **using**, select the embedding model.
5. In the output variable field, enter a name. The default is `embedding_result`.

To change where the text comes from, expand **Advanced** and set **Input Source**:

* **Direct Text**: Embed the text that you enter. Templates resolve before the step runs. The default.
* **From Variable**: Embed the value of a variable that you select.
* **From Record**: Embed a field of one Record. Enter a **record ID**, or a type and a name. In **text field**, enter the path to the text, such as `metadata.content`. Click **Fetch Example Record** to list the available fields.

The step cuts the text to **max length** characters before it embeds the text. The default is 8000. The step doesn't split long text into chunks.

### Embed many items at once

To embed every item in an array, follow these steps:

1. Expand **Advanced** and set **Input Mode** to **Batch**.
2. In **from array**, select the variable that holds the array.
3. Optional: In **each item as**, change the item name. The default is `item`.
4. In **using template**, enter the text to embed for each item, such as `{{item.title}}. {{item.body}}`.
5. Optional: Change **batch size**, the number of items sent to the model in one call. The default is 100.

### Read the output

In **Single** mode, the output variable holds one object. The following example shows its shape, with the embedding shortened:

```json
{
  "embedding": [0.0123, -0.0456, 0.0789],
  "model": "text-embedding-3-small",
  "dimensions": 1536,
  "textLength": 412,
  "metadata": {
    "tokensUsed": 98,
    "cost": 0.000002,
    "truncated": false
  }
}
```

In **Batch** mode, the output variable holds an array with one entry for each input item. Each entry keeps the fields of its input item and adds `embedding`, `embedding_model`, `embedding_dimensions`, `embedding_tokens_used`, and `embedding_cost`. If an input item isn't an object, the entry holds it in a `value` field.

## Store embeddings

To add a Store Vector step, follow these steps:

1. Add a **Store Vector** step after the **Generate Embedding** step.
2. In **Store vectors from**, enter the **Generate Embedding** output variable, such as `{{embedding_result}}`. Use the whole output variable, not its `embedding` field.
3. In the **in** list, select the vector store.
4. In **with ID template**, enter the ID for each vector. The following sections describe the value for each vector store.
5. Expand **Advanced** and set **Input Mode** to match the **Generate Embedding** step. A new **Store Vector** step starts in **Batch** mode.
6. In the output variable field, enter a name. The default is `stored_vectors`.

Set **Input Mode** to **Single** when **Store vectors from** holds one embedding. With **PostgreSQL (pgvector)**, a **Batch** step that receives one embedding fails with `All 1 items failed. First error: No embedding model`.

### Store on Records with PostgreSQL (pgvector)

With **PostgreSQL (pgvector)**, the step attaches each embedding to the Record whose ID matches **with ID template**. It also saves the embedding model with the Record, which **Vector Search** uses to match queries.

Set **with ID template** to a Record ID:

* In **Single** mode, use a template such as `{{saved_record.id}}` or `{{_record.id}}`.
* In **Batch** mode, use a field of each item, such as `{{item.id}}`.

If no Record has the ID, that item fails with `Record not found`. If **with ID template** is empty, the step fails with `ID template is required for pgvector destination`.

To index a set of documents as Records, you create one Record for each chunk of text first. For the full ingest pattern, see [Build the ingest Flow](/user-guide/records/building-retrieval-that-works#build-the-ingest-flow).

### Store in Cloudflare Vectorize

With **Cloudflare Vectorize**, the step writes each embedding to your Vectorize index. Configure these fields:

* **Connection list**: Next to the vector store, select a Vectorize configuration. If you don't select one, the step uses your default configuration.
* **namespace**: Optional. Enter a namespace to group vectors, such as `support-articles`. The field accepts templates.
* **with ID template**: Enter the vector ID, such as `{{item.id}}` in **Batch** mode. A vector with the same ID replaces the stored vector.
* **Metadata**: Optional. Expand **Metadata** and click **Add Metadata Field** to store fields with each vector, such as `content` set to `{{item.text}}`.

Store the text that you want to pass to a model in **Metadata**. **Vector Search** returns metadata, not the original text.

### Read the result

The output variable holds a summary of the write. It contains `destination`, `storedCount`, `totalItems`, `failureCount`, and `results`. With **PostgreSQL (pgvector)**, `results` has one entry for each item, and a failed entry has an `error` field that explains the failure.

The step fails when it stores no items. When only some items fail, the step succeeds and reports the failures in `failureCount` and `results`.

## Search stored vectors

To add a Vector Search step, follow these steps:

1. Click the **+** control where you want to add the step, and select **Vector Search**.
2. In **Search for**, enter the query or a template such as `{{userMessage}}`.
3. In the **in** list, select the vector store that holds the vectors.
4. Configure the fields for the vector store:
   * **PostgreSQL (pgvector)**: Optional. In **filter by type**, enter a Record type to search only Records of that type.
   * **Cloudflare Vectorize**: Select a connection, or keep **Default connection**. Optional: In **namespace**, enter the namespace that you stored the vectors in.
5. Optional: Change the number of results after **returning**, and the minimum similarity after **results with similarity**. The defaults are 5 results and a similarity of 0.7.
6. In **using**, select the embedding model that you used to generate the stored embeddings.
7. In the output variable field, enter a name. The default is `search_results`.

The step selects the closest matches up to the result count. Then it removes matches with a similarity lower than the minimum, so it can return fewer results than the count.

### Read the results

The output variable holds an array of matches, with the closest match first. Each match has these fields:

* **PostgreSQL (pgvector)**: `id`, `name`, `type`, `metadata`, and `similarity`. The `metadata` field is the Record metadata.
* **Cloudflare Vectorize**: `id`, `similarity`, and `metadata`. The `metadata` field holds the fields that you stored with the vector.

If the output variable is `search_results`, reference the matches in a later step like this:

```plaintext
{{search_results[0].id}}
{{search_results[0].metadata.content}}
```

To pass every match to a model, reference `{{search_results}}` in the prompt of a **Run Task** step.

## Example: Search a knowledge base

Dana has Records of type `kb_article`, and each Record stores the article text in `metadata.content`. Dana builds two Flows.

The indexing Flow runs once for each Record, for example in a batch run. It has these steps:

1. **Generate Embedding**: **Input Source** is **From Record**, **record ID** is `{{_record.id}}`, and **text field** is `metadata.content`.
2. **Store Vector**: **Store vectors from** is `{{embedding_result}}`, the vector store is **PostgreSQL (pgvector)**, **Input Mode** is **Single**, and **with ID template** is `{{_record.id}}`.

The question Flow answers a question from the articles. It has these steps:

1. **Vector Search**: **Search for** is `{{userMessage}}`, the vector store is **PostgreSQL (pgvector)**, and **filter by type** is `kb_article`.
2. **Run Task**: The prompt includes `{{search_results}}` and tells the model to answer from those articles only.

Both Flows use `text-embedding-3-small`. When Dana edits an article, rerunning the indexing Flow for that Record replaces its embedding.

For more information about batch runs, see [Running flows in batch](/user-guide/flows/running-flows-in-batch).

## Configure vector steps through the API

When you create a Flow through the API or an SDK, set the step `type` to `generate-embedding`, `store-vector`, or `vector-search`. The following configs match the Dana example:

**`Generate Embedding config`**

```json title="Generate Embedding config"
{
  "inputSource": "record",
  "recordId": "{{_record.id}}",
  "textField": "metadata.content",
  "embeddingModel": "text-embedding-3-small",
  "outputVariable": "embedding_result"
}
```

**`Store Vector config`**

```json title="Store Vector config"
{
  "vectorsSource": "embedding_result",
  "destination": "pgvector",
  "inputMode": "single",
  "idTemplate": "{{_record.id}}",
  "outputVariable": "stored_vectors"
}
```

**`Vector Search config`**

```json title="Vector Search config"
{
  "query": "{{userMessage}}",
  "vectorStore": "pgvector",
  "recordType": "kb_article",
  "embeddingModel": "text-embedding-3-small",
  "limit": 5,
  "threshold": 0.7,
  "outputVariable": "search_results"
}
```

The `vectorsSource` field accepts a variable name, a dot path, or a template such as `{{embedding_result}}`.

## Troubleshoot vector steps

The following table lists common problems and how to fix them:

| Problem                                                 | Fix                                                                                                                                                                                              |
| ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Vector Search** returns an empty array                | Select the same embedding model in both steps. Then lower the minimum similarity. With **PostgreSQL (pgvector)**, check that the **Store Vector** run reported a `storedCount` greater than `0`. |
| `No embedding model` in **Store Vector** results        | Set **Input Mode** to **Single** for one embedding. In **Store vectors from**, use the whole **Generate Embedding** output variable, not its `embedding` field.                                  |
| `Record not found` in **Store Vector** results          | Check that **with ID template** resolves to the ID of an existing Record.                                                                                                                        |
| `No text found at field path` in **Generate Embedding** | Check the **text field** path. Click **Fetch Example Record** to list the fields of a matching Record.                                                                                           |
| `No Vectorize configurations found.` in the step        | Add a Cloudflare Vectorize configuration in **Settings > Integrations**.                                                                                                                         |

A vector step that fails stops the Flow, unless you set its error handling to **Continue on error**. For more information, see [Error handling](/user-guide/flows/creating-and-editing-flows#error-handling).

## Next steps

* [Building retrieval that works](/user-guide/records/building-retrieval-that-works): design chunking, filters, and result settings for retrieval.
* [Weaviate (vector search)](/user-guide/integrations/weaviate-vector-search): store and search vectors in Weaviate.
* [Using record steps (get/list/upsert)](/user-guide/flows/using-record-steps-upsert-retrieve): create the Records that you embed.
* [Flow variables and templates](/user-guide/flows/flow-variables-and-templates): reference step outputs in later steps.