Migrate fulfillment from API V1 to V2

Throughout the migration process of going from V1 to V2, if you use Dialogflow fulfillment, you'll need to make sure you respond correctly to Dialogflow's V2 webhook requests. Ultimately, webhook requests you receive from Dialogflow and the responses to those webhook requests will be different between V1 and V2.

Dialogflow's fulfillment library and the Action on Google V2 client library for Node.js support both Dialogflow V1 and V2 webhook requests and responses. After migrating to either library, your fulfillment can seamlessly migrate from V1 to V2 because both libraries support Dialogflow V1 and V2 webhook requests & responses. For other platforms please refer to the Webhook Request and Response JSON.


Fulfillment and Actions on Google V2 libraries for Node.js

The libraries listed below support both Dialogflow V1 and V2 webhook requests and responses. Both libraries eliminate the need to maintain fulfillment for both V1 and V2. If you are already using the Dialogflow fulfillment library, or V2 of the Actions on Google client library, your fulfillment is already compatible with Dialogflow V2 webhook requests and responses. For platforms other than Node.js, please see Webhook Request and Response JSON.

Dialogflow Fulfillment Library for Node.js

If you are currently using Node.js for your fulfillment, we recommend migrating to Dialogflow's fulfillment library, which supports webhook requests and responses for Dialogflow API V1 and V2. The Dialogflow fulfillment library also supports multiple platforms (Google Assistant, Slack, Facebook Messenger, and 5 others) for building cross-platform fulfillment. You can find the Dialogflow fulfillment library on Github and npm. Check out the quick start guide or samples to get started.

Actions on Google Client Library V2 for Node.js

Actions on Google's client library V1 supports Dialogflow V1 only and does not support Dialogflow V2. Please upgrade to Action on Google Client Library V2 for Dialogflow V1 and V2 support. Actions on Google client library V2 supports Dialogflow V1 and V2 and is best for fulfillment when your agent is only utilizing the Google Assistant integration. You can find the Action on Google V2 client library on Github and npm. Check out the quick start guide or samples to get started.


Webhook Request and Response JSON

If not using the Dialogflow Fulfillment or Actions on Google library, your backend will need to support receiving HTTP POST requests from Dialogflow as well as responding properly. The HTTP request from Dialogflow contains information about how Dialogflow processed the request as well as information about the original request from Google Assistant, Slack, detect intent API call, or other integration. Both the request and the expected response have changed from V1 to V2 and must have JSON bodies structured as described in the next two sections.

Webhook Request

If you have configured your agent and intents to use fulfillment, a HTTP POST request will be made to the URL you have configured. The body of the request will contain JSON structured to provide you information about Dialogflow's evaluation of the request and information about the original request from the user. Below, you can see an example comparing the differences between V1 and V2 JSON body request formats:

V1 Webhook Request

{
  "id": "7811ac58-5bd5-4e44-8d06-6cd8c67f5406",
  "sessionId": "1515191296300",
  "timestamp": "2018-01-05T22:35:05.903Z",
  "timezone": "",
  "lang": "en-us",
  "result": {
    "source": "agent",
    "resolvedQuery": "user's original query to your agent",
    "speech": "Text defined in Dialogflow's console for the intent that was matched",
    "action": "Matched Dialogflow intent action name",
    "actionIncomplete": false,
    "parameters": {
      "param": "param value"
    },
    "contexts": [
      {
        "name": "incoming context name",
        "parameters": {},
        "lifespan": 0
      }
    ],
    "metadata": {
      "intentId": "29bcd7f8-f717-4261-a8fd-2d3e451b8af8",
      "webhookUsed": "true",
      "webhookForSlotFillingUsed": "false",
      "nluResponseTime": 6,
      "intentName": "Name of Matched Dialogflow Intent"
    },
    "fulfillment": {
      "speech": "Text defined in Dialogflow's console for the intent that was matched",
      "messages": [
        {
          "type": 0,
          "speech": "Text defined in Dialogflow's console for the intent that was matched"
        }
      ]
    },
    "score": 1
  },
  "originalRequest": {
    "source": "google",
    "version": "2",
    "data": {
      "isInSandbox": true,
      "surface": {
        "capabilities": [...]
      },
      "inputs": [...],
      "user": {...},
      "conversation": {...},
      "availableSurfaces": [...]
    }
  },
}
    

