Onboarding

Package: onbod/. Optional daemon, auto-included in compose when ONBOARDING_ENABLED=true.

Role

onbod handles new JIDs that arrive with no existing group registration. It registers itself as a channel with receive_only: true capability โ€” the gateway routes unmatched JIDs to it, but onbod responds via the notify/ library rather than through a router outbound call.

The gateway does not know that onbod exists. From the gateway's perspective, it is just another registered channel. No onboarding-specific code is in gated.

Enabling

ONBOARDING_ENABLED=true

Set this in .env. When true, gated routes messages from unregistered JIDs to the onboarding channel instead of discarding them. arizuko generate includes the onbod service in the compose file.

State machine

Per JID, tracked in the onboarding table:

                    user sends name
awaiting_name  โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ†’  pending
                                           โ”‚
                              /approve JID โ”‚ /reject JID
                                           โ†“
                                    approved / rejected

States: awaiting_name, pending, approved, rejected.

Poll loop

Runs every 10 seconds:

  1. Prompt any awaiting_name records that have not been prompted recently
  2. Read pending messages from unregistered JIDs
  3. Validate name response: lowercase, no collision with existing group folders โ†’ transition to pending, notify all tier-0 JIDs via notify/
  4. For JIDs already in pending: reply "Still waiting for approval" if they send another message

Operator commands

On startup, onbod seeds command routes in the routes table:

CommandAction
/approve <jid>Create group dir, copy prototype, insert registered_groups row, insert default routes, send welcome system event
/reject <jid>Set status to rejected, send rejection message to JID

Operator must be a tier-0 group (no parent). onbod verifies this before executing the command.

Approval flow

On /approve <jid>:

  1. Create groups/<world_name>/ directory
  2. Copy prototype files if a prototype group is configured: CLAUDE.md and SOUL.md are copied; session and memory are not
  3. Insert row into registered_groups
  4. Insert default routes for the new group
  5. Insert a system event message welcoming the new group
  6. Fan out a notification to all tier-0 JIDs via notify/

Prototype copy

The prototype path is configured via ONBOARDING_PROTOTYPE_FOLDER. When set, CLAUDE.md and SOUL.md from the prototype are copied to the new group directory. Session state, memory, and diary are not copied.

Agents can also spawn child groups directly via the register_group IPC tool with fromPrototype: true, which applies the same copy logic.