Overview
The LifeBots Workshop is a server-side JavaScript sandbox where you write your own programs to drive a LifeBots avatar (bot) in Second Life and OpenSim, live.
Controlling bots with JavaScript
You write plain, modern JavaScript — functions, callbacks, arrays, objects, Promises and async/await all work as you'd expect. Your code runs inside an isolated V8 engine (not a web browser, and not a normal Node.js process), so the language is completely familiar, but the only capabilities available to it are the Workshop globals documented in this reference.
- Modern JavaScript is fully supported, including top-level await — there is no old-engine restriction.
- There is no module system: import / export / require are disabled.
- You can't (yet) include one script inside another.
- There are no Node.js or browser APIs (no fs, no fetch, no Buffer, no DOM). Use the built-in http, localStorage and Bot interfaces instead.
Interacting with your bot
Your program runs in the sandbox and sends commands to the bot, while events flow back from the bot into your program. Both directions map straight onto ordinary JavaScript:
- Bot commands are functions you call — for example await Bot.say(0, 'Hello').
- Events are callback functions you register — for example Bot.on('chat_message', handler).
// command: a function you call
await Bot.say(0, 'Hello from the Workshop');
// event: a callback you register
Bot.on('chat_message', (msg) => {
console.log(msg.speakerName + ': ' + msg.message);
});The command and event API uses a familiar Bot.<command>() / Bot.on('event', handler) shape, so existing bot scripts from comparable platforms usually paste straight in with little or no change.
Good to know
- Almost every Bot.<command>() returns a Promise; use await or .then().
- Unless it returns a bare scalar, every command resolves to an object that always includes
success(bool) and, on failure,error(string). Command-specific fields are added on top. - Avatars/objects are SL UUIDs (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx). Many avatar params accept either a UUID or a 'First Last' name.
- scanNearbyAvatars camelCases CBaseBots PascalCase keys by lowercasing only the first character, so the avatar UUID key surfaces as
uUID(notuuid). - Scripts may only target bots the running user owns.
Use the menu on the left, or start typing to filter. Pick a command or event to see its parameters, return fields, and examples.
Selling your scripts
You can publish a Workshop script to the LifeBots addon store and earn L$ when other users buy it. Buyers can run your script on their own bot and configure its settings — but they can never see your source code. Your code stays protected on the server.
How source protection works
When you publish a version, the Workshop snapshots your code into a release on the server. That release is never sent to any browser. Each buyer gets an owned copy that stores their bot choice and settings but holds no code — when they press Run, the runtime loads your code server-side. The result: buyers run exactly the version you shipped, with zero visibility into how it works.
Step 1 — Build and test your script
Write and debug your script normally in the Workshop, attached to one of your own bots. Get it working end-to-end before you think about selling — buyers run the exact code you publish.
Step 2 — Expose settings (optional, recommended)
Most sellable scripts need per-buyer configuration (a greeting message, a group key, an API token…). Instead of hard-coding these, define a user settings schema — a list of fields (text, textarea, number, select, or checkbox) that buyers fill in on a simple form. Number fields can declare an optional min/max range that the buyer's form enforces, so you don't have to bounds-check in the script. Read them in your code via the userSettings global:
const greeting = userSettings.greeting || 'Hello!';
await Bot.say(0, greeting);The schema is snapshotted into each release, so a buyer always sees the field set that matches the version they run. Never put secrets you don't want buyers to control in code — expose them as settings the buyer provides instead.
Step 3 — Cut a version
On the script's Versioning tab, publish a release with a MAJOR.MINOR.PATCH version (e.g. 1.0.0). This snapshots your current code + settings schema. Rules:
- The script can't be empty.
- Each new version must be strictly greater than the last (
1.0.1>1.0.0). - You need at least one release before the script can go on sale.
Cutting a version is independent of listing for sale — you can version privately and only enable sale later.
Step 4 — Fill in the store listing
On the Listing tab, provide the details buyers see in the store:
| Field | Notes |
|---|---|
Store name | Display name in the store (up to 80 chars). Defaults to the script name. |
Short description | Store-card blurb. Required to sell — at least 10 characters (max 280). |
Long description | Full details on the addon page. Markdown supported (max 8000 chars). |
Price | Whole L$, from 0 to 1,000,000. 0 = free. |
Category | Optional grouping label. |
Store images | On the Store Images tab. At least one https:// image is required to sell (up to 8). |
Contacts | Optional support contacts (up to 10). |
Step 5 — Turn on “Available for sale”
Flip the Available for sale toggle on the Listing tab. Before it can go live you must have: at least one published version, a short description of 10+ characters, and at least one store image. Toggle it off any time to pull the script from sale — existing buyers keep their copies and can still run them.
Step 6 — Approval
Your listing is mirrored into the LifeBots store. Trusted developers are auto-approved and go live immediately. Everyone else starts as Pending until a LifeBots admin reviews and activates the listing. The script's status badge (Live / Pending / Hidden) shows where it stands.
Step 7 — Preview as a buyer
Use Test purchase to install your own script the way a buyer would — schema-driven settings form, no source visible, run on a bot. It skips the wallet and the published check (but still needs a release). Remove the test copies when you're done; they don't affect real buyers.
Pricing & earnings
- Buyers pay from their L$ wallet; the price transfers to your wallet instantly, with an audit transaction on both sides.
- Free scripts (price
0) skip the wallet entirely. - A buyer who already owns a script won't be charged again — re-buying just returns their existing copy.
- You can't buy your own script (it's already in your authored list).
Updating buyers after release
Each buyer is pinned to the release they're running, so a new version never changes their behavior unexpectedly. To ship an update, cut a new version (Step 3), then:
- Buyers see an “update available” flag and can update themselves, with a changelog of what's new.
- From your Sales view you can push one buyer — or all buyers — to the latest release; running copies restart automatically onto the new code.
- Publishing with force update moves every buyer to the new release at once.
The Sales view also reports each buyer (name censored for privacy), the version they're on, their run status, and whether they're behind. Buyers who own a script can rate it 1–5 stars.
Globals & built-in functions
The basic built-in functions do not relate to bot functionality. Instead, they let you write flexible scripts. Each script runs in its own isolated-vm V8 Isolate with a private heap and no shared memory with the host. The script's top-level code runs once at start; top-level await is supported. Any Bot.on(...) handlers you register keep firing after the top-level finishes, until the script is stopped or calls process.exit().
setTimeout(function () {
console.log("Timer has fired!");
}, 3000);List of functions
Click any function for its parameters, return value, and examples.
| Script details & flow | |
process.name | Read-only property reflecting the running script's display name (shown in the left panel). |
process.release | Read-only property reflecting the script release version (for store scripts). |
process.exit | Ends execution of the script. |
process.sleep | Pauses script execution for the given number of milliseconds. |
| Timer control | |
setTimeout | Runs a callback once after a delay (ms). |
clearTimeout | Cancels a pending setTimeout by its id. |
setInterval | Runs a callback repeatedly every ms. |
clearInterval | Stops a repeating setInterval by its id. |
| Persistent bot storage | |
localStorage.get | Restores a string value from persistent storage. |
localStorage.set | Puts a string value into persistent storage. |
localStorage.keys | Returns the list of available keys in persistent storage (for this bot). |
localStorage.remove | Deletes a key. localStorage.delete() is an alias. |
localStorage.on | Adds an event callback on localStorage. selector = a key name fires handler(oldValue, newValue) on any write to that key (including this… |
| User settings | |
userSettings | Access any configured setting as a property, e.g. userSettings.systemPrompt. |
| HTTP | |
http.get | Retrieves data from an HTTP source via GET. |
http.post | Sends data to an HTTP source via POST. |
http.requestWebhookUrl | Allocates a new per-run webhook URL and bearer token for this script instance. |
| Debug | |
console.log | Logs data to the runtime log. console.info and console.debug behave the same. |
console.warn | Logs data at the 'warn' level. |
console.error | Logs data at the 'error' level. |
_assert | Logs an error line if the assertion is false. |
The Bot object
Command surface + Bot.on/off + Bot.AI. It is a Proxy: any unknown method (Bot.somecommand(...)) is dispatched to the host, so every command in the Commands list is callable even though it isn’t a literal property. bot is an alias of Bot.
| Property | Type | Description |
|---|---|---|
Bot.agentId | string | The bot’s avatar UUID. |
Bot.name | string | The bot’s Second Life name. |
Bot.<command>(...args)— any command in the sidebar; returns aPromise.Bot.on(event, handler)/Bot.off(event, handler?)— subscribe / unsubscribe to events (chainable).
Not available
User scripts run in a true V8 sandbox — the following are intentionally absent:
- require() and import — there is no module system; static import/require is rejected before the script runs
- Node's real process — only the sandboxed process shim is exposed
- Node core modules — fs, path, os, net, child_process, crypto, etc.
- Buffer
- fetch / XMLHttpRequest / WebSocket — use http.get / http.post instead
- DOM / window / document — there is no browser environment
Safety & resource caps
User code cannot reach the host. Inputs/outputs cross the boundary by deep clone, Error.prepareStackTrace is locked, and the host injection slots are wiped after bootstrap. Runaway scripts are bounded by per-call CPU timeouts, a heap cap, and a sustained-CPU monitor (see Limits). See Limits for the exact numbers.
process.name
Read-only property reflecting the running script's display name (shown in the left panel).
Example
console.log(process.name);process.release
Read-only property reflecting the script release version (for store scripts). Currently always an empty string in this runtime.
Example
console.log(process.release);process.exit()
Ends execution of the script. Sets the script's desiredState to 'stopped' (one-shot scripts do not auto-resume) and disposes the isolate.
Usage
await Bot.say(0, 'done');
process.exit();Input
None.
Returns
Does not return — throws internally to halt the script
process.sleep(ms)
Pauses script execution for the given number of milliseconds.
Usage
await process.sleep(2000);Input
| Variable | Required | Description |
|---|---|---|
ms | yes | Milliseconds to pause |
Returns
Promise (resolves after ms)
setTimeout(fn, ms, ...args)
Runs a callback once after a delay (ms). Returns a numeric timer id that can be passed to clearTimeout.
Usage
const id = setTimeout((name) => console.log('hi ' + name), 1000, 'Bob');
// clearTimeout(id); // to cancel before it firesInput
| Variable | Required | Description |
|---|---|---|
fn | yes | Callback to run |
ms | yes | Delay in milliseconds |
...args | no | Extra arguments passed to the callback |
Returns
number — timer id (use with clearTimeout)
clearTimeout(id)
Cancels a pending setTimeout by its id.
Usage
const id = setTimeout(() => console.log('hi'), 5000);
clearTimeout(id); // cancels it before it firesInput
| Variable | Required | Description |
|---|---|---|
id | yes | Timer id returned by setTimeout |
Returns
undefined (synchronous)
setInterval(fn, ms, ...args)
Runs a callback repeatedly every ms. Returns a numeric timer id for clearInterval. The next tick is scheduled only after the previous callback resolves.
Usage
let n = 0;
const id = setInterval(() => {
if (++n >= 5) clearInterval(id);
console.log('tick', n);
}, 5000);Input
| Variable | Required | Description |
|---|---|---|
fn | yes | Callback to run each interval |
ms | yes | Interval in milliseconds |
...args | no | Extra arguments passed to the callback |
Returns
number — timer id (use with clearInterval)
clearInterval(id)
Stops a repeating setInterval by its id.
Usage
const id = setInterval(() => console.log('tick'), 1000);
clearInterval(id); // stops the repeating timerInput
| Variable | Required | Description |
|---|---|---|
id | yes | Timer id returned by setInterval |
Returns
undefined (synchronous)
localStorage.get(key)
Restores a string value from persistent storage.
Usage
const v = await localStorage.get('runs');Input
| Variable | Required | Description |
|---|---|---|
key | yes | Key to read |
Returns
Promise<string|null> — the value, or null if unset
localStorage.set(key, value)
Puts a string value into persistent storage.
Usage
await localStorage.set('runs', String(n));Input
| Variable | Required | Description |
|---|---|---|
key | yes | Key to write |
value | yes | Value to store |
Returns
Promise (resolves once written)
localStorage.keys()
Returns the list of available keys in persistent storage (for this bot).
Usage
const keys = await localStorage.keys();Input
None.
Returns
Promise<string[]>
localStorage.remove(key)
Deletes a key. localStorage.delete() is an alias.
Usage
await localStorage.remove('runs');Input
| Variable | Required | Description |
|---|---|---|
key | yes | Key to delete |
Returns
Promise (resolves once removed)
localStorage.on(selector, handler)
Adds an event callback on localStorage. selector = a key name fires handler(oldValue, newValue) on any write to that key (including this script's own writes). selector = 'update' (or its alias 'change') fires handler(key, newValue, scriptName) for CROSS-script writes only.
Usage
localStorage.on('update', (key, val, fromScript) => {
console.log(fromScript + ' set ' + key + ' = ' + val);
});Input
| Variable | Required | Description |
|---|---|---|
selector | yes | A key name, or 'update' / 'change' |
handler | yes | Callback (signature depends on selector) |
Returns
undefined (registers the observer)
userSettings
Access any configured setting as a property, e.g. userSettings.systemPrompt. Values are whatever the settings form produced (usually strings) — coerce as needed.
Example
const prompt = userSettings.systemPrompt || 'You are helpful.';
const temp = parseFloat(userSettings.temperature) || 0.7;http.get(url, opts)
Retrieves data from an HTTP source via GET. Returns the response body as text; throws on non-2xx, redirect, SSRF block, timeout, or oversize body.
Usage
const body = await http.get('https://api.example.com/data');
const data = JSON.parse(body);Input
| Variable | Required | Description |
|---|---|---|
url | yes | http/https URL |
opts | no | { headers? } |
Returns
Promise<string> — the response body text
http.post(url, data, opts)
Sends data to an HTTP source via POST. A string body is sent as-is (text/plain); an object is JSON-stringified with Content-Type application/json. Returns the response body text.
Usage
const res = await http.post('https://api.example.com/echo', { hello: 'world' });Input
| Variable | Required | Description |
|---|---|---|
url | yes | http/https URL |
data | yes | String body, or object (sent as JSON) |
opts | no | { headers? } |
Returns
Promise<string> — the response body text
http.requestWebhookUrl()
Allocates a new per-run webhook URL and bearer token for this script instance. Inbound HTTP hits to the URL fire the workshop_webhook event. Callers must send 'Authorization: Bearer <token>'.
Usage
const hook = await http.requestWebhookUrl();
Bot.on('workshop_webhook', (e) => console.log(e.payload));Input
None.
Returns
Promise<{ success, url, token }>
Output fields
| Field | Type | Description |
|---|---|---|
success | bool | true if allocation succeeded |
url | string | The public webhook URL |
token | string | Bearer token callers must send |
console.log(...args)
Logs data to the runtime log. console.info and console.debug behave the same.
Usage
console.log('user', { name: 'Bob' });Input
| Variable | Required | Description |
|---|---|---|
...args | yes | Any values; objects are JSON-stringified, Errors print their stack |
Returns
undefined
console.warn(...args)
Logs data at the 'warn' level.
Usage
console.warn('careful').then(function (res) {
console.log("console.warn response:", res);
});Or using async/await:
let res = await console.warn('careful');
console.log("console.warn response:", res);Input
| Variable | Required | Description |
|---|---|---|
...args | yes | Any values |
Returns
undefined
console.error(...args)
Logs data at the 'error' level.
Usage
console.error('failed:', err).then(function (res) {
console.log("console.error response:", res);
});Or using async/await:
let res = await console.error('failed:', err);
console.log("console.error response:", res);Input
| Variable | Required | Description |
|---|---|---|
...args | yes | Any values |
Returns
undefined
_assert(cond, message)
Logs an error line if the assertion is false. Does NOT throw — execution continues.
Usage
_assert(result.success, 'command should have succeeded');Input
| Variable | Required | Description |
|---|---|---|
cond | yes | Condition to assert |
message | no | Message logged when cond is falsy |
Returns
undefined
Bot.status()
Returns the bot's online status and location.
Usage
Bot.status().then(function (res) {
console.log("status response:", res);
});Or using async/await:
let res = await Bot.status();
console.log("status response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
status | string | Connection status, e.g. "ONLINE" |
online | string | "1" if the bot is online |
slname | string | Bot's Second Life name |
uuid | string | Bot's avatar UUID |
location | string | Current position, format "Region/X/Y/Z" |
Example response
{
"success": true,
"status": "ONLINE",
"online": "1",
"slname": "My Bot",
"uuid": "0b65a122-8f77-64fe-5b2a-225d4c490d9c",
"location": "Mainland/128/128/25"
}Bot.statusExt()
Status with extended fields. CBaseBots currently returns the same shape as status() (no extra fields are added today).
Usage
Bot.statusExt().then(function (res) {
console.log("statusExt response:", res);
});Or using async/await:
let res = await Bot.statusExt();
console.log("statusExt response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
status | string | Connection status, e.g. "ONLINE" |
online | string | "1" if the bot is online |
slname | string | Bot's Second Life name |
uuid | string | Bot's avatar UUID |
location | string | Current position, format "Region/X/Y/Z" |
Bot.isOnline()
Returns a bare boolean — true if the bot is online.
Usage
Bot.isOnline().then(function (res) {
console.log("isOnline response:", res);
});Or using async/await:
let res = await Bot.isOnline();
console.log("isOnline response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
| (return value) | bool | true if the bot is currently online, false otherwise |
Bot.login()
Logs the bot in.
Usage
Bot.login().then(function (res) {
console.log("login response:", res);
});Or using async/await:
let res = await Bot.login();
console.log("login response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | Present when already logged in ("Bot is already logged in") |
Bot.logout()
Logs the bot out.
Usage
Bot.logout().then(function (res) {
console.log("logout response:", res);
});Or using async/await:
let res = await Bot.logout();
console.log("logout response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.say(channel, message)
Sends a chat message on a channel. Channel 0 is local nearby chat.
Usage
Bot.say(0, 'Hello, world').then(function (res) {
console.log("say response:", res);
});Or using async/await:
let res = await Bot.say(0, 'Hello, world');
console.log("say response:", res);Input
| Variable | Required | Description |
|---|---|---|
channel | yes | Chat channel. 0 = local nearby chat; any integer otherwise |
message | yes | Text to send |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Message sent" |
Example response
{
"success": true,
"resulttext": "Message sent"
}Bot.im(name_or_UUID, message)
Sends an instant message to an avatar.
Usage
Bot.im('0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'Hi there!').then(function (res) {
console.log("im response:", res);
});Or using async/await:
let res = await Bot.im('0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'Hi there!');
console.log("im response:", res);Input
| Variable | Required | Description |
|---|---|---|
name_or_UUID | yes | Avatar UUID or "First Last" name |
message | yes | Text to send |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "IM sent" |
Example response
{
"success": true,
"resulttext": "IM sent"
}Bot.startTyping(uuid, delay)
Shows the typing indicator in an IM session.
Usage
Bot.startTyping('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("startTyping response:", res);
});Or using async/await:
let res = await Bot.startTyping('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("startTyping response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Target avatar UUID |
delay | no | Seconds before it auto-clears (default 15) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.stopTyping(uuid)
Stops the typing indicator.
Usage
Bot.stopTyping('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("stopTyping response:", res);
});Or using async/await:
let res = await Bot.stopTyping('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("stopTyping response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Target avatar UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.replyDialog(channel, object, button)
Presses a button on a received script dialog (see the script_dialog event).
Usage
Bot.replyDialog(1, '0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'Yes').then(function (res) {
console.log("replyDialog response:", res);
});Or using async/await:
let res = await Bot.replyDialog(1, '0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'Yes');
console.log("replyDialog response:", res);Input
| Variable | Required | Description |
|---|---|---|
channel | yes | Dialog channel (from the script_dialog event) |
object | yes | Object UUID (from the event) |
button | yes | Button label to press |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
reply | string | The button label that was pressed |
Bot.friends()
Returns the bot's friends list and the friendship rights on each side.
Usage
Bot.friends().then(function (res) {
console.log("friends response:", res);
});Or using async/await:
let res = await Bot.friends();
console.log("friends response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
friends | array | Array of friend objects (see below) |
friends[].slname | string | Friend's SL name |
friends[].uuid | string | Friend's avatar UUID |
friends[].online | bool | true if the friend is online |
friends[].theirRights | object | { canSeeOnMap, canSeeOnline, canModifyObjects } — rights they granted the bot |
friends[].myRights | object | { canSeeOnMap, canSeeOnline, canModifyObjects } — rights the bot granted them |
Example response
{
"success": true,
"friends": [
{
"slname": "Resident One",
"uuid": "11111111-2222-3333-4444-555555555555",
"online": true,
"theirRights": {
"canSeeOnMap": false,
"canSeeOnline": true,
"canModifyObjects": false
},
"myRights": {
"canSeeOnMap": false,
"canSeeOnline": true,
"canModifyObjects": false
}
}
]
}Bot.offerFriendship(avatar, message)
Sends a friend request to an avatar.
Usage
Bot.offerFriendship('0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'Be my friend').then(function (res) {
console.log("offerFriendship response:", res);
});Or using async/await:
let res = await Bot.offerFriendship('0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'Be my friend');
console.log("offerFriendship response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID or name |
message | no | Offer message (default "Be my friend") |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.acceptFriendshipOffer(avatar_uuid, session_id, accept)
Accepts or rejects a pending friendship offer. session_id comes from the friendship_offer event.
Usage
Bot.acceptFriendshipOffer('0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'session-uuid', true).then(function (res) {
console.log("acceptFriendshipOffer response:", res);
});Or using async/await:
let res = await Bot.acceptFriendshipOffer('0b65a122-8f77-64fe-5b2a-225d4c490d9c', 'session-uuid', true);
console.log("acceptFriendshipOffer response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar_uuid | yes | Offering avatar's UUID |
session_id | yes | Session id from the friendship_offer event |
accept | no | true to accept, false to reject (default true) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Friendship accepted" or "Friendship declined" |
Bot.cancelFriendship(uuid)
Removes a friend (LifeBots extension).
Usage
Bot.cancelFriendship('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("cancelFriendship response:", res);
});Or using async/await:
let res = await Bot.cancelFriendship('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("cancelFriendship response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Friend's avatar UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.activateGroup(groupuuid)
Sets the bot's active group tag.
Usage
Bot.activateGroup('group-uuid').then(function (res) {
console.log("activateGroup response:", res);
});Or using async/await:
let res = await Bot.activateGroup('group-uuid');
console.log("activateGroup response:", res);Input
| Variable | Required | Description |
|---|---|---|
groupuuid | yes | Group UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.listGroups()
Lists the groups the bot has joined.
Usage
Bot.listGroups().then(function (res) {
console.log("listGroups response:", res);
});Or using async/await:
let res = await Bot.listGroups();
console.log("listGroups response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
groups | string | Newline-delimited "groupUUID;groupName" pairs (NOT an array) |
Example response
{
"success": true,
"groups": "11111111-...;My Group\n22222222-...;Another Group"
}Bot.groupInfo(groupUUID)
Returns details about a group.
Usage
Bot.groupInfo('group-uuid').then(function (res) {
console.log("groupInfo response:", res);
});Or using async/await:
let res = await Bot.groupInfo('group-uuid');
console.log("groupInfo response:", res);Input
| Variable | Required | Description |
|---|---|---|
groupUUID | yes | Group UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
name | string | Group name |
uuid | string | Group UUID |
charter | string | Group charter text |
members | number | Member count |
member_title | string | Bot's title in the group |
insignia | string | Group insignia texture UUID |
founder | string | Founder avatar UUID |
fee | number | Membership fee (L$) |
open | bool | true if open enrollment |
mature | bool | true if mature-rated |
Bot.joinGroup(groupuuid)
Joins a group by UUID.
Usage
Bot.joinGroup('group-uuid').then(function (res) {
console.log("joinGroup response:", res);
});Or using async/await:
let res = await Bot.joinGroup('group-uuid');
console.log("joinGroup response:", res);Input
| Variable | Required | Description |
|---|---|---|
groupuuid | yes | Group UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.leaveGroup(groupuuid)
Leaves a group by UUID.
Usage
Bot.leaveGroup('group-uuid').then(function (res) {
console.log("leaveGroup response:", res);
});Or using async/await:
let res = await Bot.leaveGroup('group-uuid');
console.log("leaveGroup response:", res);Input
| Variable | Required | Description |
|---|---|---|
groupuuid | yes | Group UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.ejectGroupMember(avatar, groupuuid)
Ejects a member from a group.
Usage
Bot.ejectGroupMember('avatar-uuid', 'group-uuid').then(function (res) {
console.log("ejectGroupMember response:", res);
});Or using async/await:
let res = await Bot.ejectGroupMember('avatar-uuid', 'group-uuid');
console.log("ejectGroupMember response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Member's avatar UUID or name |
groupuuid | yes | Group UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.setGroupRole(avatar_uuid, group_uuid, role_uuid)
Adds a member to a group role.
Usage
Bot.setGroupRole('avatar-uuid', 'group-uuid', 'role-uuid').then(function (res) {
console.log("setGroupRole response:", res);
});Or using async/await:
let res = await Bot.setGroupRole('avatar-uuid', 'group-uuid', 'role-uuid');
console.log("setGroupRole response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar_uuid | yes | Member's avatar UUID |
group_uuid | yes | Group UUID |
role_uuid | yes | Role UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.revokeGroupRole(avatar_uuid, group_uuid, role_uuid)
Removes a member from a group role.
Usage
Bot.revokeGroupRole('avatar-uuid', 'group-uuid', 'role-uuid').then(function (res) {
console.log("revokeGroupRole response:", res);
});Or using async/await:
let res = await Bot.revokeGroupRole('avatar-uuid', 'group-uuid', 'role-uuid');
console.log("revokeGroupRole response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar_uuid | yes | Member's avatar UUID |
group_uuid | yes | Group UUID |
role_uuid | yes | Role UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.sendGroupIM(groupuuid, message)
Sends a message to a group's chat session.
Usage
Bot.sendGroupIM('group-uuid', 'Hello group!').then(function (res) {
console.log("sendGroupIM response:", res);
});Or using async/await:
let res = await Bot.sendGroupIM('group-uuid', 'Hello group!');
console.log("sendGroupIM response:", res);Input
| Variable | Required | Description |
|---|---|---|
groupuuid | yes | Group UUID |
message | yes | Text to send |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
groupUUID | string | The group UUID the message was sent to |
Bot.sendNotice(groupuuid, subject, text, attachment)
Sends a group notice, optionally with an inventory attachment.
Usage
Bot.sendNotice('group-uuid', 'Meeting', 'See you at 5pm', '').then(function (res) {
console.log("sendNotice response:", res);
});Or using async/await:
let res = await Bot.sendNotice('group-uuid', 'Meeting', 'See you at 5pm', '');
console.log("sendNotice response:", res);Input
| Variable | Required | Description |
|---|---|---|
groupuuid | yes | Group UUID |
subject | yes | Notice subject |
text | yes | Notice body |
attachment | no | Inventory item UUID to attach (default none) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
groupUUID | string | The group UUID the notice was sent to |
Bot.acceptGroupOffer(avatar_uuid, session_id, accept)
Accepts or rejects a group invite. session_id comes from the group_offer event.
Usage
Bot.acceptGroupOffer('avatar-uuid', 'session-uuid', true).then(function (res) {
console.log("acceptGroupOffer response:", res);
});Or using async/await:
let res = await Bot.acceptGroupOffer('avatar-uuid', 'session-uuid', true);
console.log("acceptGroupOffer response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar_uuid | yes | Inviting avatar UUID |
session_id | yes | Session id from the group_offer event |
accept | no | true to accept, false to reject (default true) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Group invite accepted" or "Group invite declined" |
Bot.inviteGroup(avatar, groupuuid, roleuuid, check_membership)
Invites an avatar to a group, optionally into a specific role.
Usage
Bot.inviteGroup('avatar-uuid', 'group-uuid', '', true).then(function (res) {
console.log("inviteGroup response:", res);
});Or using async/await:
let res = await Bot.inviteGroup('avatar-uuid', 'group-uuid', '', true);
console.log("inviteGroup response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID or name to invite |
groupuuid | yes | Group UUID |
roleuuid | no | Role UUID (default everyone role) |
check_membership | no | If truthy, skip avatars already in the group |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Group invite sent" |
Bot.listInventory(folderUUID)
Lists the contents of an inventory folder (root if omitted).
Usage
Bot.listInventory().then(function (res) {
console.log("listInventory response:", res);
});Or using async/await:
let res = await Bot.listInventory();
console.log("listInventory response:", res);Input
| Variable | Required | Description |
|---|---|---|
folderUUID | no | Folder UUID; root folder if omitted |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
items | array | Array of inventory entries (see below) |
items[].id | string | Item or folder UUID |
items[].name | string | Item or folder name |
items[].type | string | Asset type (e.g. notecard, object, folder) |
items[].folderType | number | Folder type code (folders only) |
Bot.giveInventory(avatar, object)
Gives an inventory item (or folder) to an avatar.
Usage
Bot.giveInventory('avatar-uuid', 'item-uuid').then(function (res) {
console.log("giveInventory response:", res);
});Or using async/await:
let res = await Bot.giveInventory('avatar-uuid', 'item-uuid');
console.log("giveInventory response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Recipient avatar UUID or name |
object | yes | Inventory item or folder UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Inventory item given" or "Inventory folder given" |
Bot.deleteInventory(uuid)
Deletes an inventory item.
Usage
Bot.deleteInventory('item-uuid').then(function (res) {
console.log("deleteInventory response:", res);
});Or using async/await:
let res = await Bot.deleteInventory('item-uuid');
console.log("deleteInventory response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Inventory item UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.acceptInventoryOffer(sender_type, object_id, sender_uuid, folder, session, accept)
Accepts or rejects an inventory offer (see the inventory_offer event).
Usage
Bot.acceptInventoryOffer('agent', '', 'sender-uuid', '', 'session-uuid', true).then(function (res) {
console.log("acceptInventoryOffer response:", res);
});Or using async/await:
let res = await Bot.acceptInventoryOffer('agent', '', 'sender-uuid', '', 'session-uuid', true);
console.log("acceptInventoryOffer response:", res);Input
| Variable | Required | Description |
|---|---|---|
sender_type | no | "agent" or "object" (default "agent") |
object_id | no | Object UUID if the sender is an object |
sender_uuid | yes | Sender's avatar UUID |
folder | no | Destination folder UUID |
session | yes | Session id from the inventory_offer event |
accept | no | true to accept, false to reject (default true) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Inventory accepted" or "Inventory declined" |
Bot.createNotecard(folder, name, description, text)
Creates a notecard in inventory.
Usage
Bot.createNotecard('', 'My Notecard', 'A note', 'Hello from a notecard.').then(function (res) {
console.log("createNotecard response:", res);
});Or using async/await:
let res = await Bot.createNotecard('', 'My Notecard', 'A note', 'Hello from a notecard.');
console.log("createNotecard response:", res);Input
| Variable | Required | Description |
|---|---|---|
folder | no | Destination folder UUID (root if omitted) |
name | yes | Notecard name |
description | no | Notecard description |
text | yes | Notecard body text |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
uuid | string | UUID of the newly created notecard |
Bot.editNotecard(uuid, text)
Replaces a notecard's text.
Usage
Bot.editNotecard('notecard-uuid', 'New content').then(function (res) {
console.log("editNotecard response:", res);
});Or using async/await:
let res = await Bot.editNotecard('notecard-uuid', 'New content');
console.log("editNotecard response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Notecard UUID |
text | yes | New body text |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.readNotecard(uuid)
Reads a notecard's text.
Usage
Bot.readNotecard('notecard-uuid').then(function (res) {
console.log("readNotecard response:", res);
});Or using async/await:
let res = await Bot.readNotecard('notecard-uuid');
console.log("readNotecard response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Notecard UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
text | string | The notecard's body text |
Bot.wear(uuid)
Wears / attaches an inventory item.
Usage
Bot.wear('item-uuid').then(function (res) {
console.log("wear response:", res);
});Or using async/await:
let res = await Bot.wear('item-uuid');
console.log("wear response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Inventory item UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
itemName | string | Name of the worn item |
resulttext | string | Human-readable result message |
Bot.takeoff(uuid)
Detaches / takes off an item.
Usage
Bot.takeoff('item-uuid').then(function (res) {
console.log("takeoff response:", res);
});Or using async/await:
let res = await Bot.takeoff('item-uuid');
console.log("takeoff response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Inventory item UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | e.g. "Detached <item>" |
Bot.getBalance()
Returns the bot's L$ balance.
Usage
Bot.getBalance().then(function (res) {
console.log("getBalance response:", res);
});Or using async/await:
let res = await Bot.getBalance();
console.log("getBalance response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
balance | number | Current L$ balance |
Example response
{
"success": true,
"balance": 1250
}Bot.giveMoney(avatar, amount, comment)
Sends L$ to an avatar.
Usage
Bot.giveMoney('avatar-uuid', 100, 'Thanks!').then(function (res) {
console.log("giveMoney response:", res);
});Or using async/await:
let res = await Bot.giveMoney('avatar-uuid', 100, 'Thanks!');
console.log("giveMoney response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Recipient avatar UUID or name |
amount | yes | Amount of L$ to send |
comment | no | Transaction comment |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.fly(enableFlying)
Toggles flying mode.
Usage
Bot.fly(true).then(function (res) {
console.log("fly response:", res);
});Or using async/await:
let res = await Bot.fly(true);
console.log("fly response:", res);Input
| Variable | Required | Description |
|---|---|---|
enableFlying | yes | Truthy to fly, falsy to stop flying |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.getLocation()
Returns the bot's current region and position.
Usage
Bot.getLocation().then(function (res) {
console.log("getLocation response:", res);
});Or using async/await:
let res = await Bot.getLocation();
console.log("getLocation response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
region | string | Region name |
x | number | X position in region |
y | number | Y position in region |
z | number | Z position (height) |
Example response
{
"success": true,
"region": "Mainland",
"x": 128.5,
"y": 64.2,
"z": 25
}Bot.move(instruction, state)
Low-level movement control — start/stop directional movement.
Usage
Bot.move('FORWARD', 'START').then(function (res) {
console.log("move response:", res);
});Or using async/await:
let res = await Bot.move('FORWARD', 'START');
console.log("move response:", res);Input
| Variable | Required | Description |
|---|---|---|
instruction | yes | One of FORWARD, BACK, LEFT, RIGHT, FLY, STOP |
state | yes | START or STOP |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.sit(uuid, save)
Sits the bot on a prim. uuid="NONE" stands the bot up.
Usage
Bot.sit('prim-uuid').then(function (res) {
console.log("sit response:", res);
});Or using async/await:
let res = await Bot.sit('prim-uuid');
console.log("sit response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | no | Prim UUID to sit on; "NONE" stands up (default "NONE") |
save | no | If truthy, save as permanent sit location |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
message | string | Human-readable result (e.g. "Sitting") |
Bot.stand()
Stands the bot up. Alias of sit("NONE").
Usage
Bot.stand().then(function (res) {
console.log("stand response:", res);
});Or using async/await:
let res = await Bot.stand();
console.log("stand response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
message | string | Human-readable result |
Bot.teleport(location)
Teleports the bot to a location.
Usage
Bot.teleport('Mainland/128/128/25').then(function (res) {
console.log("teleport response:", res);
});Or using async/await:
let res = await Bot.teleport('Mainland/128/128/25');
console.log("teleport response:", res);Input
| Variable | Required | Description |
|---|---|---|
location | yes | "Region/X/Y/Z" or "HOME" |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Teleported to <region>" on success |
Bot.walkTo(x, y, z)
Walks (autopilot) to a position in the current region. Fires autopilot_* events. Each call first stops the bot and switches flying off, and coordinates are rounded down to whole metres — to re-aim a moving bot often (e.g. following an avatar) use moveTo, and to fly use flyTo.
Usage
Bot.walkTo(128, 128, 25).then(function (res) {
console.log("walkTo response:", res);
});Or using async/await:
let res = await Bot.walkTo(128, 128, 25);
console.log("walkTo response:", res);Input
| Variable | Required | Description |
|---|---|---|
x | yes | Target X in region |
y | yes | Target Y in region |
z | yes | Target Z (height) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Walking to <x>, <y>, <z>" |
Bot.moveTo(x, y, z, options)
Walks to a position in the current region with continuous steering. Unlike walkTo it never stops the bot between calls — a new call just moves the target — and it keeps decimal precision, so it suits scripts that re-aim often, such as following an avatar. Runs in the background and ends on arrival (within 0.75 m), after 3 s without progress, or when another movement command is sent. Honours alwaysRun. Does not fire autopilot_* events. Within 3 m of a target point that has stopped moving it automatically slows down and stops on the point instead of coasting past (a point you keep re-aiming ahead of a moving avatar keeps normal speed). Pass { slow: true } to walk slowly the whole way.
Usage
Bot.moveTo(128.5, 64.2, 25).then(function (res) {
console.log("moveTo response:", res);
});Or using async/await:
let res = await Bot.moveTo(128.5, 64.2, 25);
console.log("moveTo response:", res);Input
| Variable | Required | Description |
|---|---|---|
x | yes | Target X in region |
y | yes | Target Y in region |
z | yes | Target Z (height); ignored while walking |
options | no | Optional { slow: true }: the bot walks very slowly and stops dead on the point instead of coasting past it (holds the server STOP control, like holding the spacebar while walking in Firestorm). Default: normal walking. |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Moving to <x>, <y>, <z>" |
Bot.flyTo(x, y, z, options)
Flies to a position in the current region, including climbing and descending, with continuous steering (same behaviour as moveTo). Switches flying on, brakes smoothly into the target instead of overshooting, and keeps hovering on arrival. walkTo cannot fly: it switches flying off, and the autopilot ignores height. Bot.fly(false) lands the bot and ends the flight. Flight speed is capped (6 m/s by default) by pulsing the controls around the limit, the same technique the viewer's autopilot uses; pass options.speed to change it.
Usage
Bot.flyTo(128, 128, 60, { speed: 4 }).then(function (res) {
console.log("flyTo response:", res);
});Or using async/await:
let res = await Bot.flyTo(128, 128, 60, { speed: 4 });
console.log("flyTo response:", res);Input
| Variable | Required | Description |
|---|---|---|
x | yes | Target X in region |
y | yes | Target Y in region |
z | yes | Target Z (height) |
options | no | Optional speed cap in m/s (horizontal and vertical), as a number or { speed }. Default 6; 0 = no limit (the sim top speed). Values are clamped to 0.2-50. Very low values (under 1.5) use the slow nudge controls. |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Flying to <x>, <y>, <z>" |
Bot.moveAlong(points, options)
Walks through a list of waypoints with continuous steering (same engine as moveTo), ending at the last one — e.g. to follow the exact path another avatar walked around corners and obstacles. Each point is passed once reached (or once the bot has clearly gone past it). A new call replaces the waypoints without stopping the bot. Up to 128 points; invalid points are skipped.
Usage
Bot.moveAlong([{ x: 120, y: 64, z: 25 }, { x: 124, y: 70, z: 25 }, { x: 130, y: 71, z: 25 }]).then(function (res) {
console.log("moveAlong response:", res);
});Or using async/await:
let res = await Bot.moveAlong([{ x: 120, y: 64, z: 25 }, { x: 124, y: 70, z: 25 }, { x: 130, y: 71, z: 25 }]);
console.log("moveAlong response:", res);Input
| Variable | Required | Description |
|---|---|---|
points | yes | Array of region positions: { x, y, z } objects or [x, y, z] arrays |
options | no | Optional { slow: true }: the bot walks very slowly and stops dead at the last point instead of coasting past it (holds the server STOP control, like holding the spacebar while walking in Firestorm). Default: normal walking. |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Moving along <n> point(s) to <x>, <y>, <z>" |
Bot.flyAlong(points, options)
Like moveAlong, but flying (including climbing and descending, same engine as flyTo). Brakes smoothly into the last point instead of overshooting it. Speed is capped like flyTo (6 m/s by default).
Usage
Bot.flyAlong([{ x: 120, y: 64, z: 40 }, { x: 140, y: 80, z: 55 }], { speed: 4 }).then(function (res) {
console.log("flyAlong response:", res);
});Or using async/await:
let res = await Bot.flyAlong([{ x: 120, y: 64, z: 40 }, { x: 140, y: 80, z: 55 }], { speed: 4 });
console.log("flyAlong response:", res);Input
| Variable | Required | Description |
|---|---|---|
points | yes | Array of region positions: { x, y, z } objects or [x, y, z] arrays |
options | no | Optional speed cap in m/s (horizontal and vertical), as a number or { speed }. Default 6; 0 = no limit (the sim top speed). Values are clamped to 0.2-50. Very low values (under 1.5) use the slow nudge controls. |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Flying along <n> point(s) to <x>, <y>, <z>" |
Bot.alwaysRun(enable)
Turns always-run on or off. While on, walkTo and moveTo run instead of walk. Switches flying off.
Usage
Bot.alwaysRun(true).then(function (res) {
console.log("alwaysRun response:", res);
});Or using async/await:
let res = await Bot.alwaysRun(true);
console.log("alwaysRun response:", res);Input
| Variable | Required | Description |
|---|---|---|
enable | no | true to run, false to walk again (default true) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.autoMove(x, y, z)
Obstacle-aware navigation to a position in the current region: plans a route around walls and furniture from the objects the bot can see, and climbs stairs and ramps. Runs in the background; a new autoMove, autoMoveStop or any other movement command cancels it. Falls back to a straight walk if no route is found.
Usage
Bot.autoMove(140, 90, 25).then(function (res) {
console.log("autoMove response:", res);
});Or using async/await:
let res = await Bot.autoMove(140, 90, 25);
console.log("autoMove response:", res);Input
| Variable | Required | Description |
|---|---|---|
x | yes | Target X in region |
y | yes | Target Y in region |
z | yes | Target Z (height) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
message | string | "automove started to (x,y,z)" |
Bot.autoRun(x, y, z)
Same as autoMove, but runs along the route.
Usage
Bot.autoRun(140, 90, 25).then(function (res) {
console.log("autoRun response:", res);
});Or using async/await:
let res = await Bot.autoRun(140, 90, 25);
console.log("autoRun response:", res);Input
| Variable | Required | Description |
|---|---|---|
x | yes | Target X in region |
y | yes | Target Y in region |
z | yes | Target Z (height) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
message | string | "automove started to (x,y,z)" |
Bot.autoMoveStop()
Cancels a running autoMove / autoRun.
Usage
Bot.autoMoveStop().then(function (res) {
console.log("autoMoveStop response:", res);
});Or using async/await:
let res = await Bot.autoMoveStop();
console.log("autoMoveStop response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.turnTo(deg)
Turns the bot to face a heading (0-360 degrees). Resolved client-side by projecting a look-at point ahead of the bot (two RPCs: bot_location then lookat).
Usage
Bot.turnTo(90).then(function (res) {
console.log("turnTo response:", res);
});Or using async/await:
let res = await Bot.turnTo(90);
console.log("turnTo response:", res);Input
| Variable | Required | Description |
|---|---|---|
deg | yes | Heading in degrees, 0-360 |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
heading | number | The heading the bot turned to (on success) |
Bot.avatarInfo(uuid)
Returns the Second Life avatar profile details.
Usage
Bot.avatarInfo('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("avatarInfo response:", res);
});Or using async/await:
let res = await Bot.avatarInfo('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("avatarInfo response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | UUID of the avatar to query |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
about | string | Profile (About) text |
born | string | SL birth date, MM/DD/YYYY |
identified | number | 1 if the avatar has payment info on file |
image | string | Profile image texture UUID |
first_life_image | string | First-life image texture UUID |
first_life_text | string | First-life profile text |
mature | number | 1 if the profile is mature |
online | number | 1 if the avatar is online |
partner | string | Partner avatar UUID (zero UUID if none) |
publish_web | number | 1 if the profile may be published on the web |
transacted | number | 1 if payment info has been used |
url | string | Profile URL |
Example response
{
"success": true,
"about": "Builder, scripter, explorer.",
"born": "03/14/2009",
"identified": 1,
"image": "aaaaaaaa-...",
"first_life_image": "00000000-0000-0000-0000-000000000000",
"first_life_text": "",
"mature": 0,
"online": 1,
"partner": "00000000-0000-0000-0000-000000000000",
"publish_web": 1,
"transacted": 1,
"url": ""
}Limitations
Not intended for mass parsing — takes ~2-3 seconds per call and repeated requests (more than ~1 per 3 seconds) may be throttled. Excessive non-stop requests can cause the bot to relog.
Bot.key2name(key)
Resolves a UUID to an SL name.
Usage
Bot.key2name('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("key2name response:", res);
});Or using async/await:
let res = await Bot.key2name('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("key2name response:", res);Input
| Variable | Required | Description |
|---|---|---|
key | yes | Avatar UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
key | string | The UUID that was queried |
name | string | Resolved SL name |
Example response
{
"success": true,
"key": "0b65a122-8f77-64fe-5b2a-225d4c490d9c",
"name": "Resident Name"
}Bot.name2key(slname)
Resolves an SL name to a UUID.
Usage
Bot.name2key('First Last').then(function (res) {
console.log("name2key response:", res);
});Or using async/await:
let res = await Bot.name2key('First Last');
console.log("name2key response:", res);Input
| Variable | Required | Description |
|---|---|---|
slname | yes | Avatar name ("First Last") |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
name | string | The name that was queried |
key | string | Resolved avatar UUID |
normalname | string | Normalized name |
Example response
{
"success": true,
"name": "First Last",
"key": "0b65a122-8f77-64fe-5b2a-225d4c490d9c",
"normalname": "first.last"
}Bot.offerTeleport(avatar, message)
Sends a teleport offer to an avatar.
Usage
Bot.offerTeleport('avatar-uuid', 'Join me').then(function (res) {
console.log("offerTeleport response:", res);
});Or using async/await:
let res = await Bot.offerTeleport('avatar-uuid', 'Join me');
console.log("offerTeleport response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID or name |
message | no | Offer message (default "Join me") |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Bot.acceptTeleportOffer(avatar_uuid, session_id, accept)
Accepts or rejects a teleport offer (see the teleport_offer event).
Usage
Bot.acceptTeleportOffer('avatar-uuid', 'session-uuid', true).then(function (res) {
console.log("acceptTeleportOffer response:", res);
});Or using async/await:
let res = await Bot.acceptTeleportOffer('avatar-uuid', 'session-uuid', true);
console.log("acceptTeleportOffer response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar_uuid | yes | Offering avatar UUID |
session_id | yes | Session id from the teleport_offer event |
accept | no | true to accept, false to reject (default true) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Teleport offer accepted" or "Teleport offer declined" |
Bot.isMyOwner(slNameOrUUID)
Returns a bare boolean — true if the avatar is the bot's owner. Resolved client-side (accepts UUID or name).
Usage
Bot.isMyOwner('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("isMyOwner response:", res);
});Or using async/await:
let res = await Bot.isMyOwner('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("isMyOwner response:", res);Input
| Variable | Required | Description |
|---|---|---|
slNameOrUUID | yes | Avatar UUID or name to test |
Output
| Field | Type | Description |
|---|---|---|
| (return value) | bool | true if the avatar is the bot's owner |
Bot.isMyManager(slNameOrUUID)
Returns a bare boolean — true if the avatar is a trusted manager of the bot. Resolved client-side.
Usage
Bot.isMyManager('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("isMyManager response:", res);
});Or using async/await:
let res = await Bot.isMyManager('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("isMyManager response:", res);Input
| Variable | Required | Description |
|---|---|---|
slNameOrUUID | yes | Avatar UUID or name to test |
Output
| Field | Type | Description |
|---|---|---|
| (return value) | bool | true if the avatar is a trusted manager |
Bot.checkScriptedAgent(slNameOrUUID)
Returns a bare boolean — true if the avatar is a registered LifeBots bot (exists in the shared bots collection). Use to avoid bot-to-bot loops. Resolved client-side via a Mongo lookup.
Usage
Bot.checkScriptedAgent('0b65a122-8f77-64fe-5b2a-225d4c490d9c').then(function (res) {
console.log("checkScriptedAgent response:", res);
});Or using async/await:
let res = await Bot.checkScriptedAgent('0b65a122-8f77-64fe-5b2a-225d4c490d9c');
console.log("checkScriptedAgent response:", res);Input
| Variable | Required | Description |
|---|---|---|
slNameOrUUID | yes | Avatar UUID or name to test |
Output
| Field | Type | Description |
|---|---|---|
| (return value) | bool | true if the avatar is a registered LifeBots bot |
Bot.scanNearbyAvatars()
Scans avatars in the bot's current region.
Usage
Bot.scanNearbyAvatars().then(function (res) {
console.log("scanNearbyAvatars response:", res);
});Or using async/await:
let res = await Bot.scanNearbyAvatars();
console.log("scanNearbyAvatars response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
avatars | array | Array of avatar objects (see below) |
avatars[].name | string | Avatar name |
avatars[].uUID | string | Avatar UUID. NOTE the casing quirk: the key is uUID (camelKeys lowercases only the first char) |
avatars[].position | object | Position in the region { x, y, z } — correct also while the avatar sits (use this one) |
avatars[].localPosition | object | Raw position { x, y, z } — relative to the seat while the avatar sits |
avatars[].heading | number | Facing direction in degrees, counter-clockwise from east (0 = east, 90 = north) |
avatars[].localHeading | number | Same as heading |
avatars[].distance | number | Distance from the bot (metres) |
avatars[].parcelID | number | Parcel local id |
avatars[].sitting | bool | true if the avatar is sitting |
avatars[].seenSince | string | ISO timestamp first seen |
avatars[].seenSeconds | number | Seconds since first seen |
Example response
{
"success": true,
"avatars": [
{
"name": "Resident One",
"uUID": "11111111-2222-3333-4444-555555555555",
"position": {
"x": 130,
"y": 64,
"z": 25
},
"localPosition": {
"x": 130,
"y": 64,
"z": 25
},
"heading": 45,
"localHeading": 45,
"distance": 3.2,
"parcelID": 12,
"sitting": false,
"seenSince": "2026-06-16T12:00:00.000Z",
"seenSeconds": 42
}
]
}Bot.trackAvatars(avatars)
Tracks one or more avatars; position updates fire as avatar_tracker_update events. Pass "" (or no args) to stop tracking.
Usage
Bot.trackAvatars(['11111111-2222-3333-4444-555555555555']).then(function (res) {
console.log("trackAvatars response:", res);
});Or using async/await:
let res = await Bot.trackAvatars(['11111111-2222-3333-4444-555555555555']);
console.log("trackAvatars response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatars | yes | Space-separated UUID string or array of UUIDs. Empty string stops tracking |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
tracking | number | Number of avatars now being tracked |
Bot.touchPrim(uuid)
Touches an in-world prim.
Usage
Bot.touchPrim('prim-uuid').then(function (res) {
console.log("touchPrim response:", res);
});Or using async/await:
let res = await Bot.touchPrim('prim-uuid');
console.log("touchPrim response:", res);Input
| Variable | Required | Description |
|---|---|---|
uuid | yes | Prim UUID to touch |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Touched" |
Bot.touchAttachment(objectName, linkNumber)
Touches one of the bot's own attachments by name + link number.
Usage
Bot.touchAttachment('My HUD', 2).then(function (res) {
console.log("touchAttachment response:", res);
});Or using async/await:
let res = await Bot.touchAttachment('My HUD', 2);
console.log("touchAttachment response:", res);Input
| Variable | Required | Description |
|---|---|---|
objectName | yes | Attachment object name |
linkNumber | no | Link number within the attachment |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
name | string | Name of the touched attachment |
uuid | string | UUID of the touched attachment |
Bot.takeInworldPrim(operation, objectUUID, folderUUID)
Takes or copies an in-world prim into inventory.
Usage
Bot.takeInworldPrim('take', 'prim-uuid').then(function (res) {
console.log("takeInworldPrim response:", res);
});Or using async/await:
let res = await Bot.takeInworldPrim('take', 'prim-uuid');
console.log("takeInworldPrim response:", res);Input
| Variable | Required | Description |
|---|---|---|
operation | no | "take" or "copy" (default "take") |
objectUUID | yes | Prim UUID |
folderUUID | no | Destination folder UUID |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Prim <operation> requested" |
Bot.regionRestart(delay)
Restarts the current region (requires estate-manager privileges).
Usage
Bot.regionRestart(120).then(function (res) {
console.log("regionRestart response:", res);
});Or using async/await:
let res = await Bot.regionRestart(120);
console.log("regionRestart response:", res);Input
| Variable | Required | Description |
|---|---|---|
delay | no | Seconds before restart, typically 30-240 (default 120) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Region restart initiated (<delay>s delay)" |
Bot.regionRestartCancel()
Cancels a pending region restart.
Usage
Bot.regionRestartCancel().then(function (res) {
console.log("regionRestartCancel response:", res);
});Or using async/await:
let res = await Bot.regionRestartCancel();
console.log("regionRestartCancel response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
resulttext | string | "Region restart cancelled" |
Bot.estateKick(avatar)
Kicks an avatar out of the current region. Use for offenders who are not group members (e.g. spam in local chat).
Usage
Bot.estateKick('avatar-uuid').then(function (res) {
console.log("estateKick response:", res);
});Or using async/await:
let res = await Bot.estateKick('avatar-uuid');
console.log("estateKick response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID to kick from the region |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world; the simulator enforces this. No addon required.
Bot.estateBan(avatar, allEstates)
Adds an avatar to the estate ban list (kicks them if present).
Usage
Bot.estateBan('avatar-uuid').then(function (res) {
console.log("estateBan response:", res);
});Or using async/await:
let res = await Bot.estateBan('avatar-uuid');
console.log("estateBan response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID to ban |
allEstates | no | true = apply to every estate the bot manages (default false = this estate only) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world.
Bot.estateUnban(avatar, allEstates)
Removes an avatar from the estate ban list.
Usage
Bot.estateUnban('avatar-uuid').then(function (res) {
console.log("estateUnban response:", res);
});Or using async/await:
let res = await Bot.estateUnban('avatar-uuid');
console.log("estateUnban response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID to unban |
allEstates | no | true = apply to every estate the bot manages (default false = this estate only) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world.
Bot.teleportHomeUser(avatar)
Sends an avatar back to their home location. Gentler than a kick — they stay in-world.
Usage
Bot.teleportHomeUser('avatar-uuid').then(function (res) {
console.log("teleportHomeUser response:", res);
});Or using async/await:
let res = await Bot.teleportHomeUser('avatar-uuid');
console.log("teleportHomeUser response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID to send home |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world.
Bot.teleportHomeAll()
Sends every non-estate-manager avatar in the region back to their home location.
Usage
Bot.teleportHomeAll().then(function (res) {
console.log("teleportHomeAll response:", res);
});Or using async/await:
let res = await Bot.teleportHomeAll();
console.log("teleportHomeAll response:", res);Input
None.
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world.
Bot.parcelEject(avatar, ban)
Ejects an avatar from the current parcel. Works with parcel (owner/manager) rights rather than estate rights.
Usage
Bot.parcelEject('avatar-uuid').then(function (res) {
console.log("parcelEject response:", res);
});Or using async/await:
let res = await Bot.parcelEject('avatar-uuid');
console.log("parcelEject response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Avatar UUID to eject from the parcel |
ban | no | true = also add them to the parcel ban list (default false = eject only) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold parcel owner/manager rights in-world.
Bot.regionMessage(message, allEstates)
Sends a blue-box message to everyone in the region (or across the estate).
Usage
Bot.regionMessage('Please keep the region friendly.').then(function (res) {
console.log("regionMessage response:", res);
});Or using async/await:
let res = await Bot.regionMessage('Please keep the region friendly.');
console.log("regionMessage response:", res);Input
| Variable | Required | Description |
|---|---|---|
message | yes | The message text |
allEstates | no | true = broadcast to the whole estate (default false = current region only) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world.
Bot.returnObjects(avatar, includeOthersLand)
Sim-wide return of an avatar's scripted objects to their owner.
Usage
Bot.returnObjects('avatar-uuid').then(function (res) {
console.log("returnObjects response:", res);
});Or using async/await:
let res = await Bot.returnObjects('avatar-uuid');
console.log("returnObjects response:", res);Input
| Variable | Required | Description |
|---|---|---|
avatar | yes | Owner UUID whose objects to return |
includeOthersLand | no | true = also return objects sitting on other people's land (default false) |
Output
| Field | Type | Description |
|---|---|---|
success | bool | true if the command completed successfully |
error | string | error string if the command has failed |
Limitations
The bot must hold estate-manager rights in-world.
chat_message
Local chat message received.
Usage
Bot.on('chat_message', m => console.log(m.speakerName, m.message));Payload fields
| Field | Type | Description |
|---|---|---|
speakerName | string | Speaker's name |
speakerUuid | string | Speaker's UUID |
speakerType | string | Speaker type |
ownerUuid | string | Owner UUID if speaker is an object |
message | string | Chat text |
timestamp | Date | When received |
instant_message
IM received.
Usage
Bot.on('instant_message', async im => { await Bot.im(im.senderUuid, 'hi'); });Payload fields
| Field | Type | Description |
|---|---|---|
senderName | string | Sender's name |
senderUuid | string | Sender's UUID |
senderType | string | 'AGENT' or 'OBJECT' |
ownerUuid | string | Owner UUID if sender is an object |
message | string | IM text |
timestamp | Date | When received |
group_im
Group chat message.
Usage
Bot.on('group_im', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
groupUuid | string | Group UUID |
groupName | string | Group name |
senderName | string | Sender name |
senderUuid | string | Sender UUID |
isModerator | bool | true if sender is a moderator |
message | string | Message text |
timestamp | Date | When received |
group_notice
Group notice received.
Usage
Bot.on('group_notice', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
groupUuid | string | Group UUID |
groupName | string | Group name |
subject | string | Notice subject |
message | string | Notice body |
senderName | string | Sender name |
senderUuid | string | Sender UUID |
group_offer
Group invite received.
Usage
Bot.on('group_offer', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
sessionId | string | Use with acceptGroupOffer |
groupUuid | string | Group UUID |
groupName | string | Group name |
avatarName | string | Inviting avatar name |
avatarUuid | string | Inviting avatar UUID |
message | string | System message |
friendship_offer
Friendship request received.
Usage
Bot.on('friendship_offer', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
sessionId | string | Use with acceptFriendshipOffer |
avatarName | string | Offering avatar name |
avatarUuid | string | Offering avatar UUID |
message | string | Offer message |
inventory_offer
Inventory offer received.
Usage
Bot.on('inventory_offer', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
sessionId | string | Use with acceptInventoryOffer |
avatarName | string | Sender name |
avatarUuid | string | Sender UUID |
itemName | string | Offered item name |
itemType | string | Offered item type |
teleport_offer
Teleport offer received.
Usage
Bot.on('teleport_offer', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
sessionId | string | Use with acceptTeleportOffer |
avatarName | string | Offering avatar name |
avatarUuid | string | Offering avatar UUID |
message | string | Offer message |
teleport_status
Teleport progress.
Usage
Bot.on('teleport_status', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
status | string | Teleport stage |
message | string | Status message |
flags | any | Teleport flags |
location | any | Destination info |
script_dialog
Script dialog with menu received.
Usage
Bot.on('script_dialog', async d => { await Bot.replyDialog(d.channel, d.objectUuid, d.buttons[0]); });Payload fields
| Field | Type | Description |
|---|---|---|
channel | string|number | Reply channel (pass to replyDialog) |
objectName | string | Object name |
objectUuid | string | Object UUID (pass to replyDialog) |
ownerUuid | string | Object owner UUID |
message | string | Dialog text |
buttons | string[] | Button labels |
balance_changed
L$ balance changed.
Usage
Bot.on('balance_changed', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
amount | number | Transaction amount |
direction | string | in / out |
source | string | Source UUID/name |
destination | string | Destination UUID/name |
balance | number | New balance |
transactionType | string | Transaction type |
description | string | Description |
transactionId | string | Transaction id |
timestamp | any | When it occurred |
start_typing
Avatar started typing.
Usage
Bot.on('start_typing', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
avatarName | string | Avatar name |
avatarUuid | string | Avatar UUID |
stop_typing
Avatar stopped typing.
Usage
Bot.on('stop_typing', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
avatarName | string | Avatar name |
avatarUuid | string | Avatar UUID |
region_restart
Region restart announced.
Usage
Bot.on('region_restart', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
region | string | Region name |
secondsRemaining | number | Seconds until restart |
region_restart_cancelled
Region restart cancelled.
Usage
Bot.on('region_restart_cancelled', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
region | string | Region name |
sit
Bot sat on or stood from an object.
Usage
Bot.on('sit', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
sitting | bool | true if now sitting |
objectUuid | string | Object UUID (empty when standing) |
self_position
Bot moved or turned (>1m or >5deg).
Usage
Bot.on('self_position', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
region | string | Region name |
x | number | X position |
y | number | Y position |
z | number | Z position |
heading | number | Facing direction in degrees, counter-clockwise from east (0 = east, 90 = north) |
autopilot_started
WalkTo/MoveTo began.
Usage
Bot.on('autopilot_started', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
x | number | Target X |
y | number | Target Y |
z | number | Target Z |
autopilot_completed
Bot reached its destination.
Usage
Bot.on('autopilot_completed', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
x | number | Final X |
y | number | Final Y |
z | number | Final Z |
autopilot_stuck
Bot stopped making progress (>10s).
Usage
Bot.on('autopilot_stuck', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
x | number | Current X |
y | number | Current Y |
z | number | Current Z |
remainingDistance | number | Distance left to target |
avatar_tracker_update
Update for a tracked avatar (after Bot.trackAvatars). Checked every 0.5 s; fires only when something changed: moved more than 0.1 m, turned more than 5°, sat or stood, changed region, or appeared/disappeared. A standing, unmoving avatar sends nothing, so keep using the last update.
Usage
Bot.on('avatar_tracker_update', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
name | string | 'avatar_tracker_update' |
bot_slname | string | Tracking bot's name |
bot_uuid | string | Tracking bot's UUID |
avatar_name | string|null | Tracked avatar name |
avatar_uuid | string | Tracked avatar UUID |
region | string|null | Region name |
regionHandle | any|null | Region handle |
position | object|null | {X,Y,Z} in the region (also while sitting); null when not visible |
velocity | object|null | {X,Y,Z}; null when not visible |
heading | number|null | Facing direction in RADIANS, counter-clockwise from east (0 = east, π/2 = north); null when not visible |
sitting | bool | true if sitting |
timestamp | number|null | Update time (Unix milliseconds) |
event_version | number | Event schema version |
version | string | Version string |
workshop_webhook
External HTTP request hit the script's allocated webhook URL (from http.requestWebhookUrl()).
Usage
const hook = await http.requestWebhookUrl(); Bot.on('workshop_webhook', e => console.log(e.payload));Payload fields
| Field | Type | Description |
|---|---|---|
name | string | 'workshop_webhook' |
bot_slname | string | Bot name |
hookId | string | Webhook id from the URL |
correlationId | string | Echoed in the HTTP response too |
payload | object|string | Parsed JSON body, or raw string for text/plain; {} for invalid/empty JSON |
before_login
Bot is logging in (CONNECTING).
Usage
Bot.on('before_login', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
status | string | Status code |
region | string|null | Region |
position | any|null | Position |
error | string|null | Error (login_error only) |
timestamp | Date | When |
after_login
Bot logged in (ONLINE).
Usage
Bot.on('after_login', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
status | string | Status code |
region | string|null | Region |
position | any|null | Position |
error | string|null | Error (login_error only) |
timestamp | Date | When |
before_logout
Bot is logging out (LOGGING_OUT).
Usage
Bot.on('before_logout', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
status | string | Status code |
region | string|null | Region |
position | any|null | Position |
error | string|null | Error (login_error only) |
timestamp | Date | When |
after_logout
Bot logged out (LOGGED_OUT).
Usage
Bot.on('after_logout', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
status | string | Status code |
region | string|null | Region |
position | any|null | Position |
error | string|null | Error (login_error only) |
timestamp | Date | When |
login_error
Login failed (LOGIN_ERROR); error is populated.
Usage
Bot.on('login_error', (e) => {
console.log(e);
});Payload fields
| Field | Type | Description |
|---|---|---|
status | string | Status code |
region | string|null | Region |
position | any|null | Position |
error | string|null | Failure reason |
timestamp | Date | When |
Bot.AI.chat(message, opts)
One-shot AI completion with no memory. The model is chosen in the Bot.AI panel; instructions/temperature/maxTokens come from configure() defaults or this call's opts.
Usage
Bot.AI.chat('Summarize Second Life in one sentence.', { temperature: 0.5, maxTokens: 100 }).then(function (res) {
console.log("chat response:", res);
});Or using async/await:
let res = await Bot.AI.chat('Summarize Second Life in one sentence.', { temperature: 0.5, maxTokens: 100 });
console.log("chat response:", res);Input
| Variable | Required | Description |
|---|---|---|
message | yes | The prompt text |
opts | no | { model?, instructions?, temperature?, maxTokens? } — overrides run defaults for this call |
Returns
Promise<{ text, model, tokens, cost }>
Output fields
| Field | Type | Description |
|---|---|---|
text | string | The model's reply text |
model | string | Model that produced the reply |
tokens | object | { input, output, total } token counts |
cost | number | Cost deducted from the owner's AI credits |
Bot.AI.configure(opts)
Override the run-level Bot.AI defaults applied to subsequent chat() calls.
Usage
Bot.AI.configure({ instructions: 'You are a friendly SL assistant.', temperature: 0.7, maxTokens: 300 }).then(function (res) {
console.log("configure response:", res);
});Or using async/await:
let res = await Bot.AI.configure({ instructions: 'You are a friendly SL assistant.', temperature: 0.7, maxTokens: 300 });
console.log("configure response:", res);Input
| Variable | Required | Description |
|---|---|---|
opts | yes | { model?, instructions?, temperature?, maxTokens? } |
Returns
Promise<{ ok, defaults }>
Bot.AI.getConversationByName(residentName)
Returns a Conversation object (synchronously) with per-resident memory that persists for the run only. The Conversation exposes chat(message, opts?) (same return shape as Bot.AI.chat, with memory), configure(opts), and forget().
Usage
const conv = Bot.AI.getConversationByName(im.senderName);
const r = await conv.chat(im.message);
await Bot.im(im.senderUuid, r.text);Input
| Variable | Required | Description |
|---|---|---|
residentName | yes | A name/key to scope the conversation memory |
Returns
Conversation { chat(message, opts?), configure(opts), forget() }
Bot.AI.forgetConversation(residentName)
Clears an in-memory conversation.
Usage
Bot.AI.forgetConversation('First Last').then(function (res) {
console.log("forgetConversation response:", res);
});Or using async/await:
let res = await Bot.AI.forgetConversation('First Last');
console.log("forgetConversation response:", res);Input
| Variable | Required | Description |
|---|---|---|
residentName | yes | Conversation name to clear |
Returns
Promise<{ ok, removed }>
Bot.AI.listConversations()
Lists active conversations and their message counts.
Usage
Bot.AI.listConversations().then(function (res) {
console.log("listConversations response:", res);
});Or using async/await:
let res = await Bot.AI.listConversations();
console.log("listConversations response:", res);Input
None.
Returns
Promise<[{ name, messages }]>
Hello, world
Send a chat message and exit.
Script
console.log(`${process.name} started`);
await Bot.say(0, 'Hello from the workshop');
process.exit();Echo IMs
Reply to every IM the bot receives.
Script
console.log('Listening for IMs…');
Bot.on('instant_message', async (im) => {
console.log(`IM from ${im.senderName}: ${im.message}`);
await Bot.im(im.senderUuid, `You said: ${im.message}`);
});Greet on local chat
Wave hello when someone speaks in nearby chat.
Script
const greeted = new Set();
Bot.on('chat_message', async (msg) => {
if (greeted.has(msg.speakerUuid)) return;
greeted.add(msg.speakerUuid);
console.log(`First message from ${msg.speakerName}`);
await Bot.say(0, `Hi ${msg.speakerName}!`);
});Scan nearby avatars
List avatars in the bot’s current region.
Script
console.log(`${process.name} started`);
const result = await Bot.scanNearbyAvatars();
console.log(`Avatars arrived: (${JSON.stringify(result).length} bytes)`);
if (!result.success) {
console.log('Error scanning avatars: ' + result.error);
} else if (!result.avatars || result.avatars.length === 0) {
console.log('No avatars found.');
} else {
for (const avatar of result.avatars) {
console.log(`${avatar.name}: seen for ${avatar.seenSeconds} seconds`);
}
}
process.exit();Login lifecycle
Watch the bot’s login/logout events.
Script
Bot
.on('before_logout', () => console.log('Bot is logging out'))
.on('before_login', () => console.log('Bot is logging in'))
.on('after_login', () => console.log('Bot has logged in'))
.on('login_error', (e) => console.log('Login error: ' + e.error));
console.log('Watching login lifecycle. Trigger from the LifeBots dashboard.');localStorage usage
Persist counters across script restarts.
Script
const prevRaw = await localStorage.get('runs');
const prev = prevRaw ? parseInt(prevRaw, 10) : 0;
const next = prev + 1;
await localStorage.set('runs', String(next));
console.log(`This script has been run ${next} time(s).`);
const keys = await localStorage.keys();
console.log('Stored keys:', keys);
process.exit();Walk to a position
Move the bot to a specific spot in the current region.
Script
const x = 128, y = 128, z = 25;
console.log(`Walking to (${x}, ${y}, ${z})…`);
const r = await Bot.walkTo(x, y, z);
console.log('walkTo response:', r);HTTP GET
Fetch a URL and log the response.
Script
const r = await http.get('https://httpbin.org/get');
console.log('status:', r.status);
console.log('body sample:', r.body.slice(0, 200));
process.exit();AI chat bot
Reply to IMs with OpenRouter-backed AI. Remembers per-resident context.
Script
// Bot.AI uses your OpenRouter key from node-web AI settings.
// The model is picked in the Bot.AI panel above (per-script / per-buyer).
// Everything else — instructions, temperature, max tokens — is controlled
// here in code. If you want the buyer to tune those, expose them via
// userSettings (the userSettings ▾ button next to Bot.AI) and read them
// below; otherwise just hardcode whatever suits the bot.
Bot.AI.configure({
instructions: userSettings.systemPrompt ||
'You are a friendly Second Life assistant. Keep replies under 200 characters.',
temperature: parseFloat(userSettings.temperature) || 0.7,
maxTokens: parseInt(userSettings.maxTokens, 10) || 300,
});
console.log('AI chat ready. Send the bot an IM.');
Bot.on('instant_message', async (im) => {
// checkScriptedAgent avoids replying to other bots and getting into a loop.
if (await Bot.checkScriptedAgent(im.senderUuid)) return;
// One conversation per resident — memory persists for this run only.
const conv = Bot.AI.getConversationByName(im.senderName);
try {
await Bot.startTyping(im.senderUuid);
const r = await conv.chat(im.message);
await Bot.im(im.senderUuid, r.text);
console.log(`[${r.model}] ${im.senderName}: ${r.text} (${r.tokens.total} tok, $${r.cost.toFixed(5)})`);
} catch (e) {
console.error('AI failed:', e.message);
await Bot.im(im.senderUuid, 'Sorry, I had trouble responding.');
} finally {
await Bot.stopTyping(im.senderUuid);
}
});Limits
Runtime caps. Defaults shown; overridable via settings.workshop.limits.
| Limit | Default |
|---|---|
maxOldGenerationMb | 256 |
maxConcurrentRunsPerUser | 10 |
scriptStartTimeoutMs | 30000 |
eventHandlerTimeoutMs | 5000 |
cpuBudgetMs | 5000 |
cpuMonitorIntervalMs | 10000 |
consoleLinesPerSecond | 100 |
consoleMaxRetainedLines | 500 |
botCommandsPerSecond | 30 |
botCommandBurst | 60 |
localStorageMaxBytes | 1048576 |
localStorageMaxKeys | 500 |
httpTimeoutMs | 15000 |
httpCallsPerMinute | 60 |
httpMaxResponseBytes | 5242880 |
webhookHitsPerMinute | 120 |
aiCallsPerMinute | 30 |
aiMaxTokensCap | 2048 |
aiRequestTimeoutMs | 45000 |
aiMaxConversations | 20 |
aiMaxMessagesPerConversation | 50 |