You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dialogflow Agent无法在HTTP请求回调内输出文本的问题

解决Dialogflow Fulfillment异步回调中agent.add()失效的问题

我完全懂你碰到的这个坑——用Dialogflow默认欢迎意图触发外部GET请求时,回调里的agent.add()总是时灵时不灵,看日志才发现函数居然在请求完成前就结束了,导致回调里的输出根本没机会传给Agent。

先看看你当前的代码实现:

'use strict'; 
const functions = require('firebase-functions'); 
const {WebhookClient} = require('dialogflow-fulfillment'); 
const {Card, Suggestion} = require('dialogflow-fulfillment'); 
process.env.DEBUG = 'dialogflow:debug'; 

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { 
  const agent = new WebhookClient({ request, response }); 

  function search(agent){ 
    var request = require("request"); 
    var options = { 
      method: 'GET', 
      url: 'http://google.com' 
    }; 
    console.log("Before request"); 
    agent.add("Before request"); 
    request(options, function (error, response, body){ 
      console.log("Request completed"); 
      agent.add("Request completed"); //<- 这行有时不显示在Agent里
      console.log("finished"); //<- 这行能正常出现在日志里
    }); 
    console.log("Request sent"); 
    agent.add(`Request sent`); 
  } 

  let intentMap = new Map(); 
  intentMap.set('Default Welcome Intent', search); 
  agent.handleRequest(intentMap); 
}); 

问题根源

核心问题出在异步操作的执行时机上:request是回调式的异步函数,当search函数执行到request(options, ...)这一行时,它会立刻发起请求,然后直接往下跑完剩余代码,函数就结束了。而Firebase Functions会在你的函数执行完毕后,立刻终止进程并返回响应——这时候你的HTTP请求回调还没触发呢!所以回调里的agent.add()要么没机会执行,要么执行时进程已经被关闭,自然就失效了。

解决方案:让函数等待异步操作完成

要解决这个问题,我们需要把异步操作改成Promise风格,让search函数等待异步请求完成后再结束进程。这里有两种常用的实现方式:

方式1:用async/await + axios(推荐,代码更简洁)

先安装axios依赖:npm install axios,然后修改代码:

'use strict'; 
const functions = require('firebase-functions'); 
const {WebhookClient} = require('dialogflow-fulfillment'); 
const {Card, Suggestion} = require('dialogflow-fulfillment'); 
const axios = require('axios'); // 引入axios
process.env.DEBUG = 'dialogflow:debug'; 

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { 
  const agent = new WebhookClient({ request, response }); 

  // 把search改成async函数
  async function search(agent){ 
    console.log("Before request"); 
    agent.add("Before request"); 
    try {
      // 用await等待请求完成
      const response = await axios.get('http://google.com');
      console.log("Request completed"); 
      agent.add("Request completed"); 
      console.log("finished"); 
    } catch (error) {
      // 别忘了处理请求错误
      console.error("Request failed:", error);
      agent.add("请求出错了,请稍后再试");
    }
    console.log("Request sent"); 
    agent.add(`Request sent`); 
  } 

  let intentMap = new Map(); 
  intentMap.set('Default Welcome Intent', search); 
  agent.handleRequest(intentMap); 
}); 

方式2:把request包装成Promise

如果不想更换HTTP请求库,可以手动把request的回调逻辑封装成Promise:

'use strict'; 
const functions = require('firebase-functions'); 
const {WebhookClient} = require('dialogflow-fulfillment'); 
const {Card, Suggestion} = require('dialogflow-fulfillment'); 
const request = require("request"); // 移到顶部统一引入
process.env.DEBUG = 'dialogflow:debug'; 

// 封装request为Promise风格的函数
function requestPromise(options) {
  return new Promise((resolve, reject) => {
    request(options, (error, response, body) => {
      if (error) reject(error);
      else resolve({response, body});
    });
  });
}

exports.dialogflowFirebaseFulfillment = functions.https.onRequest((request, response) => { 
  const agent = new WebhookClient({ request, response }); 

  async function search(agent){ 
    console.log("Before request"); 
    agent.add("Before request"); 
    const options = { 
      method: 'GET', 
      url: 'http://google.com' 
    };
    try {
      // 等待Promise完成后再继续执行
      const {response, body} = await requestPromise(options);
      console.log("Request completed"); 
      agent.add("Request completed"); 
      console.log("finished"); 
    } catch (error) {
      console.error("Request failed:", error);
      agent.add("请求出错了,请稍后再试");
    }
    console.log("Request sent"); 
    agent.add(`Request sent`); 
  } 

  let intentMap = new Map(); 
  intentMap.set('Default Welcome Intent', search); 
  agent.handleRequest(intentMap); 
}); 

为什么这样能解决问题?

把search改成async函数后,用await关键字等待异步请求完成,函数会暂停执行直到Promise状态改变,这样Firebase Functions就会等到整个异步流程跑完才终止进程,回调里的agent.add()就能正常生效了。

内容的提问来源于stack exchange,提问作者Raschid JFR

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:32:42