V2 Webhook Request

{
  "responseId": "ea3d77e8-ae27-41a4-9e1d-174bd461b68c",
  "session": "projects/your-agents-project-id/agent/sessions/88d13aa8-2999-4f71-b233-39cbf3a824a0",
  "queryResult": {
    "languageCode": "en",
    "queryText": "user's original query to your agent",
    "fulfillmentText": "Text defined in Dialogflow's console for the intent that was matched",
    "action": "action name",
    "allRequiredParamsPresent": true,
    "parameters": {
      "param": "param value"
    },
    "outputContexts": [
      {
        "name": "projects/your-agents-project-id/agent/sessions/88d13aa8-2999-4f71-b233-39cbf3a824a0/contexts/generic",
        "lifespanCount": 5,
        "parameters": {
          "param": "param value",
        }
      }
    ],
    "intent": {
      "name": "projects/your-agents-project-id/agent/intents/29bcd7f8-f717-4261-a8fd-2d3e451b8af8",
      "displayName": "Matched Intent Name"
    },
    "fulfillmentMessages": [
      {
        "text": {
          "text": [
            "Text defined in Dialogflow's console for the intent that was matched"
          ]
        }
      }
    ],
    "intentDetectionConfidence": 1,
    "diagnosticInfo": {},
  },
  "originalDetectIntentRequest": {
    "source": "google",
    "version": "2",
    "payload": {
      "isInSandbox": true,
      "surface": {
        "capabilities": [...]
      },
      "inputs": [...],
      "user": {...},
      "conversation": {...},
      "availableSurfaces": [...]
    }
  },
}
    

Intent ID and names

  • The id field used in V1 is now the name field in V2.
  • The name field in V1 is now the displayName field in V2.

Intent IDs in V2 are prefixed with /projects/<PROJECTID>/agent/intents/.

Intent ID V1 V2

Webhook Field

result.metadata.intentId queryResult.intent.name

Format

<INTENTID> /projects/<PROJECTID>/agent/intents/<INTENTID>

Example

29bcd7f8-f717-4261-a8fd-2d3e451b8af8 projects/your-project-id/agent/intents/8b006880-0af7-4ec9-a4c3-1cc503ea8260

Context and Session

Please see the context and session section for how sessions have changed from V1 to V2.

Fulfillment Messages

Messages defined in Dialogflow's console for an intent are sent in every webhook request that has matched the same intent. These messages can also be sent back to Dialogflow as a response(s) to the user. The name (messages/fulfillmentMessages) and format of these messages differs from V1 to V2. For a full list of V1 fulfillment messages and their V2 equivalents, please refer to the JSON migration reference.

result to queryResult

All the information previously found in the result attribute of the JSON request has moved to the queryResult attribute in V2. These attributes contain the following information:

  • Query from the user
  • Parameter, active context, and matched intent information (name, id, etc.)
  • Response messages defined in Dialogflow's console, and intent matching confidence

For a full list of V1 result fields and their V2 equivalents, please refer to the JSON migration reference.

originalRequest to originalDetectIntentRequest

All the information in the originalRequest attribute of the JSON request has moved to the originalDetectIntentRequest attribute in V2. These attributes contain integration specific information like the following:

  • User IDs, user authentication, ordering/transaction information, etc.
  • How the user is accessing your action (phone, speaker, etc.)
  • Conversation metadata (no input, user-prompted end of conversation, etc.)

This information is dependent on the platform the user is currently using (i.e. Google Assistant, Slack, Facebook Messenger, etc.).

Examples

Below is a list of webhook request JSON bodies you can expect for a variety of Dialogflow and Google Assistant requests to help you know what to expect when migrating from V1 to V2:

