Advanced Eventing and Reactive Workflows¶
This page covers the MCP runtime event stream tools for automation loops, watchers, and controller bots.
Why use the event tools¶
Polling action tools directly is expensive and race-prone. The event stream gives you:
- a normalized event envelope across runtime sources
- cursor-based continuation
- bounded buffers with explicit trim diagnostics
- channel separation for high-volume signals
Tools¶
EventStreamSubscribe(channels, eventTypes, radiusMeters, objectIds, objectLocalIds, chatSources)EventStreamPoll(subscriptionId, cursor, channels, eventTypes, radiusMeters, objectIds, objectLocalIds, chatSources, maxResults, waitMs)EventStreamHistory(lastSeconds, channels, eventTypes, radiusMeters, objectIds, objectLocalIds, chatSources, maxResults)EventStreamUnsubscribe(subscriptionId)EventStreamStats()ObjectMonitorSimOrPrim(regionHandle, primId, children, terseUpdateEvent, fullUpdateEvent)ListObjectMonitors()CloseObjectMonitor(monitorHandle)
Runtime model¶
Channels¶
general: login/disconnect/chat/inventory-offer/script-dialog and similar lifecycle eventsobject: object update stream (high-volume, monitor-gated)teleport: teleport success/failure stream
all is accepted when creating or overriding channels.
Cursor semantics¶
- Cursors are monotonic event IDs.
EventStreamPollreturnsnextCursor; use it as the next call'scursor.- Subscriptions persist their own cursor; omit
cursorto use stored state.
Long-poll (hybrid default)¶
Set waitMs > 0 to block briefly for new events while retaining cursor replay behavior.
Recommended baseline:
maxResults:50to200waitMs:3000to10000
Object monitor gating¶
Object channel updates are disabled by default. Subscribing to object alone does not emit object updates until at least one monitor is active.
Use monitor tools to control object event emission:
ObjectMonitorSimOrPrim: add one monitor spec and get a monitor handleListObjectMonitors: inspect active monitor specsCloseObjectMonitor: remove one monitor by handle, or remove all with empty/null handle
Monitor matching fields:
regionHandle:0means all regionsprimId:0means all primschildren: when true, child prim updates ofprimIdalso matchterseUpdateEvent/fullUpdateEvent: choose terse/full object update types
Backpressure and trimming¶
Buffers are bounded per channel. When full, the oldest events are trimmed.
Use these fields to detect and handle loss:
CursorTrimmedTrimmedTotalTrimmedGeneralTrimmedObjectTrimmedTeleport
Recovery pattern after trim:
- Record that loss occurred (metrics/log).
- Continue from returned
nextCursor. - Optionally trigger a state reconciliation pass (inventory/object snapshot tools) before resuming normal loops.
Event type filtering¶
eventTypes accepts a delimited list (comma/space/pipe). Keep filters narrow for high-volume workflows.
Common patterns:
- only failures:
teleport.failed,network.disconnected - chat-focused:
chat.im.received,chat.local.received - lifecycle:
login.success,login.failed,login.connected,network.disconnected - scripted dialogs:
script.dialog.received
Script dialog workflow¶
When a scripted object opens a dialog for the bot, runtime emits script.dialog.received on general.
The event attributes include a pendingDialogHandle plus object/owner metadata and button labels.
Typical handling loop:
- Poll
general(or filteredeventTypes="script.dialog.received"). - Read
pendingDialogHandlefrom the event. - Call
ListScriptDialogs(pendingDialogHandle="<handle>")to inspect message/buttons. - Reply with
ScriptDialogChoice(pendingDialogHandle="<handle>", buttonIndex=<n>). - Use
buttonIndex=-1to cancel/remove a pending dialog without clicking any button.
Attribute filters¶
radiusMeters: retain only events near current bot position (events without coordinates are excluded)objectIds: UUID filter for object-related eventsobjectLocalIds: local ID filter for object-related eventschatSources: source name/UUID/source-type matching for chat events
For production, keep each consumer focused on one workload class (for example object watcher vs chat watcher).
History replay window¶
Use EventStreamHistory for short retained replay during debugging:
lastSecondsis clamped to a bounded short window- returns latest matching events in the requested window
- does not mutate subscription cursor state
Recommended topologies¶
1) Operator monitor¶
- Subscription A:
general - Filters: failures + disconnect + inventory decisions
- Poll: every
5slong-poll
2) Build/scene automation¶
- Subscription A:
object - Subscription B:
teleport - Add monitor specs first (for example one per target region/object) before polling object events.
- Keep object and teleport split to avoid starvation.
3) Conversation supervisor¶
- Subscription A:
general - Filters: chat + disconnect
- On disconnect, pause workflows and wait for reconnect events.
Example MCP call sequence¶
1) EventStreamSubscribe(channels="general", eventTypes="network.disconnected,teleport.failed", chatSources="Governor Bot")
2) EventStreamPoll(subscriptionId="<id>", maxResults=100, waitMs=5000)
3) EventStreamPoll(subscriptionId="<id>", cursor="<nextCursor>", maxResults=100, waitMs=5000)
4) ObjectMonitorSimOrPrim(regionHandle=0, primId=0, children=false, terseUpdateEvent=true, fullUpdateEvent=false)
5) EventStreamSubscribe(channels="object", maxResults=100)
6) EventStreamPoll(subscriptionId="<objectSubId>", maxResults=100, waitMs=5000)
7) EventStreamHistory(lastSeconds=120, channels="teleport", eventTypes="teleport.failed", maxResults=50)
8) ListObjectMonitors()
9) CloseObjectMonitor(monitorHandle="")
10) EventStreamStats()
11) EventStreamUnsubscribe(subscriptionId="<id>")
Operational notes¶
- Prefer multiple narrow subscriptions over one broad
allsubscription in production. - Run object-intensive consumers separately from human-facing chat consumers.
- Periodically sample
EventStreamStatsand alert on increasing trim counters. - Keep handler-side processing idempotent; duplicate-safe consumers are easier to recover.
Related pages¶
- Beginner Guide -> Event Workflows (
beginner/events.md) - Advanced Guide -> Hardening (
advanced/hardening.md) - Reference -> Components (
reference/components.md)