Skip to content

Importing Existing Dialogflow Agents into Terraform

Overview

Dialogflow is a powerful tool in Google Cloud that you can use to design conversational agents powered by Natural Language Understanding (NLU) to transform user requests into actionable data. You can integrate voice and/or chat agents in your app, website, or customer support systems to determine user intent and interact with users.

Problem: When Managing Dialogflow Agents with Terraform, building (or re-implementing) an entire Dialogflow agent with flows, pages, intents, transition routes, and other components in Terraform is difficult to do from scratch.

Solution: Build a basic representation of the Dialogflow agent using the Dialogflow Console or client library (e.g., using the Dialogflow Python client library), then import the agent into Terraform using terraform import and the process outlined in this blog post.

In this post, we'll walk through the steps to import a Dialogflow agent into Terraform. Once imported into Terraform, you can manage all of your agents and their settings programmatically, version control and track the state of your agents, spin up agents in dev/QA/prod environments for testing, and all of the other neat functionality that you get by using Terraform.

Setup

There are a few things that you'll need to set up before you can import a Dialogflow agent with Terraform:

  1. Register for a Google Cloud account.
  2. Enable the Dialogflow API.
  3. Install and initialize the Google Cloud gcloud CLI tool.
  4. Create a service account and associated JSON key per the Terraform documentation and Google Cloud documentation.
  5. Finally, install Terraform. If you're using macOS, I recommend installing Terraform with Homebrew. Or, even better, install tfenv using brew install tfenv, then run tfenv install so you can easily switch between versions of Terraform!

Create a new agent (or use an existing agent)

To get started with this approach, you can use an existing Dialogflow agent that you've created, start from a pre-built agent, or create an agent following the build an agent quickstart.

Dialogflow CX Small Talk Agent

Define a provider in Terraform

Create a directory for your Terraform configuration files.

Then create a file called provider.tf with the following contents, which will define a Google Cloud provider:

provider "google" {
  project = "your-project-id"
  region  = "us-central1"
  zone    = "us-central1-a"
}

You can substitute in your own Google Cloud project ID as well as your desired region and zone.

Initialize Terraform

From the directory that contains provider.tf, run the following command in a terminal:

terraform init

If successful, you'll see output similar to the following after Terraform installs the Google Cloud provider plugin:

Initializing the backend...

Initializing provider plugins...
- Finding latest version of hashicorp/google...
- Installing hashicorp/google v4.47.0...
- Installed hashicorp/google v4.47.0 (signed by HashiCorp)

[...]

Terraform has been successfully initialized!

Import a resource into Terraform

To import an existing cloud resource such as a Dialogflow agent, page, flow, or intent into Terraform, we'll use the following steps:

  1. Define placeholder component in Terraform configuration files (*.tf)
  2. Run terraform import to import the remote state from Google Cloud
  3. Run terraform plan to check for mismatches between Terraform configuration files and imported state
  4. Run terraform show, then modify the appropriate Terraform configuration files (*.tf) by replacing the placeholder values with the values from the remote state
  5. Repeat Steps 3 and 4 until the terraform plan command reports that there are no further changes to be made (hooray for idempotence!)

Once you've iterated through that process, you'll have everything that you need in your Terraform configuration file needed to re-provision a specific component from scratch (hooray destructible testing and development!).

Let's go through the process in detail to import a Dialogflow agent into Terraform.

Define a placeholder agent in Terraform

We'll start by importing the root component in Dialogflow, the agent itself.

Create a file called agents.tf with the following contents, which will define a placeholder for the agent that we want to manage in Terraform:

resource "google_dialogflow_cx_agent" "agent" {
  display_name          = ""
  location              = ""
  default_language_code = ""
  time_zone             = ""
}

Import the remote resources into Terraform state

Now we can import the remote state of the agent in Google Cloud to our local machine (or wherever you are running terraform import from).

