Custom code and webhooks

At many points in your conversation, you most likely want to retrieve business information or connect to an external system to perform actions. You can do this through webhooks. A webhook is a simple HTTP call to your backend. To configure your HTTP call, click CALL WEBHOOK in the Bot Builder.

SAP Conversational AI - Webhook

You can provide the full URL or route (starting with a ‘/’) to be called by the Bot Builder. If you provide a route, the Bot webhook base URL (configurable in your bot’s settings) will be prepended to it.

You can specify the HTTP method to use in your webhook call (GET, POST, PUT, or PATCH).

SAP Conversational AI - Webhook

Authentication configuration

You have the following options:

• No authentication: No authentication/authorization is passed with the request.

• Basic authentication: A username/password pair is passed with the request.

• OAuth 2 authentication: A client ID, client secret, and authorization URL is passed with the request.

SAP Conversational AI - Webhook

Header configuration

HTTP headers are accommodated by configuring a key-value pair, where you can name keys and set a value to be passed along in the header.

SAP Conversational AI - Webhook

Body configuration

The HTTP request body must be formatted as a standard JSON object. You can either receive the default body that we provide with all conversation states or create your own custom body.

The default body format is as follows:

{
  "conversation": {
    "id": "A_CONVERSATION_ID",
    "language": "en",
    "memory": {
      "person": {
        "fullname": "Francois",
        "raw": "Francois",
        "confidence": 0.95
      }
    },
    "skill_stack": ["get-weather"],
    "skill": "small-talk",
    "skill_occurences": 1
  },
  "nlp": {
    "source": "hi",
    "intents": [
      {
        "slug": "greetings",
        "confidence": 0.99
      }
    ],
    "sentiment": "vpositive",
    "entities": {},
    "act": "assert",
    "type": null,
    "version": "2.10.1",
    "processing_language": "en",
    "language": "en",
    "uuid": "96597974-3ee1-4743-8a5d-341b67effb9a"
    "status": 200,
    "timestamp": "2017-10-25T21:36:02.071243+00:00",
  }
}



In custom HTTP request bodies, you can reference conversation variables (like memory variables, NLP information, etc.) in place of hard-coded values, for example, {{memory.person.raw}}. Check all the variables you can use.

SAP Conversational AI - Webhook

Templates

You can reuse specific configurations of authorizations, headers, and bodies in other skills by choosing Templates in the skill view.

SAP Conversational AI - Webhook

You can manage these templates on the Templates tab.

SAP Conversational AI - Webhook

Formatting the response of the webhook call

The body format of your response should be a valid JSON and can contain two keys: replies and conversation.

Key Required Value
replies Optional Array of object
conversation Optional Object with a key memory and language
conversation.memory Optional Object filled as you want
conversation.language Optional String with a language ISO format


Here is an example:

{
  "replies": [
    {
      "type": "text",
      "content": "Hello world!"
    }
  ],
  "conversation": {
    "language": "en",
    "memory": {
      "user": "Bob"
    }
  }
}


The conversation data you send back will update the state of your conversation:

  • memory will replace the actual memory of your bot (so be careful that you don’t lose everything if you just want to change one of your memory keys to add all your other keys).
  • language will update the language of the conversation. Each new sentence sent by the user will be processed in this language, and the bot will reply in this language.

The replies are sent in the body of the result of the main Bot Builder and will appear in the messages key:

POST https://api.cai.tools.sap/build/v1/dialog

{
    "messages": [
        {
             "type": "text",
             "content": "Hello world!"
        }
    ],
    "conversation": {
        "id": "CONVERSATION_ID",
        "language": "en",
        "memory": {},
        "skill": "default",
        "skill_occurences": 1
    },
    "nlp": {
        "uuid": "b96bc782-6aba-4fac-aeaa-2326936b08bf",
        "source": "Hello SAP Conversational AI",
        "intents": [
            {
                "slug": "greetings",
                "confidence": 0.99
            }
        ],
        "act": "assert",
        "type": null,
        "sentiment": "neutral",
        "entities": {},
        "language": "en",
        "processing_language": "en",
        "version": "2.10.1",
        "timestamp": "2017-10-19T13:24:12.984856+00:00",
        "status": 200
    }
}

Formatting the array of replies

You can format objects in the array of reply as desired, depending on your needs when you request the Bot Builder API. If you are using the Bot Connector (that is, you have connected a channel on the SAP Conversational AI platform like Facebook Messenger, Slack, or a webchat), you need to follow the Bot Connector format: Check the format to send rich messages

{
  "replies": [
    {
      "type": "text",
      "content": "Hello world!"
    }
  ]
}

Checking your code

Copy and paste this snippet in a file, install the dependencies, and run the file.

JS: npm install express body-parser –save

Python: pip install flask

Ruby: gem install sinatra

PHP: composer require slim/slim


const express = require('express')
const bodyParser = require('body-parser')

const app = express()
const port = 5000
app.use(bodyParser.json())

app.post('/', (req, res) => {
  console.log(req.body)

  res.send({
    replies: [{
      type: 'text',
      content: 'Roger that',
    }],
    conversation: {
      memory: { key: 'value' }
    }
  })
})

app.post('/errors', (req, res) => {
  console.log(req.body)
  res.send()
})

app.listen(port, () => {
  console.log('Server is running on port 5000')
})
require 'sinatra'
require 'json'

set :port, 5000

before do
  @params = JSON.parse(request.body.read)
end

post '/' do
  content_type :json
  {
    replies: [{ type: 'text', content: 'Roger that' }],
    conversation: {
      memory: {
        key: 'value'
      }
    }
  }.to_json
end

post '/errors' do
  puts @params

  200
end
from flask import Flask, request, jsonify
import json

app = Flask(__name__)
port = '5000'

@app.route('/', methods=['POST'])
def index():
  print(json.loads(request.get_data()))
  return jsonify(
    status=200,
    replies=[{
      'type': 'text',
      'content': 'Roger that',
    }],
    conversation={
      'memory': { 'key': 'value' }
    }
  )

@app.route('/errors', methods=['POST'])
def errors():
  print(json.loads(request.get_data()))
  return jsonify(status=200)

app.run(port=port)
<?php
require 'vendor/autoload.php';
use \Slim\App;

$app = new App();

$app->post('/', function ($request, $response) {
  error_log($request->getBody()->getContents());
  return $response->withJson(array(
    'replies' => [
      array('type' => 'text', 'content' => 'Roger that')
    ],
    'conversation' => array(
      'memory' => array('key' => 'value')
    )
  ));
});

$app->post('/errors', function ($request, $response) {
  error_log($request->getBody()->getContents());
  return $response;
});

$app->run();