Expression built-in functions
Asgard's Expression system provides eight functions for handling conversation history, data conversion and encoding inside dynamic content.
The functions
Conversation history
history
Returns the conversation history over an index range.
Syntax:
history(start, end)
Parameters:
start(number): where to start, from 0, with negative values counting from the endend(number): where to stop, inclusive, with negative values counting from the end
Returns:
string: the history as plain text, one message per line
Examples:
// the three messages at indexes 0, 1 and 2
history(0, 2)
// the last three messages
history(-3, -1)
// everything
history(0, -1)
The returned format:
bot: Hi, how can I help you?
user: Hello, I need assistance with my order.
bot: Okay, please provide your order number.
historySize
Returns how many messages the channel's history holds.
Syntax:
historySize()
Returns:
number: the message count
Example:
// returns a number, for example 5
historySize()
Data handling
urlEncode
URL-encodes a string.
Syntax:
urlEncode(val)
Parameters:
val(string): the string to encode
Returns:
string: the encoded result
Examples:
// "hello%20world"
urlEncode('hello world')
// "%E6%90%9C%E5%B0%8B%E9%97%9C%E9%8D%B5%E5%AD%97"
urlEncode('搜尋關鍵字')
// URL-encode the previous message
urlEncode(prevMessage)
vecToStr
Converts a vector array into a string.
Syntax:
vecToStr(vector, prefix, suffix, delimiter)
Parameters:
vector(array<number>): the vector arrayprefix(string): the opening charactersuffix(string): the closing characterdelimiter(string): the separator
Returns:
string: the converted string
Examples:
// "{1,2,3}"
vecToStr([1, 2, 3], '{', '}', ',')
// "[0.1|0.5|0.8]"
vecToStr([0.1, 0.5, 0.8], '[', ']', '|')
xpathExtract
Looks up a value in an XML document with XPath.
Syntax:
xpathExtract(xml, path)
Parameters:
xml(string): the XML documentpath(string): the XPath query
Returns:
string: the inner text of every matching element, separated by newlines
Examples:
const xml = '<root><item>1</item><item>2</item></root>'
// "1\n2"
xpathExtract(xml, '/root/item')
// every result title
xpathExtract(responseXml, '//result/title')
Date and time
isoNow
Returns the current date and time in a given timezone, as an RFC3339 string.
Syntax:
isoNow(timezone)
Parameters:
timezone(string): an IANA timezone name
Returns:
string: the current date and time in RFC3339
Examples:
// "2025-05-27T01:08:44+08:00"
isoNow('Asia/Taipei')
// "2025-05-26T17:08:44Z"
isoNow('UTC')
// "2025-05-26T13:08:44-04:00"
isoNow('America/New_York')
isoToday
Returns the current date in a given timezone, as an RFC3339 string.
Syntax:
isoToday(timezone)
Parameters:
timezone(string): an IANA timezone name
Returns:
string: the current date in RFC3339
Examples:
// "2025-05-27"
isoToday('Asia/Taipei')
// "2025-05-26"
isoToday('UTC')
// "2025-05-26"
isoToday('America/New_York')
Fuller examples
Analysing and summarising a conversation
// look at how the conversation is going
(() => {
const totalMessages = historySize();
if (totalMessages === 0) return 'no conversation yet';
// take the recent messages to analyse
const recentCount = Math.min(10, totalMessages);
const recentHistory = history(-recentCount, -1);
const lines = recentHistory.split('\n');
const userMessages = lines.filter(line => line.startsWith('user:')).length;
const botMessages = lines.filter(line => line.startsWith('bot:')).length;
return `Across the last ${recentCount} messages: ${userMessages} from the user, ${botMessages} from the bot`;
})()
Integrating with an API
// build a query URL
(() => {
const keyword = prevMessage || '';
const encodedQuery = urlEncode(keyword);
const timestamp = isoNow('UTC');
// build the query string
const params = [`q=${encodedQuery}`, `timestamp=${timestamp}`, `channel=${customChannelId || 'default'}`].join('&');
return `https://api.example.com/search?${params}`;
})()
Parsing XML
// handle a richer XML response
(() => {
if (!xmlResponse) return 'no XML data';
try {
const titles = xpathExtract(xmlResponse, '//result/title');
const prices = xpathExtract(xmlResponse, '//result/price');
if (!titles) return 'no results';
const titleList = titles.split('\n');
const priceList = prices ? prices.split('\n') : [];
let result = 'Results:\n';
titleList.forEach((title, index) => {
const price = priceList[index] || 'price unknown';
result += `${index + 1}. ${title} - ${price}\n`;
});
return result;
} catch (e) {
return 'XML parse error';
}
})()
Handling vectors
// format a vector for several consumers
(() => {
const userVector = [0.1, 0.5, 0.8, 0.2];
const systemVector = [0.2, 0.4, 0.7, 0.3];
const formats = {
json: vecToStr(userVector, '[', ']', ','),
csv: vecToStr(userVector, '', '', ','),
sql: vecToStr(userVector, '(', ')', ','),
};
return `Formatted:
JSON: ${formats.json}
CSV: ${formats.csv}
SQL: ${formats.sql}`;
})()
Timestamped logging
// build a log line with a timestamp
(() => {
const timezone = 'Asia/Taipei';
const now = isoNow(timezone);
const today = isoToday(timezone);
const messageCount = historySize();
const hasError = prevError ? true : false;
const logEntry = {
date: today,
timestamp: now,
messages: messageCount,
hasError: hasError,
channel: customChannelId || 'unknown',
};
return `[${now}] log: channel ${logEntry.channel}, ${logEntry.messages} messages${hasError ? ', with an error' : ''}`;
})()
Performance
Cache what you call
// ✅ cache the values you reuse rather than calling again
(() => {
const messageCount = historySize(); // called once
const timezone = 'Asia/Taipei';
const currentTime = isoNow(timezone); // called once
if (messageCount === 0) {
return `[${currentTime}] a new conversation`;
}
const recentHistory = messageCount > 5 ? history(-5, -1) : history(0, -1);
return `[${currentTime}] ${messageCount} messages\n${recentHistory}`;
})()
Call conditionally
// ✅ avoid calls you do not need
(() => {
// check the basics first
if (!prevMessage) return 'nothing to process';
// only encode when encoding is needed
const needsEncoding = /[^\w\s]/.test(prevMessage);
const processedMessage = needsEncoding ? urlEncode(prevMessage) : prevMessage;
return `Result: ${processedMessage}`;
})()
These functions cover the data handling an Expression needs for conversation logic and format conversion.