- Enable
context_access_enabled: truein your agent definition. - Add variables like
channelto thecontext_variablesin your agent definition file. - Reimport the agent.
- Include context variables in the JWT payload.
Copy
Ask AI
spec_version: v1
style: react
name: hello_agent
llm: watsonx/meta-llama/llama-3-1-70b-instruct
description: 'Agent description'
instructions: |
You are a helpful agent that must answer user questions in a clean and concise manner. Be polite and do not perform harmful behavior.
collaborators: []
tools: []
context_access_enabled: true
context_variables:
- channel # Use it to get access to context variables on the embedded chat
createJWT
Copy
Ask AI
const fs = require('fs');
const RSA = require('node-rsa');
const crypto = require('crypto');
const jwtLib = require('jsonwebtoken');
const express = require('express');
const path = require('path');
const { v4: uuid } = require('uuid');
const router = express.Router();
// This is your private key that you will keep on your server. This is used to sign the jwt. You will paste your public
// key into the appropriate field on the Security tab of the web chat settings page.
// This public key is used to validate the signature on the jwt.
const PRIVATE_KEY = fs.readFileSync(path.join(__dirname, 'wxo_security_config/client_private_key.pem'));
//The code below will use this key to encrypt the user payload inside the JWT.
const PUBLIC_KEY = fs.readFileSync(path.join(__dirname, 'wxo_security_config/client_public_key.pem'));
// A time period of 45 days in milliseconds.
const TIME_45_DAYS = 1000 * 60 * 60 * 24 * 45;
/**
* Generates a signed JWT. The JWT used here will always be assigned a user ID using the given anonymous user ID. If
* the user is authenticated and we have session info, then info about the user will also be added to the JWT.
* Always use the anonymous user ID even if the user is authenticated because changing the user ID in the middle of
* a session is not allowed.
*/
function createJWTString(anonymousUserID, sessionInfo,context) {
// This is the content of the JWT. You would normally look up the user information from a user profile.
const jwtContent = {
// This is the subject of the JWT which will be the ID of the user.
//
// This user ID will be available under integrations.channel.private.user.id in dialog and
// system_integrations.channel.private.user.id in actions.
sub: anonymousUserID,
// This object is optional and contains any data you wish to include as part of the JWT. This data will be
// encrypted using the public key so it will not be visible to your users.
user_payload: {
custom_message: 'Encrypted message',
name: 'Anonymous',
},
context
};
// If the user is authenticated, then add the user's real info to the JWT.
if (sessionInfo) {
jwtContent.user_payload.name = sessionInfo.userName;
jwtContent.user_payload.custom_user_id = sessionInfo.customUserID;
}
const dataString = JSON.stringify(jwtContent.user_payload);
// Encrypt the data
const encryptedBuffer = crypto.publicEncrypt(
{
key: PUBLIC_KEY,
padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,
oaepHash: 'sha256' // Specify OAEP padding with SHA256
},
Buffer.from(dataString, 'utf-8')
);
// Convert encrypted data to base64
jwtContent.user_payload = encryptedBuffer.toString('base64');
console.log(jwtContent.user_payload)
// Now sign the jwt content to make the actual jwt. We are giving this a very short expiration time (10 seconds)
// to demonstrate the web chat capability of fetching a new token when it expires. In a production environment,
// you would likely want to set this to a much higher value or leave it out entirely.
const jwtString = jwtLib.sign(jwtContent, PRIVATE_KEY, {
algorithm: 'RS256',
expiresIn: '10000000s',
});
return jwtString;
}
/**
* Gets or sets the anonymous user ID cookie. This will also ensure that an existing cookie is updated with a new 45
* day expiration time.
*/
function getOrSetAnonymousID(request, response) {
let anonymousID = request.cookies['ANONYMOUS-USER-ID'];
if (!anonymousID) {
// If we don't already have an anonymous user ID, then create one. Normally you would want to use a full UUID,
// but for the sake of this example we are going to shorten it to just five characters to make them easier to read.
anonymousID = `anon-${uuid().substr(0, 5)}`;
}
// Here we set the value of the cookie and give it an expiration date of 45 days. We do this even if we already
// have an ID to make sure that we update the expiration date to a new 45 days.
response.cookie('ANONYMOUS-USER-ID', anonymousID, {
expires: new Date(Date.now() + TIME_45_DAYS),
httpOnly: true,
});
return anonymousID;
}
/**
* Returns the session info for an authenticated user.
*/
function getSessionInfo(request) {
// Normally the cookie would contain a session token that we would use to look up the user's info from something
// like a database. But for the sake of simplicity in this example the session cookie directly contains the user's
// info.
const sessionInfo = request.cookies.SESSION_INFO;
if (sessionInfo) {
return JSON.parse(sessionInfo);
}
return null;
}
/**
* Handles the createJWT request.
*/
function createJWT(request, response) {
const anonymousUserID = getOrSetAnonymousID(request, response);
const sessionInfo = getSessionInfo(request);
const context = {
dev_id: 23424,
dev_name: "Name",
is_active: true
}
response.send(createJWTString(anonymousUserID, sessionInfo,context));
}
router.get('/', createJWT);
module.exports = router;
JavaScript
Copy
Ask AI
<script>
function getUserId() {
let embed_user_id = getCookie('embed_user_id');
if (!embed_user_id) {
embed_user_id = Math.trunc(Math.random() * 1000000);
setCookie('embed_user_id', embed_user_id);
}
return embed_user_id;
}
function getCookie(name) {
console.log('getCookie');
const value = `; ${document.cookie}`;
const parts = value.split(`; ${name}=`);
if (parts.length === 2) return parts.pop().split(';').shift();
}
function setCookie(name, value) {
document.cookie = `${name}=${value}; path=/`;
}
function preSendHandler(event) {
if (event?.message?.content) {
event.message.content = event.message.content.toUpperCase();
}
}
function sendHandler(event) {
console.log('send event', event);
}
function feedbackHandler(event) {
console.log('feedback', event);
}
function preReceiveHandler(event) {
event?.content?.map((element) => {
element.type = 'date';
});
}
function receiveHandler(event) {
console.log('received event', event);
}
function userDefinedResponseHandler(event) {
console.log('userDefinedResponse event', event);
event.hostElement.innerHTML = `
<cds-code-snippet>
node -v Lorem ipsum dolor sit amet, consectetur adipisicing elit. Blanditiis,
veritatis voluptate id incidunt molestiae officia possimus, quasi itaque
alias, architecto hic, dicta fugit? Debitis delectus quidem explicabo vitae
laboriosam!
</cds-code-snippet>
<br><br>
<div style="background-color:orange;color:white;padding:10px;">
<p>${event.contentItem?.template || '[No message content]'}</p>
</div>`;
}
function onChatLoad(instance) {
instance.on('chatstarted', (instance) => {
window.wxoChatInstance = instance;
});
instance.on('pre:send', preSendHandler);
instance.on('send', sendHandler);
instance.on('pre:receive', preReceiveHandler);
instance.on('receive', receiveHandler);
instance.on('feedback', feedbackHandler);
instance.on('userDefinedResponse', userDefinedResponseHandler);
}
async function getIdentityToken() {
// This will make a call to your server to request a new JWT.
const result = await fetch(
"http://localhost:3000/createJWT?user_id=" + getUserId()
);
window.wxOConfiguration.token = await result.text();
}
window.wxOConfiguration = {
orchestrationID: "20250430-0912-2925-309a-35c6bef54760_20250430-0949-0287-00f2-33dc583100c9",
hostURL: "https://us-south.watson-orchestrate.cloud.ibm.com",
rootElementID: "root",
deploymentPlatform: "ibmcloud",
crn: "crn:v1:bluemix:public:watsonx-orchestrate:us-south:a/123-456::",
chatOptions: {
agentId: "852431a8-32dd-4925-8cc3-9ea3d3162726",
agentEnvironmentId: "5d769a04-9445-4768-a687-710d6e9a24cf",
onLoad: onChatLoad
},
};
getIdentityToken().then(() => {
const script = document.createElement("script");
script.src = `${window.wxOConfiguration.hostURL}/wxochat/wxoLoader.js?embed=true`;
script.addEventListener("load", function () {
wxoLoader.init();
});
document.head.appendChild(script);
});
</script>

