Dialogflow에서 살펴보기
계속을 클릭하여 Dialogflow에서 Surface 기능 샘플을 가져옵니다. 그런 다음 다음 단계에 따라 샘플을 배포하고 테스트합니다.
- 에이전트 이름을 입력하고 샘플의 새 Dialogflow 에이전트를 만듭니다.
- 에이전트 가져오기가 완료되면 Go to agent를 클릭합니다.
- 기본 탐색 메뉴에서 fulfillment로 이동합니다.
- 인라인 편집기를 사용 설정한 다음 배포를 클릭합니다. 편집기에 샘플 파일이 포함되어 있고 있습니다.
- 기본 탐색 메뉴에서 Integrations로 이동한 다음 Google을 클릭합니다. 어시스턴트를 탭합니다.
- 모달 창이 나타나면 변경사항 자동 미리보기를 사용 설정하고 테스트를 클릭합니다. 작업 시뮬레이터를 엽니다.
- 시뮬레이터에서
Talk to my test app
를 입력하여 샘플을 테스트합니다.
내 작업은 오디오 전용 모드를 비롯한 다양한 표시 경로에 표시 경로 (스마트 스피커), 오디오 및 디스플레이 표면 (예: 스마트 디스플레이 및 합니다.
모든 표시 경로에서 원활하게 작동하는 대화를 설계하고 빌드하려면 노출 영역을 사용하세요. 대화를 제어하고 범위를 정하는 데 도움이 됩니다.
작업 기능 표시
Actions on Google을 사용하면 영향을 줄 수 있습니다. 사용자가 기기에 문제가 있다는 오류 메시지가 있습니다.
작업 프로젝트에서 작업의 노출 영역 지원을 정의합니다.
내 작업은 다양한 위치에 표시될 수 있으며 스마트폰 (Android 및 iOS)과 Google Home 기기
런타임 노출 영역 기능
런타임 노출 영역 기능으로 사용자 경험을 제공할 수 있는 두 가지 주요 방법은 다음과 같습니다.
- 응답 분기 - 사용자에게 서로 다른 응답을 제공하되 대화의 구조와 흐름을 동일하게 유지하는 데 도움이 될 수 있습니다 대상 예를 들어, 날씨 작업은 휴대전화에 이미지가 있는 카드를 표시하고 Google Home에서 오디오 파일을 재생하지만 대화 흐름은 동일합니다. 표시된다는 것입니다
대화 분기 - 사용자에게 완전히 다른 경험을 제시 대화를 나눌 수 있습니다. 예를 들어 음식 주문 앱을 빌드한다면 Google Home에서 재주문 절차를 제공하고 싶을 수 있지만 휴대전화에서 장바구니 조립 흐름을 확인해 보겠습니다. 대화 브랜치를 수행하려면 범위를 지정합니다. Dialogflow의 인텐트 트리거를 사용하여 특정 표면 기능에 대해 Dialogflow로 전달 있습니다. 실제 Dialogflow 인텐트는 특정 인텐트에 대한 표면 기능이 만족스러울 수 있습니다.
다각형 대화: 하나의 대화에서 사용자에게 대화 전달 다른 표면으로 전환됩니다. 예를 들어 사용자가 Google과 같은 오디오 전용 표시 경로에 이미지가 있는 작업을 호출할 때 홈에서는 작업을 빌드하여 시각 요소가 포함된 다른 영역을 찾을 수 있습니다 가능하다면 대화를 그곳으로 옮길 수 있습니다.
응답 분기
처리에서 Google 어시스턴트의 요청을 수신할 때마다 사용자는 다음 표면 (예: Google Home 또는 Android 휴대전화)을 쿼리할 수 있습니다. 기능:
Node.js
const hasScreen = conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT'); // OR conv.screen; const hasAudio = conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT'); const hasMediaPlayback = conv.surface.capabilities.has('actions.capability.MEDIA_RESPONSE_AUDIO'); const hasWebBrowser = conv.surface.capabilities.has('actions.capability.WEB_BROWSER'); // Interactive Canvas must be enabled in your project to see this const hasInteractiveCanvas = conv.surface.capabilities.has('actions.capability.INTERACTIVE_CANVAS');
자바
boolean hasScreen = request.hasCapability(Capability.SCREEN_OUTPUT.getValue()); boolean hasAudio = request.hasCapability(Capability.AUDIO_OUTPUT.getValue()); boolean hasMediaPlayback = request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue()); boolean hasWebBrowser = request.hasCapability(Capability.WEB_BROWSER.getValue()); // Interactive Canvas must be enabled in your project to see this boolean hasInteractiveCanvas = request.hasCapability("INTERACTIVE_CANVAS");
Node.js
const hasScreen = conv.surface.capabilities.has('actions.capability.SCREEN_OUTPUT'); // OR conv.screen; const hasAudio = conv.surface.capabilities.has('actions.capability.AUDIO_OUTPUT'); const hasMediaPlayback = conv.surface.capabilities.has('actions.capability.MEDIA_RESPONSE_AUDIO'); const hasWebBrowser = conv.surface.capabilities.has('actions.capability.WEB_BROWSER'); // Interactive Canvas must be enabled in your project to see this const hasInteractiveCanvas = conv.surface.capabilities.has('actions.capability.INTERACTIVE_CANVAS');
자바
boolean hasScreen = request.hasCapability(Capability.SCREEN_OUTPUT.getValue()); boolean hasAudio = request.hasCapability(Capability.AUDIO_OUTPUT.getValue()); boolean hasMediaPlayback = request.hasCapability(Capability.MEDIA_RESPONSE_AUDIO.getValue()); boolean hasWebBrowser = request.hasCapability(Capability.WEB_BROWSER.getValue()); // Interactive Canvas must be enabled in your project to see this boolean hasInteractiveCanvas = request.hasCapability("INTERACTIVE_CANVAS");
JSON
아래 JSON은 웹훅 요청을 설명합니다.
{ "responseId": "206a66fb-a572-4cfc-9e41-8e2eb62fdf18-712767ed", "queryResult": { "queryText": "Current capabilities", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Current Capabilities", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Current Capabilities" ] } } ], "outputContexts": [ { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_audio_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_account_linking" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_web_browser" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_screen_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/google_assistant_input_type_touch" } ], "intent": { "name": "projects/df-surface-caps-kohler/agent/intents/4e191eef-ba17-4f68-8a97-85a43cbc9ed1", "displayName": "Current Capabilities" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ" }
JSON
아래 JSON은 웹훅 요청을 설명합니다.
{ "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHENuB8dw7LgVquXnW5Bmy9hwu1Qz4bsaL7uIb9vDSBYPAFhFgsMWnMV6m4JEDgaUWz9FUVuIhQqWh1KZ_jjTwKEIlza", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }
대화 브랜치
특정 기능에서만 트리거되도록 Dialogflow 인텐트를 설정할 수 있습니다. 사전 정의된 Dialogflow 컨텍스트입니다. 인텐트가 일치될 때마다 Dialogflow는 기기의 표면 기능 세트에서 컨텍스트를 자동으로 생성 사용할 수 있습니다. 이러한 컨텍스트 중 하나 이상을 '입력 컨텍스트'로 지정할 수 있습니다. 정의합니다. 이를 통해 모달리티를 기반으로 인텐트 트리거를 제어할 수 있습니다.
예를 들어 화면 출력이 있는 기기에서만 인텐트를 트리거하도록 하려면
인텐트의 입력 컨텍스트를 actions_capability_screen_output
로 설정할 수 있습니다.
사용할 수 있는 컨텍스트는 다음과 같습니다.
actions_capability_audio_output
- 기기에 스피커가 있습니다.actions_capability_screen_output
- 기기에 출력 디스플레이 화면이 있습니다.actions_capability_media_response_audio
- 기기가 미디어 콘텐츠 재생을 지원합니다.actions_capability_web_browser
- 기기가 웹브라우저를 지원합니다. 이 현재 스마트 디스플레이에서는 사용할 수 없습니다.)
다음은 화면이 있는 노출 영역에서만 트리거되는 인텐트의 예입니다.
다목적 대화
작업 흐름 도중 언제든지 사용자에게 다른 노출 영역을 기반으로 합니다 요청된 사용할 수 있게 되면 현재 애플리케이션을 새로운 표면으로 전달할 수 있습니다.
노출 영역 전송의 흐름은 다음과 같습니다.
- 사용자에게 사용 가능한 표시 경로가 있는지 확인
웹훅 핸들러에서 사용자에게 노출 영역이 있는지 쿼리할 수 있습니다. 사용할 수 있습니다 이 노출 영역은 소스 표시 경로와 동일한 Google 계정을 사용합니다
Node.js
const screenAvailable = conv.available.surfaces.capabilities.has( 'actions.capability.SCREEN_OUTPUT');
자바
String screen = Capability.SCREEN_OUTPUT.getValue(); boolean screenAvailable = false; for (Surface surface : request.getAvailableSurfaces()) { for (com.google.api.services.actions_fulfillment.v2.model.Capability capability : surface.getCapabilities()) { if (capability.getName().equals(screen)) { screenAvailable = true; break; } } }
Node.js
const screenAvailable = conv.available.surfaces.capabilities.has( 'actions.capability.SCREEN_OUTPUT');
자바
String screen = Capability.SCREEN_OUTPUT.getValue(); boolean screenAvailable = false; for (Surface surface : request.getAvailableSurfaces()) { for (com.google.api.services.actions_fulfillment.v2.model.Capability capability : surface.getCapabilities()) { if (capability.getName().equals(screen)) { screenAvailable = true; break; } } }
JSON
아래 JSON은 웹훅 요청을 설명합니다.
{ "responseId": "206a66fb-a572-4cfc-9e41-8e2eb62fdf18-712767ed", "queryResult": { "queryText": "Current capabilities", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Current Capabilities", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Current Capabilities" ] } } ], "outputContexts": [ { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_audio_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_account_linking" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_web_browser" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/actions_capability_screen_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ/contexts/google_assistant_input_type_touch" } ], "intent": { "name": "projects/df-surface-caps-kohler/agent/intents/4e191eef-ba17-4f68-8a97-85a43cbc9ed1", "displayName": "Current Capabilities" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] } ] } }, "session": "projects/df-surface-caps-kohler/agent/sessions/ABwppHG7pYytu-kJGJApvrFTk2iNkshy-NLsjlzJg2ntVbxZkoz-rdFch3Fd8Vmlgf0VxmNSK1woelx1otayGwCnE8gzAQ" }
JSON
아래 JSON은 웹훅 요청을 설명합니다.
{ "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHENuB8dw7LgVquXnW5Bmy9hwu1Qz4bsaL7uIb9vDSBYPAFhFgsMWnMV6m4JEDgaUWz9FUVuIhQqWh1KZ_jjTwKEIlza", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.TEXT", "rawInputs": [ { "inputType": "TOUCH", "query": "Current capabilities" } ], "arguments": [ { "name": "text", "rawText": "Current capabilities", "textValue": "Current capabilities" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }
- 사용자를 새 표시 경로로 이전하도록 요청
필요한 기능이 있는 사용 가능한 노출 영역이 있다면 작업은 사용자에게 대화를 트랜스퍼하고 싶은지 물어봐야 합니다.
Node.js
if (conv.screen) { conv.ask(`You're already on a screen device.`); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Current Capabilities', 'Check Audio Capability', 'Check Screen Capability', 'Check Media Capability', 'Check Web Capability', ])); return; } else if (screenAvailable) { const context = `Let's move you to a screen device for cards and other visual responses`; const notification = 'Try your Action here!'; const capabilities = ['actions.capability.SCREEN_OUTPUT']; return conv.ask(new NewSurface({context, notification, capabilities})); } else { conv.ask('It looks like there is no screen device ' + 'associated with this user.'); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Current Capabilities', 'Check Audio Capability', 'Check Screen Capability', 'Check Media Capability', 'Check Web Capability', ])); };
자바
ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { responseBuilder.add("You're already on a screen device"); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Transfer surface", "Check Audio Capability", "Check Screen Capability", "Check Media Capability", "Check Web Capability", }); return responseBuilder.build(); } else if (screenAvailable) { responseBuilder.add( new NewSurface() .setContext("Let's move you to a screen device for cards and other visual responses") .setNotificationTitle("Try your Action here!") .setCapabilities(Collections.singletonList(screen))); return responseBuilder.build(); } else { responseBuilder.add("It looks like there is no screen device associated with this user."); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Transfer surface", "Check Audio Capability", "Check Screen Capability", "Check Media Capability", "Check Web Capability", }); return responseBuilder.build(); }
Node.js
if (conv.screen) { conv.ask(`You're already on a screen device.`); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Transfer surface', 'Current capabilities', ])); return; } else if (screenAvailable) { const context = `Let's move you to a screen device for cards and other visual responses`; const notification = 'Try your Action here!'; const capabilities = ['actions.capability.SCREEN_OUTPUT']; return conv.ask(new NewSurface({context, notification, capabilities})); } else { conv.ask('It looks like there is no screen device ' + 'associated with this user.'); conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Transfer surface', 'Current capabilities', ])); };
자바
ResponseBuilder responseBuilder = getResponseBuilder(request); if (request.hasCapability(Capability.SCREEN_OUTPUT.getValue())) { responseBuilder.add("You're already on a screen device"); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Current capabilities", "Transfer surface", }); return responseBuilder.build(); } else if (screenAvailable) { responseBuilder.add( new NewSurface() .setContext("Let's move you to a screen device for cards and other visual responses") .setNotificationTitle("Try your Action here!") .setCapabilities(Collections.singletonList(screen))); return responseBuilder.build(); } else { responseBuilder.add("It looks like there is no screen device associated with this user."); responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Current capabilities", "Transfer surface", }); return responseBuilder.build(); }
JSON
아래 JSON은 웹훅 응답을 설명합니다.
{ "payload": { "google": { "expectUserResponse": true, "systemIntent": { "intent": "actions.intent.NEW_SURFACE", "data": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValueSpec", "capabilities": [ "actions.capability.SCREEN_OUTPUT" ], "context": "Let's move you to a screen device for cards and other visual responses", "notificationTitle": "Try your Action here!" } } } } }
JSON
아래 JSON은 웹훅 응답을 설명합니다.
{ "expectUserResponse": true, "expectedInputs": [ { "possibleIntents": [ { "intent": "actions.intent.NEW_SURFACE", "inputValueData": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValueSpec", "capabilities": [ "actions.capability.SCREEN_OUTPUT" ], "context": "Let's move you to a screen device for cards and other visual responses", "notificationTitle": "Try your Action here!" } } ] } ] }
- 사용자 응답 처리
요청에 대한 사용자의 응답에 따라 작업이 원래 노출 영역으로 대화의 핸드오프 또는 반환 제어 권한을 전달합니다. 어떤 방법을 사용하든 엔드포인트에 대한 다음 요청에는
actions.intent.NEW_SURFACE
가 포함됩니다. 따라서 해당 이벤트에서 트리거되는 인텐트를 해당 핸들러를 정의합니다. 핸들러 코드에서 전송이 완료되었는지 확인합니다.Node.js
app.intent('Transfer Surface - NEW_SURFACE', (conv, input, newSurface) => { if (newSurface.status === 'OK') { conv.ask('Welcome to a screen device!'); conv.ask(new BasicCard({ title: `You're on a screen device!`, text: `Screen devices support basic cards and other visual responses!`, })); } else { conv.ask(`Ok, no problem.`); } conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Current Capabilities', 'Check Audio Capability', 'Check Screen Capability', 'Check Media Capability', 'Check Web Capability', ])); });
자바
@ForIntent("Transfer Surface - NEW_SURFACE") public ActionResponse newSurface(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); Map<String, Object> newSurfaceStatus = request.getArgument("NEW_SURFACE").getExtension(); if (newSurfaceStatus.get("status").equals("OK")) { responseBuilder.add("Welcome to a screen device!"); responseBuilder.add( new BasicCard() .setTitle("You're on a screened device!") .setFormattedText("Screen devices support basic cards and other visual responses!")); } else { responseBuilder.add("Ok, no problem."); } responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Transfer surface", "Check Audio Capability", "Check Screen Capability", "Check Media Capability", "Check Web Capability", }); return responseBuilder.build(); }
Node.js
app.intent('actions.intent.NEW_SURFACE', (conv) => { if (conv.arguments.get('NEW_SURFACE').status === 'OK') { conv.ask('Welcome to a screen device!'); conv.ask(new BasicCard({ title: `You're on a screen device!`, text: `Screen devices support basic cards and other visual responses!`, })); } else { conv.ask(`Ok, no problem.`); } conv.ask('What else would you like to try?'); conv.ask(new Suggestions([ 'Transfer surface', 'Current capabilities', ])); });
자바
@ForIntent("actions.intent.NEW_SURFACE") public ActionResponse newSurface(ActionRequest request) { ResponseBuilder responseBuilder = getResponseBuilder(request); Map<String, Object> newSurfaceStatus = request.getArgument("NEW_SURFACE").getExtension(); if (newSurfaceStatus.get("status").equals("OK")) { responseBuilder.add("Welcome to a screen device!"); responseBuilder.add( new BasicCard() .setTitle("You're on a screened device!") .setFormattedText("Screen devices support basic cards and other visual responses!")); } else { responseBuilder.add("Ok, no problem."); } responseBuilder.add("What else would you like to try?"); responseBuilder.addSuggestions( new String[] { "Current capabilities", "Transfer surface", }); return responseBuilder.build(); }
JSON
아래 JSON은 웹훅 요청을 설명합니다.
{ "responseId": "94b74485-cd7a-4b3b-b96a-fec15f3a496c-712767ed", "queryResult": { "queryText": "actions_intent_NEW_SURFACE", "parameters": {}, "allRequiredParamsPresent": true, "fulfillmentText": "Webhook failed for intent: Transfer Surface - NEW_SURFACE", "fulfillmentMessages": [ { "text": { "text": [ "Webhook failed for intent: Transfer Surface - NEW_SURFACE" ] } } ], "outputContexts": [ { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_screen_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_web_browser" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_audio_output" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_media_response_audio" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_capability_account_linking" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/google_assistant_input_type_voice" }, { "name": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q/contexts/actions_intent_new_surface", "parameters": { "NEW_SURFACE": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValue", "status": "OK" }, "text": "" } } ], "intent": { "name": "projects/df-surface-caps-kohler/agent/intents/9db3798d-bdac-4dc8-a8e7-52349a3af0e8", "displayName": "Transfer Surface - NEW_SURFACE" }, "intentDetectionConfidence": 1, "languageCode": "en" }, "originalDetectIntentRequest": { "source": "google", "version": "2", "payload": { "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q", "type": "ACTIVE", "conversationToken": "[]" }, "inputs": [ { "intent": "actions.intent.NEW_SURFACE", "rawInputs": [ { "inputType": "VOICE" } ], "arguments": [ { "name": "NEW_SURFACE", "extension": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.ACCOUNT_LINKING" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" } ] } ] } }, "session": "projects/df-surface-caps-kohler/agent/sessions/ABwppHEfQy-JgH7nmiW5gHWiDEyvqNRSPv9zkd3qTVF7F8G8YXJFI2_yal335Co0Z-_N5oUBTmVO_DJUlQONqd5lUgZz-Q" }
JSON
아래 JSON은 웹훅 요청을 설명합니다.
{ "user": { "locale": "en-US", "userVerificationStatus": "VERIFIED" }, "conversation": { "conversationId": "ABwppHENAOzBH5swn9iKb5QgUliTw4JLu5f86gS373tGtNvYcz1C3qHdorjcIb77o_PUleXGzIEFdPsl3-kmIAARvx67A7Ym", "type": "NEW" }, "inputs": [ { "intent": "actions.intent.NEW_SURFACE", "rawInputs": [ { "inputType": "VOICE" } ], "arguments": [ { "name": "NEW_SURFACE", "extension": { "@type": "type.googleapis.com/google.actions.v2.NewSurfaceValue", "status": "OK" } }, { "name": "text" } ] } ], "surface": { "capabilities": [ { "name": "actions.capability.SCREEN_OUTPUT" }, { "name": "actions.capability.ACCOUNT_LINKING" }, { "name": "actions.capability.MEDIA_RESPONSE_AUDIO" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.WEB_BROWSER" } ] }, "availableSurfaces": [ { "capabilities": [ { "name": "actions.capability.WEB_BROWSER" }, { "name": "actions.capability.AUDIO_OUTPUT" }, { "name": "actions.capability.SCREEN_OUTPUT" } ] } ] }