Skip to main content

Extensions

AI assistant extensions, are tools or pieces of software that are designed to augment the functionality of an AI assistant. These extensions provide extra features and capabilities to enhance the overall user experience.

Available Extensions:

Swarm Betting

The Swarm Betting Assistant is a powerful AI assistant extension designed to elevate your sports betting experience. This intelligent extension seamlessly integrates with your sports betting platform to provide your users with a personalized betting experience. It is designed to enhance the betting experience with a unique blend of personalized guidance, up-to-date information, and friendly interaction.

Here's how to integrate the Swarm Betting Assistant into your sports betting platform:

<script async>
// Load the Hoory SDK
window.hoorySettings = {
type: "expanded_bubble",
launcherTitle: "Need Betting Tips? Tap Here!",
};
(function (d, t) {
var BASE_URL = "https://<Hoory SDK URL>";
var g = d.createElement(t),
s = d.getElementsByTagName(t)[0];
g.src = BASE_URL + "/packs/js/sdk.js";
g.defer = true;
g.async = true;
s.parentNode.insertBefore(g, s);
g.onload = function () {
window.hoorySDK.run({
websiteToken: "<Website Token>",
baseUrl: BASE_URL,
});
};
})(document, "script");

// Submit site and user information to the AI Assistant
window.addEventListener("hoory:ready", function () {
// Partner site information (required)
const site = {
id: -1, // Required Partner Site ID
url: window.origin, // Optional Website Site URL example: https://betboard.springbuilder.live
swarm_url: "wss://<Swarm API URL>", // Optional Swarm API URL (default: wss://eu-swarm-springre.betconstruct.com)
};

// User information (optional)
const user = {
id: -1, // Required User ID
email: "<Use Email>", // Required User Email
name: "<User Name>", // Require User Name
auth_token: "XXX", // Optional User Swarm Auth Token
jwe_token: "XXX", // Optional User Swarm JWE Token
};

if (user) {
// If user is logged in set user and site information

console.info("Setting user information");

window.$hoory.setUser(user.id, {
identifier: user.id,
email: user.email,
name: user.name,
custom_attributes: {
__assistant: {
context: {
site_id: site.id,
site_url: site.url,
swarm_url: site.swarm_url,
auth_token: user.auth_token,
jwe_token: user.jwe_token,
},
},
},
});
} else {
// If user is not logged in only set site information

console.info("Setting site information");

window.$hoory.setCustomAttributes({
__assistant: {
context: {
site_id: site.id,
site_url: site.url,
swarm_url: site.swarm_url,
},
},
});
}
});

// Handle messages from the AI Assistant
window.addEventListener("hoory:on-message", function (message) {
// Check if the message requires an action
if (message.detail.content_type === "require_action") {
try {
// Parse the content of the message
const content = JSON.parse(message.detail.content);
// Switch based on the action specified in the message
switch (content.action) {
case "betslip":
// Log information about adding an event to the betslip
// Data schema: { event_id: number, game_id: number }
console.info("Adding event to betslip: ", content.data);
break;
default:
// Handle unknown actions
console.warn("Received an unknown action: ", content.action);
break;
}
} catch (error) {
console.error("Error processing message: ", error);
}
}
});
</script>

Ensure proper handling of links to games and markets directed to your website using the following format:

https://<your-website>/redirect-to-game/<game-id>?event=<event-id>

Odds format

You can change the odds format that Betting Assistant uses during the conversation with the user. Odds format can be provided as odds_format attribute in custom attributes. Available odds formats:

  1. decimal (used by default)
  2. fractional

Here is an example of how to set the fractional odds format, instead of decimal:

...
__assistant: {
context: {
site_id: site.id,
site_url: site.url,
swarm_url: site.swarm_url,
...,
odds_format: "fractional", // Set the odds format (if not provided, "decimal" will be used as default one)
},
},
...

Note: fractional odds are calculated from decimal odds using the ladder provided by Swarm command get_permissible_odds.

Deactivating AI Assistant Capabilities

You can optionally deactivate certain built-in capabilities of AI Assistant Extensions by modifying the tools property in custom attributes.

Here is an example of how to deactivate the connect_to_support capability and prevent AI Assistant from connecting users to an agent:

...
__assistant: {
context: {
site_id: site.id,
site_url: site.url,
swarm_url: site.swarm_url,
auth_token: user.auth_token,
jwe_token: user.jwe_token,
tools: {
connect_to_support: false // Deactivate the capability
}
},
},
...

Capabilities that can be deactivated

  1. Connect to Support Tool (connect_to_support): Connects the user to an agent.
  2. Fasttoken Price Tool (get_fasttoken_price): Checks the current price of FastToken (FTN) cryptocurrency.

Custom Extensions

