Skip to navigation

Using record steps (get/list/upsert)

Use record steps to retrieve, create, update, and search Records from a Flow. Records hold JSON metadata that your Flows can reference.

For more information about Records, see What are Records?.

Choose between Get Record and List Records

Choose Get Record when you need one object, such as a lookup by ID or by a unique name. Choose List Records when the number of matches can vary, such as a lookup for every open ticket for a customer.

Get Record step

Use Get Record when you need one Record. The step returns one object.

Add a Get Record step

To add a Get Record 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 Get Record.
  3. Under Get record, choose one of these lookup methods:
    • By ID: In with ID, enter a Record ID or a template such as {{customer_id}}.
    • By query: Select a Record type and add filter conditions. For more information, see Filtering and searching records.
  4. Optional: To return only some fields, expand Fields and set Include fields or Exclude fields. With By query, you can click Fetch example for include/exclude fields to list the available fields.
  5. In the output variable field, enter a name such as customer.
  6. Click Save version, or Create for a new Flow.

The Record ID and filter values accept {{variable}} templates. Runtype resolves them before the lookup.

When multiple Records match, Get Record returns the Record with the newest update time. When no Record matches, the step fails with an error that begins with Record not found. For what happens next, see Handle missing results.

Read the result

The returned Record includes id, name, type, metadata, createdAt, and updatedAt. When you set Include fields or Exclude fields, the object contains only the selected fields.

If the output variable is customer, use these references:

{{customer.id}}
{{customer.name}}
{{customer.metadata.tier}}
{{customer.metadata.customer_name}}

List Records step

Use List Records when the lookup can return zero, one, or multiple Records. The step returns an array of Records.

Add a List Records step

To add a List Records 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 List Records.
  3. Select a Record type and add filter conditions.
  4. Optional: Set Maximum records. The default is 50, and the maximum is 1000.
  5. Optional: Set If no records match to Succeed with an empty list or Fail the step. The default is Succeed with an empty list.
  6. Optional: Expand Fields to include or exclude specific fields from each Record.
  7. In the output variable field, enter a name such as customers.
  8. Click Save version, or Create for a new Flow.

List Records orders results by update time, with the newest first.

Read the results

List Records always returns an array, even when one Record matches. Each item has the same fields as a Get Record result. If the output variable is customers, index the array before you read a field.

Use either dot indexing or bracket indexing. The following references return fields of the first Record and the number of matches:

{{customers.0.metadata.tier}}
{{customers[0].metadata.tier}}
{{customers.0.id}}
{{customers.length}}

Upsert Record step

Use Upsert Record to create a Record or update an existing Record. The step stores an object from a variable as the Record metadata.

Add an Upsert Record step

To add an Upsert Record 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 Upsert Record.
  3. Under Create or update records, select Single.
  4. In from variable, enter the variable that holds the metadata object, such as customer_profile.
  5. In with type, enter the Record type, such as customer.
  6. In named, enter a stable Record name, such as customer-{{customer_id}}.
  7. In the output variable field, enter a name such as saved_record.
  8. Click Save version, or Create for a new Flow.

The step uses the Record type and name to find the Record. If a Record with the same type and name exists, the step updates it. Otherwise, it creates a Record. The name accepts {{variable}} templates. If you leave the name empty, the step generates a name from the Record type and the execution time, so every run creates a new Record.

To use the same Record in a later Get Record step, look it up with the same name.

Choose a merge strategy

To change how the step writes to an existing Record, expand Options and set Merge Strategy:

  • Merge: Replace the top-level fields that appear in the source object and keep the other fields. The default.
  • Replace: Replace all existing metadata with the source object.

Merge works on top-level fields only. A nested object in the source replaces the stored nested object completely. For example, if the Record has {"address": {"city": "Oslo", "street": "Main St"}} and the source is {"address": {"city": "Bergen"}}, the result is {"address": {"city": "Bergen"}}. To change nested fields and keep their neighbors, use Update Record.

Set the source variable