Generic Request V2 JSON V1 JSON
Action on Google Request V2 JSON V1 JSON
Actions on Google: Welcome Event V2 JSON V1 JSON
Actions on Google: Permission Event V2 JSON V1 JSON
Actions on Google: List Selection Event V2 JSON V1 JSON
Actions on Google: Confirmation Event V2 JSON V1 JSON
Actions on Google: Datetime Event V2 JSON V1 JSON
Actions on Google: Delivery Address Event V2 JSON V1 JSON
Actions on Google: End Conversation Event V2 JSON V1 JSON
Actions on Google: No Input Event V2 JSON V1 JSON

Webhook Responses

After receiving a webhook request from Dialogflow, your backend must respond with a correctly formatted response within the timeout limit. Your backend's response to this request must have the header Content-Type set to the value application/json and the body of the response must contain properly formatted and valid JSON. The expected response format differs from V1 and V2. Below, you can see an example comparing the differences between expected V1 and V2 JSON body response formats:

V1 Webhook Response

{
  "speech": "spoken response",
  "displayText": "displayed response",
  "messages": [
    {
      "speech": "Text response",
      "type": 0
    }
  ],
  "source": "example.com",
  "data": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "this is a simple response"
            }
          }
        ]
      }
    },
    "facebook": {
      "text": "Hello, Facebook!"
    },
    "slack": {
      "text": "This is a text response for Slack."
    }
  },
  "contextOut": [
    {
      "name": "context name",
      "lifespan": 5,
      "parameters": {
        "param": "param value"
      }
    }
  ],
  "followupEvent": {
    "name": "event name",
    "parameters": {
      "param": "param value"
    }
  }
}
    

V2 Webhook Response

{
  "fulfillmentText": "displayed&spoken response",
  "fulfillmentMessages": [
    {
      "text": [
        "text response"
      ],
    }
  ],
  "source": "example.com",
  "payload": {
    "google": {
      "expectUserResponse": true,
      "richResponse": {
        "items": [
          {
            "simpleResponse": {
              "textToSpeech": "this is a simple response"
            }
          }
        ]
      }
    },
    "facebook": {
      "text": "Hello, Facebook!"
    },
    "slack": {
      "text": "This is a text response for Slack."
    }
  },
  "outputContexts": [
    {
      "name": "projects/${PROJECT_ID}/agent/sessions/${SESSION_ID}/contexts/context name",
      "lifespanCount": 5,
      "parameters": {
        "param": "param value"
      }
    }
  ],
  "followupEventInput": {
    "name": "event name",
    "languageCode": "en-US",
    "parameters": {
      "param": "param value"
    }
  }
}
    

Context and Session

Please see the contexts and session section for how sessions have changed from V1 to V2.

Fulfillment Messages

Messages defined in Dialogflow's console for an intent are sent in every webhook request that has matched the same intent. These messages can also be sent back to Dialogflow as a response(s) to the user. The name (messages/fulfillmentMessages) and format of these messages differs from V1 to V2. For a full list of V1 fulfillment messages and their V2 equivalents, please see the JSON migration reference.

Examples

Below is a list of webhook response JSON bodies you can send to respond to your users for a variety of circumstances with versions for both V1 and V2 to help you migrate:

Generic Response V2 JSON V1 JSON
Actions on Google: Simple Response V2 JSON V1 JSON
Actions on Google: Basic Card V2 JSON V1 JSON
Actions on Google: End Conversation V2 JSON V1 JSON
Actions on Google: No Input V2 JSON V1 JSON
Actions on Google: Carousel V2 JSON V1 JSON
Actions on Google: List V2 JSON V1 JSON
Actions on Google: SSML V2 JSON V1 JSON
Actions on Google: TTS V2 JSON V1 JSON
Actions on Google: Suggestions V2 JSON V1 JSON
Actions on Google: Ask for Confirmation V2 JSON V1 JSON
Actions on Google: Ask for Datetime V2 JSON V1 JSON
Actions on Google: Ask for delivery address V2 JSON V1 JSON
Actions on Google: Ask for permission V2 JSON V1 JSON
Actions on Google: Ask for sign in V2 JSON V1 JSON

Contexts and Sessions

