Hooks and Bus topics
Every hook point the framework fires and every Bus topic it publishes or consumes, with arguments, the module that fires it and its page.
Hooks ask permission and Bus topics announce facts. A hook point runs its handlers in priority order (lower first,
default 100, ties in registration order) over one shared, mutable context table. A handler that returns false
cancels the action. A handler that errors cancels it too, unless the point is defined FailOpen, and Hooks:fire
returns the traceback as a third value. A point with no handlers passes. A Bus subscriber receives (topic, ...) and
cannot cancel anything. Both registries create names on first use. The mechanics are on Hooks and
Bus.
Everything below comes from a Hooks:fire or Bus:publish call site in the v0.9.1 source. All hook points fire on the
server. Arguments are listed without the leading topic.
Hook points
Section titled “Hook points”Channel and session points
Section titled “Channel and session points”| Point | Context | Mode | Fired |
|---|---|---|---|
Intent.<Channel> |
{ Name, Player, Session, Args, Seq? } |
fail-closed | By NetDriver before every intent handler. Validators may rewrite Args; the handler and the Intent.<Channel> topic receive the result. A channel with no handler on this point and no Open = true rejects every payload. Seq is set for predicted intents. |
Request.<Channel> |
{ Name, Player, Session, Args } |
fail-closed | By NetDriver before every request handler. A rejection answers the client with the channel’s RejectValue. |
Intent.BusPublish.<Topic> |
{ Name, Player, Session, Args } |
fail-closed | By NetDriver when a client publishes a ClientTopics name through BusBridge. BusBridge defines these channels Open = true, so they pass unless a game handler vetoes. |
Intent.Settings_Set |
{ Name, Player, Session, Args, Acknowledged? } |
fail-closed | By NetDriver for the Settings_Set intent, and by Settings itself with Acknowledged = true for every Settings_Write request. The kit’s schema gate sits at priority 50. |
Session.Start |
{ Session, Player } |
observational | By the server kernel on join, before Kernel.SessionStart (Sessions). The verdict is ignored. |
Session.End |
{ Session, Player, ExitReason } |
observational | By the server kernel on leave, before Kernel.SessionEnd. ExitReason is the Enum.PlayerExitReason from PlayerRemoving, or nil. |
Net.RateLimited |
{ Player, Channel } |
fail-open | By NetDriver when a channel’s token bucket rejects a message (Rate limiting). |
Net.FloodDetected |
{ Player, Bytes, PayloadBytes, BudgetBytes, Reason, Count } |
fail-open | By NetDriver once per player and reason per heartbeat window. Count is the drops in the window and PayloadBytes the bytes dropped. |
AntiExploit.MovementViolation |
{ Player, Session, Type, HorizontalSpeed, Displacement, Strikes } |
fail-open | By the Movement monitor when a sample fails. |
Intent.Interact |
{ Session, Player, Id, Instance, Prompt, Definition } |
fail-closed | By InteractionKit on every prompt trigger. The kit’s distance, line of sight and cooldown gate sits at priority 50. |
Intent.Checkpoint |
{ Session, Player, Stage, Pad } |
fail-closed | By CheckpointKit on a pad touch. The kit’s stage order, minimum time and reach gate sits at priority 50. |
Kit channels are ordinary intents, so their points follow the Intent.<Channel> shape: Intent.WK_Fire,
Intent.SK_Cast, Intent.ML_Attack, Intent.INV_Use, Intent.CR_Craft, Intent.SH_Buy, Intent.CP_Summon,
Intent.PT_Invite, Intent.DLG_Choose, Intent.CKMove, Intent.PR_Report and the rest; requests use Request.<Channel>,
such as Request.INV_Fetch. Each kit registers its own gate at priority 50,
Registry Validate rules compile to handlers at priority 5, and game rules go at any other
priority.
Kit gates
Section titled “Kit gates”Policy gates that kits fire before acting on a request that already passed its channel validation. They are fail-open
on purpose: they carry game rules (safe zones, friendly fire, tournament locks), and a crashing rule should not stop the
kit. Return false to veto.
| Point | Context | Mode | Fired |
|---|---|---|---|
Inventory.CanEquip |
{ Session, Id, SlotName } |
fail-open | By InventoryKit before an equip changes the bag. |
Inventory.CanUse |
{ Session, Id, SlotIndex } |
fail-open | By InventoryKit before an item’s OnUse runs. The slot is locked while the chain runs. |
Craft.CanCraft |
{ Session, RecipeId, Station } |
fail-open | By CraftingKit before inputs are taken. Verify the claimed station here. A veto returns Vetoed. |
Companion.CanSummon |
{ Session, CompanionId } |
fail-open | By CompanionKit before a summon. Gate ownership here. |
Party.CanInvite |
{ From, To, Platform? } |
fail-open | By PartyKit before an invite, and with Platform = true before a player joins the party of their Roblox platform party. |
Melee.CanHit |
{ Attacker, Victim, Attack } |
fail-open | By MeleeKit for every hit-frame candidate. TeamKit registers its friendly-fire veto at priority 40. |
Weapon.CanDamage |
{ Session, Attacker, Victim, WeaponId, Weapon } |
fail-open | By WeaponKit before a validated shot deals damage. TeamKit vetoes at priority 40. |
Dialogue.CanBegin |
{ Session, Dialogue } |
fail-open | By DialogueKit before begin starts a conversation. |
Bus topics
Section titled “Bus topics”Kernel and sessions
Section titled “Kernel and sessions”| Topic | Arguments | Published |
|---|---|---|
Kernel.SessionStart |
(session) |
By the server kernel on join, after the Session.Start hook (Sessions). |
Kernel.SessionEnd |
(session, exitReason?) |
By the server kernel on leave, before the session is destroyed, so bound state is still readable. exitReason is the Enum.PlayerExitReason, also stored as session.ExitReason. |
Kernel.Closing |
(closeReason?) |
By the server kernel’s one BindToClose, before service stop() runs in reverse boot order with a 25 s budget (Kernel and boot). |
Kernel.Stopped |
(closeReason?) |
By the server kernel when the close stop phase ends, including when a stop() errored. DataDriver’s final saves wait for it, up to 5 s. |
Kernel.RestartScheduled |
(restartTime, source, attributes) |
By SoftShutdown from the engine’s ServerRestartScheduled event, where the engine has it. restartTime is a DateTime. |
Kernel.SoftShutdown |
(playerCount) |
By SoftShutdown before it moves everyone to a transit server. |
Kernel.ServiceRegistered |
(serviceName) |
By kernel:registerService on either side (Services). |
Kernel.Overload |
(snapshot) |
By kernel diagnostics when deferred work shows up three diagnostics windows in a row. |
Kernel.ScriptError |
(message, trace, source, count) |
By ErrorWatch for a new error or a repeat of a known one. |
Kernel.ProfileLoaded |
(session, profile) |
By DataDriver through Milestones when a player’s profile has loaded. Subscribe with Milestones.on to get it for profiles that loaded earlier. |
Kernel.ProfileRestored |
(session, profile) |
By DataDriver after Kernel.ProfileLoaded when the load restored a corrupt record from a native version (Version history) or a backup. |
| Topic | Arguments | Published |
|---|---|---|
Data.Throttled |
(key, errorText) |
By an attached DataDriver once per throttling episode, when a DataStore throttling error starts the wider retry spacing. |
Data.SaveRefused |
(key, reason) |
By DataDriver when a save cannot be written: Validate rejected it, a value cannot be serialized, the codec cannot hold it, or it is over the 4 MB value limit. The lock stays fresh so no other server loads the older record. |
Data.LockLost |
(key) |
By DataDriver when a save finds the session lock taken by another server. The player’s session ends here. See Handoff. |
Commerce
Section titled “Commerce”| Topic | Arguments | Published |
|---|---|---|
Commerce.PurchaseGranted |
(player, productId, purchaseId, purchaseChannel?, currencySpent?) |
By Receipts once per grant, after it has saved, including a grant that only the buyer’s leave save persisted (its redelivery announces it). purchaseChannel is the receipt’s ProductPurchaseChannel; currencySpent is the Robux actually paid, after Roblox Plus and other discounts. |
Commerce.PlusChanged |
(session, subscribed) |
By Pricing when the player’s Roblox Plus subscription starts or ends. session.RobloxPlus already holds the new value. |
Commerce.RobuxSpent |
(session, kind, id, amount, source) |
By Pricing once per purchase. kind is "Product" or "Pass"; source is "Receipt" (exact), "ClientQuote" (the player’s quoted pass price, capped at the list price), "ListPrice" or "UnverifiedQuote" (the list price stayed unreadable, so the quote is uncapped). Held until the buyer’s profile has loaded. |
Commerce.PassOwned |
(session, passId, name) |
By Passes once per owned pass per session, from the join lookup or an in-server purchase. |
Commerce.PassesResolved |
(session) |
By Passes through Milestones once every pass lookup for the session has finished. |
Commerce.TransactionEnded |
(profileA, profileB, ok) |
By Transactions when Transactions.atomic releases both profiles, whether or not the trade committed. |
Networking
Section titled “Networking”| Topic | Arguments | Published |
|---|---|---|
Intent.<Channel> |
(session, ...args) |
By NetDriver after an accepted intent’s handler ran, with the validated arguments. |
Net.IntentRejected |
(player, channelName) |
By NetDriver when an intent is rejected: no validator and not Open, a validator said no, the session changed while it yielded, or the handler threw. |
Net.RateLimited |
(player, channelName) |
By NetDriver when a token bucket rejects a message (Rate limiting). |
Net.FloodDetected |
(player, bytes, payloadBytes, budgetBytes, reason, count) |
By NetDriver, coalesced to one report per player and reason per heartbeat window. count is the drops in the window. |
Net.TierChanged |
(player, tier, stats) |
By NetGovernor when a link moves between Good, Strained and Poor. |
<ClientTopic> |
(session, ...args) |
By BusBridge on the server when a client publishes a whitelisted ClientTopics name. |
Security and compliance
Section titled “Security and compliance”| Topic | Arguments | Published |
|---|---|---|
AntiExploit.MovementViolation |
(player, violationType, strikes) |
By the Movement monitor when it records a strike. |
AntiExploit.Banned |
(userId, durationSeconds, record) |
By Consequences after Players:BanAsync succeeded for that id. durationSeconds is -1 for permanent; record is { DisplayReason, PrivateReason, PriorBans?, Production }. |
AntiExploit.BanFailed |
(userId, reason) |
By Consequences for an invalid id ("InvalidUserId") or a failed API call (the error text). |
AntiExploit.Unbanned |
(userId) |
By Consequences after Players:UnbanAsync succeeded for that id. |
AntiExploit.UnbanFailed |
(userId, reason) |
By Consequences for an invalid id or a failed API call. |
Forensics.Captured |
(player, capture) |
By Forensics when a capture finalizes. |
Policy.Loaded |
(session, policy) |
By Policy through Milestones when the session’s PolicyService lookup succeeded. |
Policy.Failed |
(session, reason) |
By Policy when every retry failed. Paid random items and paid trading stay refused for that session. |
Gameplay systems
Section titled “Gameplay systems”| Topic | Arguments | Published |
|---|---|---|
Zone.Entered, Zone.Left |
(zoneName, player) |
By Zones when a player crosses a zone boundary. Leaves are delivered before enters. |
Zone.EntityEntered, Zone.EntityLeft |
(zoneName, entity) |
By Zones for a tracked entity (NPC, prop, vehicle). |
Effects.Applied |
(player, effectName, stacks) |
By Effects when an effect is applied or stacks. |
Effects.Expired |
(player, effectName) |
By Effects when an effect expires or is removed. |
Effects.Blocked |
(player, effectName, byEffect) |
By Effects when an Immune effect blocked an apply. |
Effects.Cleansed |
(player, category?, count) |
By Effects when a cleanse removed count effects. |
Projectile.Hit |
(ownerSession, victimPlayer?, defId, position) |
By Projectiles when a shot hits a player or the world. |
Projectile.Redirected |
(ownerSession, serial, defId, position) |
By Projectiles after redirect restarts a shot. The owner is the one after the redirect. |
Hazard.Spawned, Hazard.Retired |
(handle) |
By Hazards when a hazard starts or ends. Occupants receive Hazard.Left before Retired. |
Hazard.Entered, Hazard.Left |
(handle, occupant) |
By Hazards when an occupant crosses the band. A crossing inside one tick fires both. |
Sweep.Hit |
(swing, victim, position) |
By Sweeps once per victim per swing. |
Stage.Loaded, Stage.Unloaded |
(stageName) |
By Stages when the first occupant arrives and after the last one leaves plus Linger. |
Stage.Entered, Stage.Left |
(stageName, player) |
By Stages per occupant. |
Mount.Added, Mount.Removed |
(instance, mountType) |
By Mounts on the side that attached it. |
Ragdoll.Started, Ragdoll.Ended |
(model) |
By Ragdoll when a ragdoll engages and when it is released. |
Matchmaking.Queued, Matchmaking.Dequeued |
(player, queueName) |
By Matchmaking when queue membership changes. |
Matchmaking.MatchFound |
(queueName, members) |
By Matchmaking before it teleports a match. |
Matchmaking.TeleportFailed |
(queueName, members, reason, result?, message?) |
By Matchmaking when a member’s teleport failed for good (TeleportRetry). members holds that one player. |
Leaderboard.Updated |
(boardName, entries) |
By Leaderboards when a board’s cached page refreshes. |
Config.Changed |
(key, value) |
By LiveConfig when a key’s effective value changes: an override applied, an override removed (the default is sent), or an Experience Configs update. |
Settings.Changed |
(session, key, value) |
By Settings when a setting is written by the client or the server. |
| Topic | Arguments | Published |
|---|---|---|
Round.PhaseChanged |
(phaseName, duration?) |
By RoundKit when a phase starts. |
Obby.Checkpoint |
(player, stage) |
By CheckpointKit when a checkpoint is accepted. |
Spell.Cast, Spell.Interrupted |
(session, spellId) |
By SpellKit. |
Weapon.Fired |
(session, weaponId, origin, direction) |
By WeaponKit when a shot is accepted. |
Weapon.Hit |
(session, victim, weaponId, position) |
By WeaponKit when an accepted shot deals damage. |
Weapon.ShotRejected |
(player, reason) |
By WeaponKit when validation refused a shot. |
Quest.Progress |
(player, questId, objectiveIndex, count, required) |
By QuestKit when an objective advances. |
Quest.Completed |
(player, questId) |
By QuestKit when every objective is met. |
Interact.Triggered |
(session, id, instance) |
By InteractionKit when a trigger passes Intent.Interact. |
Interact.Rejected |
(player, id) |
By InteractionKit when a trigger fails Intent.Interact. |
Procedural.Spawned, Procedural.Removed |
(archetypeName, model) |
By ProceduralKit. |
Procedural.Updated |
(archetypeName, model, appliedParams) |
By ProceduralKit when a parameter batch applied. |
Procedural.Rejected |
(archetypeName, param, error) |
By ProceduralKit when a parameter failed validation. |
Procedural.Failed |
(archetypeName, model, reason) |
By ProceduralKit when waitForGeneration finds that generation failed. |
Inventory.Granted |
(session, id, count) |
By InventoryKit with the count that fit. |
Inventory.Overflow |
(session, id, count) |
By InventoryKit with the count that did not fit, or the whole count for an unknown id. Declines a Receipts grant for that buyer. |
Inventory.Taken |
(session, id, count) |
By InventoryKit when an all-or-nothing take succeeded. |
Inventory.Equipped, Inventory.Unequipped |
(session, slotName, id) |
By InventoryKit when an equip slot changes. |
Inventory.Used |
(session, id, slotIndex) |
By InventoryKit when an OnUse item was consumed. |
Inventory.Changed |
(session) |
By InventoryKit on any bag change, with the owner’s INV_Sync push. |
Loot.Rolled |
(tableName, items, session?) |
By LootKit; session is nil for roll(). |
Loot.Awarded |
(session, tableName, granted, overflow) |
By LootKit when award granted through InventoryKit. |
Loot.Refused |
(session, tableName, reason) |
By LootKit when Policy refused a Paid table ("PolicyRestricted"). Declines a Receipts grant for that buyer. |
Craft.Started |
(session, recipeId, finishAt) |
By CraftingKit when a timed craft starts. |
Craft.Completed |
(session, recipeId, output) |
By CraftingKit when a craft finishes and the output was granted. |
Craft.Cancelled |
(session, recipeId) |
By CraftingKit when a craft is cancelled and its inputs refunded. |
Craft.Overflow |
(session, recipeId, remainder) |
By CraftingKit when output or a cancel refund did not fit. |
Shop.Bought |
(session, shopId, itemId, count, cost) |
By ShopKit. |
Shop.Sold |
(session, shopId, itemId, count, payout) |
By ShopKit. |
Shop.Rejected |
(player, shopId, itemId, reason) |
By ShopKit when a buy or sell is refused. |
Companion.Summoned |
(session, companionId, npc) |
By CompanionKit. |
Companion.Dismissed |
(session, companionId) |
By CompanionKit on dismiss or replacement by a new summon. |
Companion.Died |
(session, companionId) |
By CompanionKit at the companion’s death (from Npc.Died). |
Party.Created |
(party) |
By PartyKit on the first accept. |
Party.Disbanded |
(partyId) |
By PartyKit when the last member leaves. |
Party.Joined, Party.Left |
(party, player) |
By PartyKit when membership changes. |
Party.Kicked, Party.Promoted |
(party, player) |
By PartyKit; Promoted also fires on leader inheritance. |
Party.Invited |
(fromPlayer, toPlayer) |
By PartyKit when an invite is created. |
Team.Assigned |
(player, teamName, previous?) |
By TeamKit on auto-balance or assign. |
Team.Unassigned |
(player, previous) |
By TeamKit on unassign. |
Melee.Hit |
(attacker, victim, attackName, damage) |
By MeleeKit when a hit frame connects. |
Melee.Blocked |
(victim, attacker, attackName, damage) |
By MeleeKit when a block absorbed a hit; damage is the chip damage. |
Melee.GuardBroken |
(victim, attacker, attackName) |
By MeleeKit when a guard break shatters a block. |
Melee.Parried |
(parrier, attacker, attackName) |
By MeleeKit when a timed parry kills the swing. |
Melee.Staggered |
(entity, seconds) |
By MeleeKit. |
Melee.Combo |
(entity, chainLength) |
By MeleeKit when an attack chains through ComboNext. |
Melee.State |
(entity, state) |
By MeleeKit when a combatant’s state changes. |
Move.Used |
(session, abilityName, position) |
By MoveKit.server when it accepts an ability use (MoveKit). |
Move.Rejected |
(player, abilityName, reason) |
By MoveKit.server; reason is "Charges" or "Cooldown". |
Npc.Spawned, Npc.Died |
(npc) |
By NPCKit. Died sets npc.Dying and precedes the despawn delay. |
Npc.Action |
(npc, actionName, target) |
By NPCKit when a moveset action runs. |
Npc.Heard |
(npc, heardPosition, source?) |
By NPCKit when a sound reached the NPC; the position is already blurred by its skill. |
Npc.Suspicious |
(npc, target, glimpsedPosition) |
By NPCKit when graded detection reaches half charge. |
Npc.Damaged |
(npc, attacker?) |
By NPCKit when the NPC registers damage. |
Npc.Reload |
(npc, actionName, seconds) |
By NPCKit when a magazine empties. |
Npc.Windup |
(npc, actionName, target, seconds) |
By NPCKit when a telegraphed melee windup starts. |
Npc.Path |
(npc, waypoints) |
By NPCKit when a route is computed; the list starts at the NPC’s position. |
Npc.PathLink |
(npc, label, from, to) |
By NPCKit when a route starts crossing a PathfindingLink. The archetype’s Traverse[label] handler runs next. |
Npc.Hitscan |
(npc, origin, hitPosition, victim?) |
By NPCKit when a hitscan action fires, hit or miss. |
Npc.Defense |
(npc, reactionName, success, context) |
By NPCKit for each defensive reaction attempt. |
Npc.Tactic |
(npc, role) |
By the squad director when a role changes: "Pressure", "Flank" or "Suppress". |
Achievement.Progress |
(session, id, count, target) |
By AchievementKit on each counted event. |
Achievement.Unlocked |
(session, id) |
By AchievementKit once per player ever. |
Achievement.BadgeAwarded |
(session, id, badgeId) |
By AchievementKit when AwardBadgeAsync awarded the achievement’s platform badge. |
Dialogue.Started |
(session, dialogueId) |
By DialogueKit. |
Dialogue.Node |
(session, dialogueId, nodeId) |
By DialogueKit when a node is entered. |
Dialogue.Choice |
(session, dialogueId, nodeId, index) |
By DialogueKit when a visible choice is picked. |
Dialogue.Ended |
(session, dialogueId, reason) |
By DialogueKit; reason is "Completed" or "Stopped". |
Cutscene.Played |
(sceneName, origin?) |
By the server half of CutsceneKit when it broadcasts a scene. |
Vfx.Played |
(sequenceName, cframe) |
By the server half of VfxSuite when it broadcasts a sequence. |
Client and media
Section titled “Client and media”These publish on the kernel the module is attached to, which for most of them is the client.
| Topic | Arguments | Published |
|---|---|---|
Input.<Action> |
(state, inputObject) |
By InputDriver when a bound action changes state, before the handler runs on its own thread. |
Input.PreferredChanged |
(preferredInput) |
By InputDriver when UserInputService.PreferredInput changes. |
Move.Triggered |
(abilityName, context) |
By MoveKit on the client when an ability passes its context gate and runs. |
Audio.Cue |
(soundName, cueName, handle) |
By AudioKit when playback crosses a registered cue, loop-aware. |
Audio.Subtitle |
(text, durationSeconds) |
By AudioKit when a speak line starts. |
Audio.SubtitleEnded |
() |
By AudioKit when a line that published Audio.Subtitle finishes. |
Anim.Marker |
(model, animName, markerName, param) |
By AnimKit when an animation marker fires. |
Cutscene.Started, Cutscene.Ended, Cutscene.Skipped |
(sceneName) |
By CutsceneKit on the playing client. |
Cutscene.Line |
(text, seconds) |
By CutsceneKit for a Line event. The string is passed through unlocalized. |
Preload.Started |
(total) |
By Preload. |
Preload.Progress |
(loaded, total, assetId, ok, status?) |
By Preload per asset; status is the Enum.AssetFetchStatus when the engine reports one. |
Preload.Done |
(loaded, total, failed) |
By Preload when every batch finished. |
Device.Benchmarked |
(result) |
By DeviceBench when a run completes (cached afterwards). |
Device.QualityChanged |
(quality, profile) |
By the DeviceBench governor when it changes effective quality. |
Hair.Rigged |
(character, meshPart, boneNames) |
By HairKit when a hair mesh was rigged. |
Time.ScaleChanged |
(scale) |
By Time on setScale. |
Time.Paused, Time.Resumed |
() |
By Time on pause and resume. |
Text.TranslatorReady |
(player) |
By Text with Source = "Translator" once the player’s Roblox translator loaded. |
Topics the framework consumes
Section titled “Topics the framework consumes”Game code publishes these for framework modules to act on.
| Topic | Arguments | Effect |
|---|---|---|
AntiExploit.Forgive |
(player) |
The Movement monitor pardons the next sample, Rewind resets the player’s history, and Hazards does not count the move as a crossing. Movement.teleport, MoveKit.server (abilities with Forgive = true) and TeamKit spawns publish it themselves. |
AntiExploit.Exempt |
(player, exempt) |
The Movement monitor stops or resumes checking a player (vehicles, mounts, scripted knockback) without resetting Rewind. exempt is true or false. |
Combat.Hit |
(attacker, victim) |
SpellKit interrupts a channelled cast of the victim (a session or a player). |
Framework modules also listen to each other. Receipts treats Loot.Refused or Inventory.Overflow for the buyer during
a grant as a declined purchase unless the grant returns true. DataDriver waits for Kernel.Stopped before its final
saves, and on Commerce.TransactionEnded ends the session of a participant the trade left blocked, so the next load
recovers the trade. Replica
bindZone and Stages follow Zone.Entered and Zone.Left, and CompanionKit follows Npc.Died.