# Flows TF Provider

The Flows TF Provider can be used with OpenTofu and Terraform to manage Flows (yes, Flows-as-Code!), app installations, secrets, and more.

You can find installation and basic usage instructions in the [GitHub repository](https://github.com/spacelift-io/terraform-provider-flows) and resource documentation on the [OpenTofu registry](https://search.opentofu.org/provider/spacelift-io/flows/latest).

When using with Terraform (as opposed to OpenTofu), you will have to provide the full registry path:


**

```
terraform {  required_providers {    flows = {      source = "registry.opentofu.org/spacelift-io/flows"    }  }}
```

## Managing Flows as Code
[Section titled “Managing Flows as Code”](#managing-flows-as-code)
Whether you want to version control your flows, have a code-review driven change management process, deploy them across multiple environments, or generate them programmatically, the Flows TF Provider can help you achieve that.

Flows themselves have a YAML representation, which you can export from the UI. Without any blocks selected, click cmd+c to copy the entire flow (or with blocks selected, to copy just those), you can then paste that into a YAML file.

Here’s an example of such a Flow (the #1 sample flow):


**

```
blocks:  - name: Sample Endpoint    type:      coreBlock: httpEndpoint    position: [-50, 82]    config:      path: /hello/{name}      methods:        - GET      audience: world    inputs:      default:        links:          - block: Sleep            output: default        config:          statusCode: 200          body: !expr '`Hello, ${outputs.sampleEndpoint.params.name}`'  - name: Sleep    type:      coreBlock: sleep    position: [-50, 255]    inputs:      default:        links:          - block: Sample Endpoint            output: requests        config:          sleep: 5notes:  - body: |-      # Simple Webhook Handler
      You can see that the **HTTP Endpoint** block produces events on its `requests` output, and expects a response to arrive at its input.
      To test this Flow, first click on the **Sample Endpoint** block, then click on the copy button next to the **Path** field. You can navigate to the copied URL using your browser, or curl it.
      Once you do that and get a response, you will also see events appear on the canvas next to various outputs. Click on an output to see the events it produced!
      You can **re-emit** those events, in order to replay parts of your flow - great for debugging, or just building up your flow piece by piece!    position: [273, 13]    style:      width: 400      height: 380      color: '#18181b'
```

This is pretty self-explanatory. For config fields, you can just input raw values, or provide expressions using the `!expr` tag.

It becomes slightly more complex if you have apps. Here you can see a Flow with app blocks used:


**

```
appInstallations:  slack:    appName: Slack    appVersion: 0.2.2    id: 019a4a1d-3494-758a-9df9-67d6e5f4660bblocks:  - name: Mentions    type:      appBlock:        block: appMentionSubscription        appInstallation: slack    position: [116, 0]  - name: Is Hello Command    description: Checks if the mention contains a hello command    type:      coreBlock: condition    position: [0, 160]    inputs:      default:        links:          - block: Mentions            output: default        config:          condition: !expr /^<@U\w+>\s+hello$/i.test(outputs.mentions.text.trim())  - name: Hello Response    description: Sends a hello message to the user    type:      appBlock:        block: sendTextMessage        appInstallation: slack    position: [0, 293]    inputs:      default:        links:          - block: Is Hello Command            output: then        config:          channelId: !expr outputs.mentions.channel          text: !expr '`Hello <@${outputs.mentions.user}>!`'          threadTs: !expr outputs.mentions.thread_ts || outputs.mentions.ts
```

Here you can see that the type of app blocks refers back to the installation they are related to, while an initial `appInstallations` section describes the apps used, their versions, and installation IDs.

Importantly, the YAML representation only manages the “configuration layer” of the Flow. It does not include e.g. lifecycle confirmation.

### Managing Flows with the TF Provider
[Section titled “Managing Flows with the TF Provider”](#managing-flows-with-the-tf-provider)
With the Flows TF Provider, you can use the `flows_flow` resource to create and update Flows. Additionally, you are able to parameterize the app installations (so you don’t have to include the IDs in the yaml file):


**

```
resource "flows_flow" "example" {  project_id = "your-project-id"  name       = "my-flow"  definition = file("${path.module}/flow.yaml")
  app_installation_mapping = {    my_app = "app-installation-id"  }}
```

Moreover, if you have blocks with a lifecycle, you are able to confirm them using the `flows_entity_lifecycle_confirmation`:


**

```
resource "flows_entity_lifecycle_confirmation" "example" {  entity_id = flows_flow.example.blocks["my_entity"].id}
```

### Changing Block Names
[Section titled “Changing Block Names”](#changing-block-names)
Blocks are uniquely identified by their names. This means that if you just change a block name, it will be deleted and recreated - for most blocks this is fine, but you will lose e.g. the event history of that block. Additionally, it will be problematic for blocks that manage external resources (like AWS Resource blocks).

To rename a block without losing its identity, you can use the `alternativeLookupStrategy` field. Here’s an example of how to use it by referring to the old name of the block:


**

```
blocks:- name: New Block Name  alternativeLookupStrategy:    name: Old Block Name  type:    appBlock:      block: appMentionSubscription      appInstallation: slack  position: [116, 0]
```

Alternatively, you can also directly refer to the block ID:


**

```
blocks:- name: New Block Name  alternativeLookupStrategy:    id: 019be5ca-3832-717a-b5d7-dfe4bc19569a  type:    appBlock:      block: appMentionSubscription      appInstallation: slack  position: [116, 0]
```

### Reference
[Section titled “Reference”](#reference)
See the [Flow Definition Reference](/automating-flows/flow-definition-reference) for complete YAML schema documentation.