Run the following import command, and replace $PROJECT, $LOCATON, and $AGENT with your project ID, region, and Dialogflow agent ID, respectively (note that you can obtain the Dialogflow agent ID from the Dialogflow Console):

terraform import google_dialogflow_cx_agent.agent "projects/$PROJECT/locations/$LOCATION/agents/$AGENT"

If successful, you'll see output similar to the following after Terraform imports the remote agent:

google_dialogflow_cx_agent.agent: Importing from ID "projects/your-project-id/locations/us-central1/agents/5717be04-3519-4cb1-9d0e-378333aea9ac"...
google_dialogflow_cx_agent.agent: Import prepared!
  Prepared google_dialogflow_cx_agent for import
google_dialogflow_cx_agent.agent: Refreshing state... [id=projects/your-project-id/locations/us-central1/agents/5717be04-3519-4cb1-9d0e-378333aea9ac]

Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.

All of the Terraform state is now captured in the terraform.tfstate file in your current directory. Note that you can view the Terraform state in human-readable format (and .tf friendly format) using the terraform show command.

Run Terraform plan to view differences

We're not quite done yet, we've just captured the remote state and saved it to our local machine (or wherever you are running terraform import from).

Now we need to invoke Terraform to see what would change if we were to run a terraform apply with our current Terraform configuration files. In other words, we need to see what is mismatched between the remote state and our local Terraform configuration files.

We can see what resources that Terraform would change by running the following command in a terminal:

terraform plan

If successful, you'll see output similar to the following after Terraform determines what would need to change such that the Terraform configuration files match the remote state:

google_dialogflow_cx_agent.agent: Refreshing state... [id=projects/your-project-id/locations/us-central1/agents/5717be04-3519-4cb1-9d0e-378333aea9ac]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
-/+ destroy and then create replacement

Terraform will perform the following actions:

  # google_dialogflow_cx_agent.agent must be replaced
-/+ resource "google_dialogflow_cx_agent" "agent" {
      - default_language_code      = "en" -> null # forces replacement
      - display_name               = "Small talk" -> null
      ~ id                         = "projects/your-project-id/locations/us-central1/agents/5717be04-3519-4cb1-9d0e-378333aea9ac" -> (known after apply)
      - location                   = "us-central1" -> null # forces replacement
      ~ name                       = "5717be04-3519-4cb1-9d0e-378333aea9ac" -> (known after apply)
      ~ project                    = "your-project-id" -> (known after apply)
      ~ start_flow                 = "projects/your-project-id/locations/us-central1/agents/5717be04-3519-4cb1-9d0e-378333aea9ac/flows/00000000-0000-0000-0000-000000000000" -> (known after apply)
      - time_zone                  = "America/Los_Angeles" -> null
    }

Plan: 1 to add, 0 to change, 1 to destroy.

Modify Terraform configuration files to match remote state

Now comes the important part, we need to modify the Terraform configuration files (*.tf) so that they would reproduce the remote state that we captured earlier. In other words, we are trying to solve for the problem of "what inputs need to be in my Terraform configuration files such that it would identically reproduce my existing Dialogflow agent?".

Referring to the output in the previous step, we can ignore any lines that contain (known after apply) since those will be handled after we apply the configuration.

The lines that we care about are the ones that involve changes to the arguments in the Dialogflow agent that we defined in Terraform earlier, which are:

-/+ resource "google_dialogflow_cx_agent" "agent" {
      - default_language_code      = "en" -> null # forces replacement
      - display_name               = "Small talk" -> null
      - location                   = "us-central1" -> null # forces replacement
      - time_zone                  = "America/Los_Angeles" -> null
    }

Taking those differences into account and running terraform show to display the Terraform state, let's update the agents.tf file that we created earlier to use the following values rather than the empty placeholder values:

resource "google_dialogflow_cx_agent" "agent" {
  display_name          = "Small talk"
  location              = "us-central1"
  default_language_code = "en"
  time_zone             = "America/Los_Angeles"
}