Custom extensions are a set of tools defined by you that the AI assistant can use to provide a more personalized experience for your users. These extensions can be used to provide additional features and capabilities to the AI assistant, such as custom integrations, data sources, and more.

Create or Update Custom Extension

To create or update a custom extension, you need to use the following API. This endpoint creates a new custom extension or updates an existing one based on the provided ID.

URL: https://app.hoory.com/svc/bot/v1/agentbots/accounts/{account_id}/assistants/{assistant_id}

Method: PUT

Headers:
Authorization: Bearer <access token>

Parameters:

  • account_id (integer, required): Your account ID
  • assistant_id (integer, required): Your assistant ID. You can pick a unique number

Body:

{
"name": "string", // The name of the custom extension (required)
"description": "string", // A brief description of the custom extension (optional)
"instructions": "string", // Detailed instructions for the custom extension (required)
"secret": "string", // A secret key to authenticate the webhook requests (optional)
"tools": [
// A list of tools that the custom extension provides (optional)
{
"type": "string", // The type of the tool (required-enum)
"spec": {} // The specification of the tool. See Supported Tools below for more information (required)
}
]
}

Docs:
API Documentation

Example

Here's how you can create or update a custom extension using the above endpoint:

curl -X PUT "https://app.hoory.com/svc/bot/v1/agentbots/accounts/100/assistants/100" \
-H "Authorization: Bearer secret" \
-H "Content-Type: application/json" \
-d '{
"name": "My Custom Extension",
"description": "This is a custom extension.",
"instructions": "Follow these steps to use the custom extension.",
"tools": [
{
"type": "webhook",
"spec": {
"name": "My Webhook Tool",
"description": "This tool calls a webhook.",
"url": "https://example.com/webhook",
"args_schema": {
"type": "object",
"properties": {
"arg1": {
"type": "string"
},
"arg2": {
"type": "number"
}
},
"required": ["arg1", "arg2"]
}
}
}
]
}'