The source variable must resolve to a JSON object. The object becomes the Record metadata. If a Run Task step produces the object, set its Response Format to JSON.

The following object shows a valid source value:

{
"customer_id": "{{customer_id}}",
"conversation_summary": "{{summarize_result}}",
"sentiment": "{{analyze_sentiment.label}}",
"timestamp": "{{_now.iso}}"
}

In this example, customer_id, summarize_result, and analyze_sentiment refer to values from previous steps. {{_now.iso}} inserts the execution timestamp.

An Extract Fields step produces a ready-made source object. If its output variable is claim, set the source variable to the path claim.values, without braces. Fields that the input didn’t contain are null, and with Merge a null replaces the stored value.

A plain-text source value is not a JSON object, so the step writes nothing. To store text, add a Run Code step that wraps the text in an object. Flows that you configure through the API or SDK can instead set contentField on the step, which stores the text as { "<contentField>": "<text>" }. When you save the Flow, validation reports a text source as the warning UPSERT_RECORD_SOURCE_NOT_JSON.

Upsert several Records at once

To create or update one Record for each item in an array, follow these steps:

  1. Under Create or update records, select Batch.
  2. In For each item in, enter the variable that holds the array, such as products.
  3. Optional: Change reference as from item to another name, and change with batch size from the default of 100.
  4. In with type, enter the Record type.
  5. In named, enter a name that is unique for each item, such as {{item.sku}}.

Each item in the array becomes the metadata of one Record. If the variable does not hold an array, the step writes nothing. An empty array returns an empty result.

Read the result

The output variable contains the saved Record’s id, name, type, createdAt, and updatedAt. It does not contain the metadata. In batch mode, the output is an array with one such object for each item.

If the output variable is saved_record, use {{saved_record.id}} to reference the Record in a later step.

Update Record step

Use Update Record to change metadata on one existing Record. Unlike Upsert Record, it does not create a Record when the target does not exist.

Add an Update Record step

To add an Update Record 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 Update Record.
  3. Under Find record, choose the target:
    • From context: Update the Record in the _record variable, such as the current Record in a batch run.
    • By ID: Enter a Record ID or a template such as {{saved_record.id}}.
    • By filter: Select a Record type and add filter conditions. The step updates the most recently updated match.
  4. Under Update metadata, enter each field’s path inside the metadata, such as status or address.city, its type, and its value. Click Add Field to add another field. To edit the updates as JSON instead, turn on JSON mode.
  5. Optional: Set Merge Strategy to Replace, or turn on Return full record.
  6. In the output variable field, enter a name such as updated_record.
  7. Click Save version, or Create for a new Flow.

String values can contain {{templates}} that resolve before the write.

Merge Strategy controls how the updates combine with the existing metadata:

  • Merge: Merge the updates into the existing metadata, including fields inside nested objects. The default. In the API and SDK, deep-merge behaves the same as merge.
  • Replace: Replace all existing metadata with the updates.

Read the result

By default, the output variable contains a summary: id, name, type, updated, updatedAt, metadataKeysUpdated, and mergeStrategy. When Return full record is on, the output variable contains the updated Record, including its metadata.

Write limits and schema validation

Upsert Record and Update Record reject metadata that exceeds these limits:

  • 256 KB of serialized JSON (METADATA_TOO_LARGE)
  • 200 top-level keys (METADATA_TOO_MANY_KEYS)
  • 64 characters for a top-level key (METADATA_KEY_TOO_LONG)
  • 5 levels of nesting (METADATA_TOO_DEEP)

If the Record type has a collection schema, the schema’s validation mode also applies. In warn mode, a nonconforming write proceeds and the step reports schema warnings. In enforce mode, the step rejects a nonconforming write. For more information, see Defining a schema.

Handle write failures

A write step that fails does not always stop the Flow. The result depends on the cause and on the step’s error-handling setting. For the available settings, see Error handling.

The following table shows the outcome for each cause:

