Mantenha tudo organizado com as coleções
Salve e categorize o conteúdo com base nas suas preferências.
O agente predefinido que você criou na última etapa
não pode fornecer dados dinâmicos, como saldos de contas,
porque tudo está codificado no agente.
Nesta etapa do tutorial,
você vai criar um
webhook
que pode fornecer dados dinâmicos ao agente.
As funções do Cloud Run
são usadas para hospedar o webhook neste tutorial devido à simplicidade,
mas há muitas outras maneiras de hospedar um serviço de webhook.
O exemplo também usa a linguagem de programação Go,
mas você pode usar qualquer
linguagem com suporte às funções do Cloud Run.
Criar a função
As funções do Cloud Run podem ser criadas com o console do Google Cloud (acesse a documentação, abra o console).
Para criar uma função para este tutorial:
É importante que o agente do Dialogflow e a função
estejam no mesmo projeto.
Essa é a maneira mais fácil de o Dialogflow ter
acesso seguro à sua função.
Antes de criar a função,
selecione seu projeto no console do Google Cloud .
Clique em Criar função e defina os seguintes campos:
Ambiente: 1ª geração
Nome da função: tutorial-banking-webhook
Região: se você especificou uma região para o agente, use a mesma.
Tipo de gatilho HTTP: HTTP
URL: clique no botão "Copiar" e salve o valor.
Você vai precisar desse URL ao configurar o webhook.
Autenticação: exija autenticação.
Requerer HTTPS: marcada
Clique em Salvar.
Clique em Próxima. Você não precisa de configurações especiais de ambiente de execução, build,
conexões ou segurança.
Defina os seguintes campos:
Ambiente de execução: selecione o ambiente de execução mais recente do Go.
Código-fonte: editor inline
Ponto de entrada: HandleWebhookRequest
Substitua o código por este:
packageestwhimport("context""encoding/json""fmt""log""net/http""os""strings""cloud.google.com/go/spanner""google.golang.org/grpc/codes")//clientisaSpannerclient,createdonlyoncetoavoidcreation//foreveryrequest.//See:https://cloud.google.com/functions/docs/concepts/go-runtime#one-time_initializationvarclient*spanner.Clientfuncinit(){//Ifusingadatabase,theseenvironmentvariableswillbeset.pid:=os.Getenv("PROJECT_ID")iid:=os.Getenv("SPANNER_INSTANCE_ID")did:=os.Getenv("SPANNER_DATABASE_ID")ifpid!="" && iid!="" && did!=""{db:=fmt.Sprintf("projects/%s/instances/%s/databases/%s",pid,iid,did)log.Printf("Creating Spanner client for %s",db)varerrerror//Usethebackgroundcontextwhencreatingtheclient,//butusetherequestcontextforcallstotheclient.//See:https://cloud.google.com/functions/docs/concepts/go-runtime#contextcontextclient,err=spanner.NewClient(context.Background(),db)iferr!=nil{log.Fatalf("spanner.NewClient: %v",err)}}}typequeryResultstruct{Actionstring`json:"action"`Parametersmap[string]interface{}`json:"parameters"`}typetextstruct{Text[]string`json:"text"`}typemessagestruct{Texttext`json:"text"`}//webhookRequestisusedtounmarshalaWebhookRequestJSONobject.Notethat//notallmembersneedtobedefined--justthosethatyouneedtoprocess.//Asanalternative,youcouldusethetypesprovidedby//theDialogflowprotocolbuffers://https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookRequesttypewebhookRequeststruct{Sessionstring`json:"session"`ResponseIDstring`json:"responseId"`QueryResultqueryResult`json:"queryResult"`}//webhookResponseisusedtomarshalaWebhookResponseJSONobject.Notethat//notallmembersneedtobedefined--justthosethatyouneedtoprocess.//Asanalternative,youcouldusethetypesprovidedby//theDialogflowprotocolbuffers://https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookResponsetypewebhookResponsestruct{FulfillmentMessages[]message`json:"fulfillmentMessages"`}//accountBalanceCheckhandlesthesimilarnamedactionfuncaccountBalanceCheck(ctxcontext.Context,requestwebhookRequest)(webhookResponse,error){account:=request.QueryResult.Parameters["account"].(string)account=strings.ToLower(account)vartablestringifaccount=="savings account"{table="Savings"}else{table="Checking"}s:="Your balance is $0"ifclient!=nil{//ASpannerclientexists,soaccessthedatabase.//See:https://pkg.go.dev/cloud.google.com/go/spanner#ReadOnlyTransaction.ReadRowrow,err:=client.Single().ReadRow(ctx,table,spanner.Key{1},//TheaccountID[]string{"Balance"})iferr!=nil{ifspanner.ErrCode(err)==codes.NotFound{log.Printf("Account %d not found",1)}else{returnwebhookResponse{},err}}else{//Arowwasreturned,socheckthevaluevarbalanceint64err:=row.Column(0, &balance)iferr!=nil{returnwebhookResponse{},err}s=fmt.Sprintf("Your balance is $%.2f",float64(balance)/100.0)}}response:=webhookResponse{FulfillmentMessages:[]message{{Text:text{Text:[]string{s},},},},}returnresponse,nil}//Defineatypeforhandlerfunctions.typehandlerFnfunc(ctxcontext.Context,requestwebhookRequest)(webhookResponse,error)//Createamapfromactiontohandlerfunction.varhandlersmap[string]handlerFn=map[string]handlerFn{"account.balance.check":accountBalanceCheck,}//handleErrorhandlesinternalerrors.funchandleError(whttp.ResponseWriter,errerror){log.Printf("ERROR: %v",err)http.Error(w,fmt.Sprintf("ERROR: %v",err),http.StatusInternalServerError)}//HandleWebhookRequesthandlesWebhookRequestandsendstheWebhookResponse.funcHandleWebhookRequest(whttp.ResponseWriter,r*http.Request){varrequestwebhookRequestvarresponsewebhookResponsevarerrerror//ReadinputJSONiferr=json.NewDecoder(r.Body).Decode(&request);err!=nil{handleError(w,err)return}log.Printf("Request: %+v",request)//Gettheactionfromtherequest,andcallthecorresponding//functionthathandlesthataction.action:=request.QueryResult.Actioniffn,ok:=handlers[action];ok{response,err=fn(r.Context(),request)}else{err=fmt.Errorf("Unknown action: %s",action)}iferr!=nil{handleError(w,err)return}log.Printf("Response: %+v",response)//Sendresponseiferr=json.NewEncoder(w).Encode(&response);err!=nil{handleError(w,err)return}}
Clique em Implantar.
Aguarde até que o indicador de status mostre que a função foi implantada.
Enquanto aguarda, examine o código que você acabou de implantar.
Configurar o webhook para o agente
Agora que o webhook existe como um serviço,
é necessário associá-lo ao seu agente.
Isso é feito pelo fulfillment.
Para ativar e gerenciar o fulfillment do agente:
Selecione o agente predefinido que você acabou de criar.
Selecione Fulfillment no menu da barra lateral esquerda.
Alterne o campo Webhook para Ativado.
Informe o URL que você copiou acima.
Não preencha os outros campos.
Clique em Salvar, na parte inferior da página.
Agora que o fulfillment está ativado para o agente,
é necessário ativar o fulfillment para uma intent:
Selecione Intents no menu da barra lateral à esquerda.
Selecione a intent account.balance.check.
Role para baixo até a seção Fulfillment.
Alternar Ativar chamada de webhook para este intent para ativada.
Clique em Salvar.
Testar o agente
Seu agente está pronto para ser testado.
Clique no botão Testar agente para abrir o simulador.
Tente ter a seguinte conversa com o agente:
Turno de conversa
Você
Agente
1
Olá
Olá, agradecemos por escolher o ACME Bank.
2
Quero saber o saldo da minha conta
Qual conta você quer consultar o saldo: poupança ou corrente?
3
Verificando
Este é seu saldo mais recente: $0,00
Na terceira vez que você interagiu com o bot,
você informou "checking" como o tipo de conta.
A intent account.balance.check tem um parâmetro chamado account.
Esse parâmetro está definido como "verificando" nesta conversa.
A intent também tem um valor de ação de "account.balance.check".
O serviço de webhook é chamado
e recebe os valores de parâmetro e ação.
Se você examinar o código do webhook acima,
vai notar que essa ação aciona uma função com nome semelhante para ser chamada.
A função determina o saldo da conta.
A função verifica se variáveis de ambiente específicas estão definidas
com informações para conexão ao banco de dados.
Se essas variáveis de ambiente não estiverem definidas,
a função vai usar um saldo de conta codificado.
Nas próximas etapas,
você vai alterar o ambiente da função
para que ela extraia dados de um banco de dados.
Solução de problemas
O código do webhook inclui instruções de registro.
Se você tiver problemas, tente conferir os registros da sua função.
Mais informações
Para mais informações sobre as etapas acima, consulte:
[[["Fácil de entender","easyToUnderstand","thumb-up"],["Meu problema foi resolvido","solvedMyProblem","thumb-up"],["Outro","otherUp","thumb-up"]],[["Difícil de entender","hardToUnderstand","thumb-down"],["Informações incorretas ou exemplo de código","incorrectInformationOrSampleCode","thumb-down"],["Não contém as informações/amostras de que eu preciso","missingTheInformationSamplesINeed","thumb-down"],["Problema na tradução","translationIssue","thumb-down"],["Outro","otherDown","thumb-down"]],["Última atualização 2025-08-18 UTC."],[[["\u003cp\u003eThis tutorial guides you through creating a webhook using Cloud Run functions to provide dynamic data, such as account balances, to a Dialogflow agent, enhancing its capabilities beyond hardcoded responses.\u003c/p\u003e\n"],["\u003cp\u003eThe webhook, hosted via Cloud Run functions, interacts with the Dialogflow agent through fulfillment, and this interaction is triggered by specific intents, in this example, the 'account.balance.check' intent.\u003c/p\u003e\n"],["\u003cp\u003eThe example uses the Go programming language to develop the webhook code, which can be viewed and edited inline within the Google Cloud console, and handles requests and responses between Dialogflow and a potential database.\u003c/p\u003e\n"],["\u003cp\u003eTo set up the webhook, you must first create a Cloud Run function within the same Google Cloud project as your Dialogflow agent, ensuring secure access, then configure fulfillment within Dialogflow, associating it with the created function's URL.\u003c/p\u003e\n"],["\u003cp\u003eAfter enabling the webhook for specific intents and configuring fulfillment, you can test the enhanced Dialogflow agent using the simulator, where the agent can now retrieve and display dynamic account balance information.\u003c/p\u003e\n"]]],[],null,["# Create a webhook service\n\nThe prebuilt agent you created in the last step\ncannot provide dynamic data like account balances,\nbecause everything is hardcoded into the agent.\nIn this step of the tutorial,\nyou will create a\n[webhook](/dialogflow/es/docs/fulfillment-overview)\nthat can provide dynamic data to the agent.\n[Cloud Run functions](/functions/docs)\nare used to host the webhook in this tutorial due to their simplicity,\nbut there are many other ways that you could host a webhook service.\nThe example also uses the Go programming language,\nbut you can use any\n[language supported by Cloud Run functions](/functions/docs/concepts/exec).\n\nCreate the Function\n-------------------\n\nCloud Run functions can be created with the Google Cloud console ([visit documentation](https://support.google.com/cloud/answer/3465889?ref_topic=3340599), [open console](https://console.cloud.google.com/)).\nTo create a function for this tutorial:\n\n1. It is important that your Dialogflow agent and the function\n are both in the same project.\n This is the easiest way for Dialogflow to have\n [secure access to your function](/dialogflow/es/docs/fulfillment-webhook#gcf).\n Before creating the function,\n select your project from the Google Cloud console.\n\n [Go to project selector](https://console.cloud.google.com/projectselector2/home/dashboard)\n2. Open the Cloud Run functions overview page.\n\n [Go to Cloud Run functions overview](https://console.cloud.google.com/functions/list)\n3. Click **Create Function**, and set the following fields:\n\n - **Environment**: 1st gen\n - **Function name**: tutorial-banking-webhook\n - **Region**: If you specified a region for your agent, use the same region.\n - **HTTP Trigger type**: HTTP\n - **URL**: Click the copy button here and save the value. You will need this URL when configuring the webhook.\n - **Authentication**: Require authentication\n - **Require HTTPS**: checked\n4. Click **Save**.\n\n5. Click **Next** (You do not need special runtime, build,\n connections, or security settings).\n\n6. Set the following fields:\n\n - **Runtime**: Select the latest Go runtime.\n - **Source code**: Inline Editor\n - **Entry point**: HandleWebhookRequest\n7. Replace the code with the following:\n\n ```python\n package estwh\n\n import (\n \t\"context\"\n \t\"encoding/json\"\n \t\"fmt\"\n \t\"log\"\n \t\"net/http\"\n \t\"os\"\n \t\"strings\"\n\n \t\"cloud.google.com/go/spanner\"\n \"google.golang.org/grpc/codes\"\n )\n\n // client is a Spanner client, created only once to avoid creation\n // for every request.\n // See: https://cloud.google.com/functions/docs/concepts/go-runtime#one-time_initialization\n var client *spanner.Client\n\n func init() {\n \t// If using a database, these environment variables will be set.\n \tpid := os.Getenv(\"PROJECT_ID\")\n \tiid := os.Getenv(\"SPANNER_INSTANCE_ID\")\n \tdid := os.Getenv(\"SPANNER_DATABASE_ID\")\n \tif pid != \"\" && iid != \"\" && did != \"\" {\n \t\tdb := fmt.Sprintf(\"projects/%s/instances/%s/databases/%s\",\n \t\t\tpid, iid, did)\n \t\tlog.Printf(\"Creating Spanner client for %s\", db)\n \t\tvar err error\n \t\t// Use the background context when creating the client,\n \t\t// but use the request context for calls to the client.\n \t\t// See: https://cloud.google.com/functions/docs/concepts/go-runtime#contextcontext\n \t\tclient, err = spanner.NewClient(context.Background(), db)\n \t\tif err != nil {\n \t\t\tlog.Fatalf(\"spanner.NewClient: %v\", err)\n \t\t}\n \t}\n }\n\n type queryResult struct {\n \tAction string `json:\"action\"`\n \tParameters map[string]interface{} `json:\"parameters\"`\n }\n\n type text struct {\n \tText []string `json:\"text\"`\n }\n\n type message struct {\n \tText text `json:\"text\"`\n }\n\n // webhookRequest is used to unmarshal a WebhookRequest JSON object. Note that\n // not all members need to be defined--just those that you need to process.\n // As an alternative, you could use the types provided by\n // the Dialogflow protocol buffers:\n // https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookRequest\n type webhookRequest struct {\n \tSession string `json:\"session\"`\n \tResponseID string `json:\"responseId\"`\n \tQueryResult queryResult `json:\"queryResult\"`\n }\n\n // webhookResponse is used to marshal a WebhookResponse JSON object. Note that\n // not all members need to be defined--just those that you need to process.\n // As an alternative, you could use the types provided by\n // the Dialogflow protocol buffers:\n // https://godoc.org/google.golang.org/genproto/googleapis/cloud/dialogflow/v2#WebhookResponse\n type webhookResponse struct {\n \tFulfillmentMessages []message `json:\"fulfillmentMessages\"`\n }\n\n // accountBalanceCheck handles the similar named action\n func accountBalanceCheck(ctx context.Context, request webhookRequest) (\n \twebhookResponse, error) {\n \taccount := request.QueryResult.Parameters[\"account\"].(string)\n \taccount = strings.ToLower(account)\n \tvar table string\n \tif account == \"savings account\" {\n \t\ttable = \"Savings\"\n \t} else {\n \t\ttable = \"Checking\"\n \t}\n \ts := \"Your balance is $0\"\n \tif client != nil {\n \t\t// A Spanner client exists, so access the database.\n \t\t// See: https://pkg.go.dev/cloud.google.com/go/spanner#ReadOnlyTransaction.ReadRow\n \t\trow, err := client.Single().ReadRow(ctx,\n \t\t\ttable,\n \t\t\tspanner.Key{1}, // The account ID\n \t\t\t[]string{\"Balance\"})\n \t\tif err != nil {\n \t\t\tif spanner.ErrCode(err) == codes.NotFound {\n \t\t\t\tlog.Printf(\"Account %d not found\", 1)\n \t\t\t} else {\n \t\t\t\treturn webhookResponse{}, err\n \t\t\t}\n \t\t} else {\n \t\t\t// A row was returned, so check the value\n \t\t\tvar balance int64\n \t\t\terr := row.Column(0, &balance)\n \t\t\tif err != nil {\n \t\t\t\treturn webhookResponse{}, err\n \t\t\t}\n \t\t\ts = fmt.Sprintf(\"Your balance is $%.2f\", float64(balance)/100.0)\n \t\t}\n \t}\n \tresponse := webhookResponse{\n \t\tFulfillmentMessages: []message{\n \t\t\t{\n \t\t\t\tText: text{\n \t\t\t\t\tText: []string{s},\n \t\t\t\t},\n \t\t\t},\n \t\t},\n \t}\n \treturn response, nil\n }\n\n // Define a type for handler functions.\n type handlerFn func(ctx context.Context, request webhookRequest) (\n \twebhookResponse, error)\n\n // Create a map from action to handler function.\n var handlers map[string]handlerFn = map[string]handlerFn{\n \t\"account.balance.check\": accountBalanceCheck,\n }\n\n // handleError handles internal errors.\n func handleError(w http.ResponseWriter, err error) {\n \tlog.Printf(\"ERROR: %v\", err)\n \thttp.Error(w,\n \t\tfmt.Sprintf(\"ERROR: %v\", err),\n \t\thttp.StatusInternalServerError)\n }\n\n // HandleWebhookRequest handles WebhookRequest and sends the WebhookResponse.\n func HandleWebhookRequest(w http.ResponseWriter, r *http.Request) {\n \tvar request webhookRequest\n \tvar response webhookResponse\n \tvar err error\n\n \t// Read input JSON\n \tif err = json.NewDecoder(r.Body).Decode(&request); err != nil {\n \t\thandleError(w, err)\n \t\treturn\n \t}\n \tlog.Printf(\"Request: %+v\", request)\n\n \t// Get the action from the request, and call the corresponding\n \t// function that handles that action.\n \taction := request.QueryResult.Action\n \tif fn, ok := handlers[action]; ok {\n \t\tresponse, err = fn(r.Context(), request)\n \t} else {\n \t\terr = fmt.Errorf(\"Unknown action: %s\", action)\n \t}\n \tif err != nil {\n \t\thandleError(w, err)\n \t\treturn\n \t}\n \tlog.Printf(\"Response: %+v\", response)\n\n \t// Send response\n \tif err = json.NewEncoder(w).Encode(&response); err != nil {\n \t\thandleError(w, err)\n \t\treturn\n \t}\n }\n ```\n\n \u003cbr /\u003e\n\n8. Click **Deploy**.\n\n9. Wait until the status indicator shows that the function\n has successfully deployed.\n While waiting, examine the code you just deployed.\n\nConfigure the webhook for your agent\n------------------------------------\n\nNow that the webhook exists as a service,\nyou need to associate this webhook with your agent.\nThis is done via fulfillment.\nTo enable and manage fulfillment for your agent:\n\n1. Go to the [Dialogflow ES console](https://dialogflow.cloud.google.com).\n2. Select the pre-built agent you just created.\n3. Select **Fulfillment** in the left sidebar menu.\n4. Toggle the **Webhook** field to **Enabled**.\n5. Provide the URL that you copied from above. Leave all other fields blank.\n6. Click **Save** at the bottom of the page.\n\nNow that fulfillment is enabled for the agent,\nyou need to enable fulfillment for an intent:\n\n1. Select **Intents** in the left sidebar menu.\n2. Select the **account.balance.check** intent.\n3. Scroll down to the **Fulfillment** section.\n4. Toggle **Enable webhook call for this intent** to on.\n5. Click **Save**.\n\nTry the agent\n-------------\n\nYour agent is now ready to try.\nClick the **Test Agent** button to open the simulator.\nAttempt to have the following conversation with the agent:\n\nAt conversational turn #3,\nyou supplied \"checking\" as the account type.\nThe **account.balance.check** intent has a parameter called **account**.\nThis parameter is set to \"checking\" in this conversation.\nThe intent also has an action value of \"account.balance.check\".\nThe webhook service is called,\nand it is passed the parameter and action values.\n\nIf you examine the webhook code above,\nyou see that this action triggers a similar named function to be called.\nThe function determines the account balance.\nThe function checks whether specific environment variables are set\nwith information for connecting to the database.\nIf these environment variables are not set,\nthe function uses a hardcoded account balance.\nIn upcoming steps,\nyou will alter the environment for the function\nso that it retrieves data from a database.\n\nTroubleshooting\n---------------\n\nThe webhook code includes logging statements.\nIf you are having issues, try viewing the logs for your function.\n\nMore information\n----------------\n\nFor more information about the steps above, see:\n\n- [Cloud Run functions Go quickstart](/functions/docs/console-quickstart-1st-gen)"]]