Sessions now include the Google Cloud Project ID, which is created when you create/import your Dialogflow agent and the session ID and have the form projects/<PROJECTID>/agent/sessions/<SESSIONID>. A Session attribute is included in each webhook request that indicates the full session path (project ID and session ID)
\ { \ "session": "projects/${PROJECTID}/agent/sessions/${SESSIONID}" \ // other webhook request fields \ … \ } \

Contexts

The session path prefixes all context names with the format projects/<PROJECTID>/agent/sessions/<SESSIONID>/contexts/<CONTEXT_NAME>. When creating/specifying new contexts in V2, you must include the prefix in the context name.

Project ID

You can find the Project ID for your Dialogflow agent in your agent's settings under the General tab.


JSON Migration Reference

Webhook Requests

Top Level Attributes

V1 V2
result queryResult
originalRequest originalDetectIntentRequest
sessionId session
id responseId
lang see queryResult.languageCode
status N/A
timestamp N/A

result to queryResult

V1 V2
result.source Not applicable
result.resolvedQuery queryResult.queryText
result.action queryResult.action
result.actionIncomplete queryResult.allRequiredParamsCollected
result.parameters queryResult.parameters
result.contexts queryResult.outputContexts
result.contexts.name queryResult.outputContexts.name
result.contexts.parameters queryResult.outputContexts.parameters
result.contexts.lifespan queryResult.outputContexts.lifespanCount
result.fulfillment queryResult.fulfillment
result.fulfillment.speech queryResult.fulfillment.text
result.fulfillment.messages queryResult.fulfillment.messages
result.score queryResult.intentDetectionConfidence
result.metadata queryResult.intent
result.metadata.intentId queryResult.intent.name
result.metadata.webhookUsed queryResult.intent.webhookState
result.metadata.webhookForSlotFillingUsed queryResult.intent.webhookState
result.metadata.webhookResponseTime queryResult.diagnosticInfo.webhookLatencySeconds
result.metadata.intentName queryResult.intent.displayName

Webhook Responses

Top level attributes

V1 V2
speech fulfillmentText
displayText fulfillmentText
messages fulfillmentMessages
data payload
contextOut outputContexts
source source
followEvent followupEventInput

Contexts

V1 V2
contextOut.name outputContexts.name*
contextOut.lifespan outputContexts.lifespanCount
contextOut.parameters outputContexts.parameters

* Must prefix context name with session; see [Contexts and Sessions](#contexts_and_session).

Follow-up Event

V1 V2
followupEvent.name followupEventInput.name
N/A followupEventInput.languageCode
followupEvent.parameters followupEventInput.parameters

Fulfillment message objects

See our Message Objects page for V1 and V2 comparisons.

Text

V1 V2
{
  "platform": "facebook",
  "speech": "Text response",
  "type": 0
}
      
{
  "platform": "ACTIONS_ON_GOOGLE",
  "text": {
    "text": [
      "Text response"
    ]
  }
}
      

Image

V1 V2
{
  "imageUrl": "http://urltoimage.com",
  "platform": "facebook",
  "type": 3
}
      
{
  "platform": "ACTIONS_ON_GOOGLE",
  "image": {
    "imageUri": "https://example.com/image.jpg",
  }
}
      

Card

V1 V2
{
  "buttons": [
    {
      "postback": "Card Link URL or text",
      "text": "Card Link Title"
    }
  ],
  "imageUrl": "http://urltoimage.com",
  "platform": "facebook",
  "subtitle": "Card Subtitle",
  "title": "Card Title",
  "type": 1
}
      
{
  "platform": "ACTIONS_ON_GOOGLE",
  "card": {
    "title": "card title",
    "subtitle": "card subtitle",
    "imageUri": "https://example.com/image.jpg",
    "buttons": [
      {
        "text": "Button Text",
        "postback": "https://example.com"
      }
    ]
  }
}
      

Quick Replies

V1 V2
{
  "platform": "facebook",
  "replies": [
    "Quick reply 1",
    "Quick reply 2",
    "Quick reply 3"
  ],
  "title": "Quick Reply Title",
  "type": 2
}
      
{
  "platform": "ACTIONS_ON_GOOGLE",
  "quickReplies": {
    "title": "quick replies title",
    "quickReplies": [
      "quick reply 1",
      "quick reply 2",
      "quick reply 3"
    ]
  }
}