Now we're ready to continue to the next step and test that our new Terraform configuration matches the Dialogflow agent.

Iterate until Terraform configuration files match remote state

Similar to the earlier step, we can see what resources that Terraform would change by running the following command in a terminal:

terraform plan

If you've successfully matched all of the remote state, you'll see output similar to the following:

google_dialogflow_cx_agent.agent: Refreshing state... [id=projects/your-project-id/locations/us-central1/agents/5717be04-3519-4cb1-9d0e-378333aea9ac]

No changes. Your infrastructure matches the configuration.

Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.

If you see a message similar to the above output: Awesome! We've successfully imported the root Dialogflow agent configuration into Terraform.

If you don't see a message similar to the about output, continue to iterate on your Terraform configuration files and modify the arguments based on terraform plan and terraform show.

Import other agent resources into Terraform

But we're not done yet!

Don't forget about all of the other components that make up your agents: flows, intents, entity types, pages, and so on.

You can repeat the above steps one-by-one to import each component that exists in your agent into your Terraform configuration files.

You might also find it helpful to keep a record of the terraform import commands that you have run and the paths that you have used since they correspond to a specific component in your agent, such as:

terraform import google_dialogflow_cx_agent.agent "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69"

terraform import google_dialogflow_cx_page.request "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69/flows/00000000-0000-0000-0000-000000000000/pages/8806f1fb-c45e-43ba-ac16-47a668ddc9eb"

terraform import google_dialogflow_cx_intent.default_welcome_intent "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69/intents/00000000-0000-0000-0000-000000000000"
terraform import google_dialogflow_cx_intent.agent.residence        "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69/intents/327ed726-043e-41b7-af1f-f34a10a0f1e6"
terraform import google_dialogflow_cx_intent.agent.hungry           "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69/intents/551e2b01-f2bf-49da-8ff4-92adf139b736"
terraform import google_dialogflow_cx_intent.user.testing_agent     "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69/intents/7608701f-a8f5-4519-9b05-97ec2094c634"

At this point, you'll probably also want to use the REST APIs or client libraries in Dialogflow to list and get detailed information about agents, flows, intents, entity types, and all of the other configuration that makes up your virtual agent. This is a good way to ensure that you capture all of the components in your agent.

Keep importing resources from Dialogflow into Terraform until you've completely reproduced your agent. Next, we'll talk about a couple of best practices that might be helpful along the way.

Additional best practices

When importing resources from Dialogflow into Terraform based on the output of terraform plan, you will often end up with lines in your Terraform configuration files that contain static references to specific agents, flows, pages, etc., such as:

page = "projects/your-project-id/locations/us-central1/agents/73696d8a-b312-460e-a88a-3fc00827ed69/flows/00000000-0000-0000-0000-000000000000/pages/e736abf0-bc00-4d65-936b-f56033d12433"

You'll want to convert these static references into variables, which you can find by referring to the Attributes References section in the Dialogflow Terraform documentation. Using this approach, you would change the above line into something like:

page = google_dialogflow_cx_page.request.id

That way, your Terraform configuration files will dynamically substitute the identifiers in the right places. Otherwise, you'll get errors when your new Dialogflow agent is trying to refer to a specific resource from a different agent that no longer exists or has changed!

One final tip, if you find that you are not able to use Terraform to manage certain components or settings in your virtual agent, you can use the REST APIs or client libraries in Dialogflow to configure certain settings. You can even templatize these calls and manage them with Terraform using the null_resource in conjunction with the local_exec provisioner. For an example of this, refer to this example code that templatizes a Dialogflow REST API request in Terraform.

Next steps with Terraform and Dialogflow

Now that you've captured all of your Dialogflow agent settings and configuration in Terraform, you are ready to check your Terraform scripts into version control, spin up and destroy agents as you please using terraform apply and terraform destroy, or even store remote Terraform state in Google Cloud using the GCS backend.

Refer to the following resources to get started importing Dialogflow agents into Terraform:

Happy Importing!