Mantieni tutto organizzato con le raccolte
Salva e classifica i contenuti in base alle tue preferenze.
L'agente predefinito che hai creato nell'ultimo passaggio
non può fornire dati dinamici come i saldi degli account,
perché tutto è hardcoded nell'agente.
In questo passaggio del tutorial,
creerai un
webhook
in grado di fornire dati dinamici all'agente.
Le funzioni Cloud Run vengono utilizzate per ospitare l'webhook in questo tutorial per la loro semplicità, ma esistono molti altri modi per ospitare un servizio webhook.
L'esempio utilizza anche il linguaggio di programmazione Go, ma puoi utilizzare qualsiasi linguaggio supportato da Cloud Run Functions.
Crea la funzione
Le funzioni Cloud Run possono essere create con la console Google Cloud (visita la documentazione, apri la console).
Per creare una funzione per questo tutorial:
È importante che l'agente Dialogflow e la funzione
si trovino entrambi nello stesso progetto.
Questo è il modo più semplice per Dialogflow di avere accesso sicuro alla tua funzione.
Prima di creare la funzione,
seleziona il progetto dalla Google Cloud console.
Fai clic su Crea funzione e imposta i seguenti campi:
Ambiente: 1ª generazione.
Nome della funzione: tutorial-banking-webhook
Regione: se hai specificato una regione per l'agente, utilizza la stessa regione.
Tipo di trigger HTTP: HTTP
URL: fai clic sul pulsante di copia qui e salva il valore.
Ti servirà questo URL durante la configurazione dell'webhook.
Autenticazione: Richiedi autenticazione
Richiedi HTTPS: selezionato
Fai clic su Salva.
Fai clic su Avanti (non sono necessarie impostazioni di runtime, build, connessioni o sicurezza speciali).
Imposta i seguenti campi:
Runtime: seleziona il runtime Go più recente.
Codice sorgente: editor incorporato
Punto di contatto: HandleWebhookRequest
Sostituisci il codice con quanto segue:
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}}
Fai clic su Esegui il deployment.
Attendi che l'indicatore di stato mostri che la funzione è stata dispiegamento correttamente.
Mentre aspetti, esamina il codice che hai appena disegnato.
Configura il webhook per l'agente
Ora che il webhook esiste come servizio,
devi associarlo al tuo agente.
Questo avviene tramite l'evasione degli ordini.
Per attivare e gestire l'evasione degli ordini per il tuo agente:
Seleziona Fulfillment nel menu della barra laterale a sinistra.
Imposta il campo Webhook su Abilitato.
Fornisci l'URL che hai copiato sopra.
Lascia vuoti tutti gli altri campi.
Fai clic su Salva nella parte inferiore della pagina.
Ora che l'agente è attivo,
devi attivare il completamento per un'intenzione:
Seleziona Intent nel menu della barra laterale a sinistra.
Seleziona l'intent account.balance.check.
Scorri verso il basso fino alla sezione Evasione degli ordini.
Attiva l'opzione Abilita chiamata webhook per questo intent.
Fai clic su Salva.
Prova l'agente
L'agente è ora pronto per essere provato.
Fai clic sul pulsante Test agente per aprire il simulatore.
Prova a tenere la seguente conversazione con l'agente:
Turno di conversazione
Tu
Agente
1
Ciao
Ciao, grazie per aver scelto la Banca ACME.
2
Voglio conoscere il saldo del mio conto
Per quale conto vuoi il saldo: di risparmio o corrente?
3
Controllo in corso…
Ecco il tuo saldo più recente: 0,00 $
Al terzo turno di conversazione,
hai fornito "associato a un conto corrente" come tipo di conto.
L'intent account.balance.check ha un parametro chiamato account.
Questo parametro è impostato su "checking" in questa conversazione.
L'intent ha anche un valore di azione "account.balance.check".
Viene chiamato il servizio webhook,
a cui vengono passati i valori del parametro e dell'azione.
Se esamini il codice webhook riportato sopra,
noti che questa azione attiva una chiamata a una funzione con nome simile.
La funzione determina il saldo dell'account.
La funzione controlla se sono impostate variabili di ambiente specifiche con informazioni per la connessione al database.
Se queste variabili di ambiente non sono impostate, la funzione utilizza un saldo dell'account hardcoded.
Nei passaggi successivi,
modificherai l'ambiente per la funzione
in modo che recuperi i dati da un database.
Risoluzione dei problemi
Il codice webhook include istruzioni di logging.
Se riscontri problemi, prova a visualizzare i log della funzione.
Ulteriori informazioni
Per ulteriori informazioni sui passaggi precedenti, consulta:
[[["Facile da capire","easyToUnderstand","thumb-up"],["Il problema è stato risolto","solvedMyProblem","thumb-up"],["Altra","otherUp","thumb-up"]],[["Difficile da capire","hardToUnderstand","thumb-down"],["Informazioni o codice di esempio errati","incorrectInformationOrSampleCode","thumb-down"],["Mancano le informazioni o gli esempi di cui ho bisogno","missingTheInformationSamplesINeed","thumb-down"],["Problema di traduzione","translationIssue","thumb-down"],["Altra","otherDown","thumb-down"]],["Ultimo aggiornamento 2025-09-04 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)"]]