An access token can be obtained from your profile settings page (https://app.hoory.com/app/accounts/{your_account_id}/profile/settings) in your Hoory account. You must have the admin role to be able to create or update custom extensions for your account: profile settings access token

Once the custom tool is created, you can select it for the knowledge base assistant on the assistant train page (https://app.hoory.com/app/accounts/{your_account_id}/agent-bots/webhook/{your_agentbot_id}/train): assistant train custom tool

Supported Tools

Webhook

The webhook tool allows you to define a webhook endpoint that the AI assistant can call when the tool is triggered. The webhook tool must be defined with the following fields:

{
"type": "webhook", // The type of the tool (required-enum)
"spec": {
"name": string, // The name of the tool (required)
"description": string, // Detailed description of the tool (required)
"using_tool_message": string, // Message to show when triggering the tool (optional)
"url": string, // The URL of the webhook (required)
"secret" : string, // A secret key to authenticate the webhook requests (optional)
"args_schema": {}, // The payload schema of the webhook request (required) (JSON Schema) https://json-schema.org/specification
}
}

When you define a webhook tool in your custom extension, you need to provide a URL that the AI assistant will call when the tool is triggered. The webhook handler should be able to handle the incoming request and provide a response based on the provided payload.

The webhook handler is a POST endpoint that receives a JSON payload and returns a JSON response. The payload schema is defined in the args_schema field of the tool definition, and the request contains some additional fields to help you identify the context of the request.

The following is the request schema that the webhook handler should expect:

{
"args": {}, // The arguments for the webhook tool
"ctx": {
// The context of the request
"conversation": {
"channel": "Channel::WebWidget",
"meta": {
"sender": {
"account": null,
"additional_attributes": {
"city": null,
"country": "",
"country_code": null,
"created_at_ip": "::1"
},
"custom_attributes": {},
"identifier": "2",
"name": "",
"type": "contact",
"email": ""
}
},
"id": 24,
"status": "pending"
},
"contact_lang": "en"
}
}

After processing the request, the webhook handler should return a JSON response instructing the AI assistant on how to proceed. The response schema should look like this:

{
"success": boolean, // A boolean value indicating the status of the response (required)
"message": string, // A message indicating the status of the processing. The AI assistant will use this message to inform the user. (optional)
"actions": [ // A list of actions that the AI assistant should take based on the response (optional)
{
"type": string, // The type of the action (required-enum)
"spec": {} // The specification of the action. See **Supported Actions** below for more information (required)
}
]
}

To authenticate the webhook requests, you can use the secret field in the webhook tool. The AI assistant will include the Authorization header in the request which contains the Bearer token with the value of the secret field.

Authorization: Bearer <secret>

Supported Actions

Emit to Browser Window

This action allows you to emit a message to the browser window that hosts the Hoory widget, which you can listen to and handle in your application. This action is useful when you want to trigger some action in your application based on the response from the webhook handler.

{
"type": "emit_to_window", // The type of the action (required-enum)
"spec": {
"action": string, // The action to emit (required)
"data": {} // The data to emit with the event (required)
}
}

Listening to the emitted event in your application:

window.addEventListener("hoory:on-message", function (message) {
// Check if the message requires an action
if (message.detail.content_type === "require_action") {
try {
// Parse the content of the message
const content = JSON.parse(message.detail.content);
// Switch based on the action specified in the message
switch (content.action) {
case "my_custom_action":
// Log information about the custom action
console.info("Received custom action: ", content.data);
break;
default:
// Handle unknown actions
console.warn("Received an unknown action: ", content.action);
break;
}
} catch (error) {
console.error("Error processing message: ", error);
}
}
});

Additional instructions

Sometimes, you may want to change the behavior of the AI assistant dynamically during the conversation. For that purpose, you can use the additional_instructions attribute. When provided, it appends additional instructions at the end of the existing instructions before generating a response.

...
__assistant: {
context: {
...,
additional_instructions: "Use emojis in your repsonses to make the conversation more engaging.", // Set additional instructions
},
},
...

Example Use Case

Let's say you want to create a custom extension that allows the AI assistant to call a webhook to get the current weather information for a specific location. You can define a webhook tool in your custom extension that calls a weather API and returns the weather information.

We're start by creating the custom extension with the webhook tool:

curl -X PUT "https://app.hoory.com/svc/bot/v1/agentbots/accounts/100/assistants/100" \
-H "Authorization: Bearer <API_TOKEN_OBTAINED_FROM_YOUR_PROFILE>" \
-H "Content-Type: application/json" \
-d @- <<EOF
{
"name": "Weather Extension",
"description": "Get the current weather information for a specific location.",
"instructions": "To get the weather information, provide the location and the date.",
"tools": [
{
"type": "webhook",
"spec": {
"name": "weather_webhook",
"description": "Get the current weather information for a specific location.",
"using_tool_message": "Getting the weather information for you...",
"url": "https://example.com/weather",
"secret": "<WEBHOOK_SECRET>",
"args_schema": {
"type": "object",
"properties": {
"location": {
"type": "string"
}
},
"required": ["location"]
}
}
}
]
}
EOF

Next, you need to create a webhook handler that will handle the incoming requests and return the weather information. The webhook handler should be able to handle the incoming request and provide a response based on the provided payload.

Here's an example of a webhook handler in Node.js that calls a weather API and returns the weather information:

const express = require("express");
const bodyParser = require("body-parser");
const axios = require("axios");

const app = express();
app.use(bodyParser.json());

const secret = process.env.WEBHOOK_SECRET;

app.post("/weather", async (req, res) => {
const { location } = req.body.args;

// Check the webhook secret
if (req.headers.authorization !== `Bearer ${secret}`) {
return res.status(401).json({
success: false,
message: "Unauthorized",
});
}

try {
const response = await axios.get(
`https://api.openweathermap.org/data/2.5/weather?q=${location}&appid=<API_KEY>`
);

const weather = response.data.weather[0].description;
res.json({
success: true, // Indicates the status of the response
message: `The weather in ${location} is ${weather}.`, // Optional message to show to the user
actions: [
// actions to take based on the response
{
type: "emit_to_window",
spec: {
action: "weather_info",
data: {
location,
weather,
},
},
},
],
});
} catch (error) {
res.json({
success: false,
message: "Failed to get weather information.",
});
}
});

In this example, the webhook handler receives the location from the request payload, calls the OpenWeatherMap API to get the weather information for that location, and returns the weather information in the response.

Finally, you need to listen to the emitted event in your application and display the weather information to the user:

<html>
<head>
<title>Weather Information</title>
</head>
<body>
<h1>Weather Information</h1>
<div id="weather-info"></div>
</body>

<script>
window.addEventListener("hoory:on-message", function (message) {
if (message.detail.content_type === "require_action") {
try {
const content = JSON.parse(message.detail.content);
switch (content.action) {
case "weather_info":
console.info("Received weather information: ", content.data);
const weatherInfo = document.getElementById("weather-info");
weatherInfo.innerHTML = `The weather in ${content.data.location} is ${content.data.weather}.`;
break;
default:
console.warn("Received an unknown action: ", content.action);
break;
}
} catch (error) {
console.error("Error processing message: ", error);
}
}
});
</script>
</html>

Now if you trigger the webhook tool in the AI assistant, it will call the webhook handler, get the weather information, and display it to the user:

AI: Hey there! How can I help you today?
User: Can you tell me the weather in New York?
AI: Sure! Let me check that for you...
AI: The weather in New York is cloudy, with a temperature of 20°C, and a chance of rain.