CauseError handling not setContinue on errorStop on error
The source variable is missing or is not an object, or no target Record matchesThe step reports a failure, writes no output variable, and the Flow continuesThe step succeeds, sets the output variable to null, and writes no RecordThe Flow stops
The write is rejected, for example by a limit or an enforce schemaThe step succeeds, sets the output variable to null, and writes no RecordThe step succeeds, sets the output variable to null, and writes no RecordThe Flow stops

An Update Record step that you add in the dashboard starts with Stop on error. An Upsert Record step starts with no setting, and its control shows Continue on error until you choose a mode. When a missed write must stop the Flow, set the step to Stop on error. In the API and SDK, set defaultValue to write a value other than null when the step continues.

Vector Search step

Use Vector Search to find stored content by semantic similarity. Before you search, create embeddings with Generate Embedding and store them with Store Vector.

Add a Vector Search step

To add a Vector Search 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 Vector Search.
  3. In Search for, enter the search text or a template such as {{question}}.
  4. In the in list, select the vector store: Weaviate, Cloudflare Vectorize, or, when it’s available for your account, PostgreSQL (pgvector). For Weaviate, also select the connection and collection. For Cloudflare Vectorize, select the connection and, optionally, enter a namespace.
  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 when you stored the vectors.
  7. In the output variable field, enter a name such as search_results.
  8. Click Save version, or Create for a new Flow.

Read search results

Vector Search returns an array of matches, with the closest match first. With PostgreSQL (pgvector) and Cloudflare Vectorize, each match includes id, similarity, and metadata. With Weaviate, each match includes id, score, and properties, which holds the stored fields.

If the output variable is search_results, read fields from an indexed result like this:

{{search_results[0].similarity}}
{{search_results[0].metadata.content}}

For guidance on choosing the number of results and the similarity threshold, see Building retrieval that works.

Build a retrieval-augmented generation flow

A retrieval-augmented generation (RAG) flow retrieves relevant Record content and passes it to a model. Build the pattern with these steps:

  1. Get Record, List Records, or Vector Search: Find relevant Records for the question.
  2. Run Code: Optional. Extract and format the retrieved context.
  3. Run Task: Generate an answer from the retrieved context.

Use a prompt like the following to answer a question from search results:

Answer this question using only the provided context.
Question: {{question}}
Context:
{{search_results[0].metadata.content}}
{{search_results[1].metadata.content}}
Answer:

This prompt reads the question variable and the first two items in the search_results array.

Handle missing results

A read step that fails writes no output variable. The Flow stops only when the step’s error handling is Stop on error. Otherwise, later steps run, and a reference such as {{customer.id}} stays in their input as literal text.

Choose the step behavior that matches how you handle missing Records:

  • Use Get Record when no match must fail the step.
  • Use List Records with Succeed with an empty list when no match is an expected result.
  • Use List Records with Fail the step when an empty result must fail the step.

To branch on an empty List Records result, add a Conditional Logic step after it. If the output variable is customers, enter this condition in code mode:

customers.length > 0

Put the steps that use the Record data on the true path. Put the steps that handle missing Records, such as a default reply, on the false path. For more information, see Using conditional steps.

Best practices for record steps

Follow these practices when you configure record steps:

  • Use snake_case metadata keys: Records that you create in the dashboard or through the API store keys in lowercase snake_case. Use keys such as customer_name in Flows too, so reads and filters match.
  • Keep metadata concise: Store only the fields that your Flows use in queries or prompts, and stay within the write limits.
  • Use stable names for upserts: Set a stable name when later runs must update the same Record.
  • Set a List Records limit: Set Maximum records to the number of Records that the Flow needs.

Migrate from retrieve-record

The retrieve-record step is deprecated. Existing Flows that use it continue to run. When you edit such a Flow, replace the step with Get Record when you need one object, or with List Records when you need an array.

Existing retrieve-record steps behave like Get Record when they look up by ID. When they look up by type, name, or filter, they behave like List Records with a limit of 1000 that fails when no Record matches. For save-time checks, see Flow validation warnings.

Next steps

Continue with these related topics: