UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

383 lines (305 loc) • 18 kB
--- summary: "Tlon/Urbit support status, capabilities, and configuration" read_when: - Working on Tlon/Urbit channel features title: "Tlon" --- Tlon is a decentralized messenger built on Urbit. OpenClaw connects to your Urbit ship and responds to DMs and group chat messages. Group replies require an @ mention by default, with authorization rules and an owner-approval flow layered on top. Status: bundled plugin. DMs, group mentions, threads, rich text, image upload/download, and an owner approval system are supported. Reactions and polls are not. ## Bundled plugin Tlon ships bundled in current OpenClaw releases; packaged builds do not need a separate install. On an older build or custom install that excludes it, install from npm: ```bash openclaw plugins install @openclaw/tlon ``` Use the bare package name to track the current release tag. Pin a version (`@openclaw/tlon@x.y.z`) only for reproducible installs. From a local checkout: ```bash openclaw plugins install ./path/to/local/tlon-plugin ``` Details: [Plugins](/tools/plugin) ## Setup ```bash openclaw channels add --channel tlon --ship ~sampel-palnet --url https://your-ship-host --code lidlut-tabwed-pillex-ridrup ``` Or edit config directly: ```json5 { channels: { tlon: { enabled: true, ship: "~sampel-palnet", url: "https://your-ship-host", code: "lidlut-tabwed-pillex-ridrup", ownerShip: "~your-main-ship", // recommended: your ship, always authorized }, }, } ``` The login code is your ship's web login code: run `+code` in the ship's dojo to print the current one. It rotates, so re-read it whenever authentication starts failing. Ship URLs support IPv6 literals in brackets, such as `http://[::1]:8080`. Loopback and private IPv6 addresses require the private-network opt-in below. Config changes follow [hot reload](/gateway/configuration/hot-reload). Check `openclaw channels status --probe`, starting the Gateway if it is offline. Then DM the bot or @ mention it in a group channel. ## Inbound durability OpenClaw persists accepted Tlon DM and group-chat events before agent dispatch. Pending or retryable turns survive a Gateway restart, and work remains serialized per group channel or direct peer. Stable Urbit message IDs also suppress a redelivered event while its queue record or retained completion record exists. Delivery is at least once across the queue-to-agent boundary: a crash during handoff can replay a turn. Agent actions that produce external side effects should therefore remain idempotent where practical. ## Private/LAN ships OpenClaw blocks private/internal hostnames and IP ranges for SSRF protection by default. If your ship runs on a private network (localhost, LAN IP, internal hostname), opt in explicitly: ```json5 { channels: { tlon: { url: "http://localhost:8080", network: { dangerouslyAllowPrivateNetwork: true, }, }, }, } ``` Applies to targets like `http://localhost:8080`, `http://192.168.x.x:8080`, and `http://my-ship.local:8080`. Only enable this for a ship URL you trust; it disables SSRF protection for that account's HTTP requests. <Note> `channels.tlon.allowPrivateNetwork` (flat key) is retired. `openclaw doctor --fix` moves it to `channels.tlon.network.dangerouslyAllowPrivateNetwork` automatically. </Note> ## Group channels Pin channels manually, or turn on auto-discovery: ```json5 { channels: { tlon: { groupChannels: ["chat/~host-ship/general", "chat/~host-ship/support"], autoDiscoverChannels: true, }, }, } ``` `autoDiscoverChannels` defaults to `false` when unset in config; the setup wizard defaults the prompt to yes and writes `true` explicitly. With it on, OpenClaw scries joined groups on startup, watches new channels as group invites are accepted, and rechecks every 2 minutes. ## Access control DM allowlist (empty = no DMs allowed unless the sender is `ownerShip`): ```json5 { channels: { tlon: { dmAllowlist: ["~zod", "~nec"], }, }, } ``` Group authorization defaults to `restricted` per channel. Set `defaultAuthorizedShips` for a baseline, and override per channel nest: ```json5 { channels: { tlon: { defaultAuthorizedShips: ["~zod"], authorization: { channelRules: { "chat/~host-ship/general": { mode: "restricted", allowedShips: ["~zod", "~nec"], }, "chat/~host-ship/announcements": { mode: "open", }, }, }, }, }, } ``` Once the bot has replied inside a thread, it keeps responding to later messages in that thread without requiring another mention. Set `channels.tlon.implicitMentions.threadParticipation: false` to require a new explicit mention for those follow-ups. Account overrides use `channels.tlon.accounts.<id>.implicitMentions`. Tlon does not currently produce `replyToBot` or `quotedBot` facts, so those flags have no effect here. Set `channels.tlon.requireMentionInBotThreads: false` to accept unmentioned replies whenever this account's ship authored the thread root, including the first reply. Setting it to `true` requires a fresh mention in those threads even after the bot has participated. Omit it to keep the existing participation policy. The root author is read from the authenticated ship API; an unavailable or foreign root leaves the normal mention policy in place. Named accounts can override it with `accounts.<id>.requireMentionInBotThreads`. A per-channel `authorization.channelRules.<nest>.requireMentionInBotThreads` overrides the account default, including rules supplied through the Urbit settings store. For this option, a saved channel rule overrides the file value only when it sets a boolean value; older access-only rules inherit the file value. Sender authorization still applies, and this option does not change top-level channel posts or DMs. ## Owner and approval system ```json5 { channels: { tlon: { ownerShip: "~your-main-ship", }, }, } ``` The owner ship is authorized everywhere: DM invites are always auto-accepted, group invites are always auto-accepted, and channel messages always pass authorization. The owner does not need to be in `dmAllowlist`, `defaultAuthorizedShips`, or `groupInviteAllowlist`. Group DMs are the exception. Tlon does not verify who wrote a group DM message, so group DM messages never carry owner authority: owner commands, approval replies, and admin commands only work in a 1:1 DM with the bot. A group DM message whose claimed author is on `dmAllowlist` is still answered, but as an ordinary unverified sender. Pending DM requests saved by versions before this behavior cannot be told apart from group DM claims. Approving one still adds the ship to `dmAllowlist`, but its stored message is not replayed. The approval confirmation tells the owner the message was not processed and that the sender has to send it again. When `ownerShip` is set, unauthorized requests do not just get dropped — they queue a pending approval and DM the owner: - DM requests from ships not on `dmAllowlist` - Mentions in channels where the sender fails authorization - Group invites from ships not on `groupInviteAllowlist` (when auto-accept is off, or on but the inviter is not allowlisted) The owner replies in DM to act on a request: | Owner reply | Effect | | ---------------------------- | ---------------------------------------------------- | | `approve` / `deny` / `block` | Acts on the most recent pending approval | | `approve <id>` / `deny <id>` | Acts on a specific approval by id | | `block` | Also blocks the ship natively so it cannot reconnect | | `unblock ~ship` | Reverses a native block | | `blocked` | Lists currently blocked ships | | `pending` | Lists pending approval requests | Without `ownerShip` configured, unauthorized DMs and channel mentions are just dropped and logged; there is no approval prompt. The monitor admits up to 100 new pending approvals. Existing approvals from an older version are preserved so owner replies keep targeting the same request after an upgrade. When the queue is full, the monitor sends the owner one saturation notice and does not admit more unique requests until pending items are resolved. Failed notice delivery is retried up to three times per full-queue episode. Admitting a new request after capacity becomes available starts a new episode, so filling the queue again can send another notice in the same monitor run. Rejected requesters must retry after capacity is available; pending DM and group invite updates remain retryable rather than being acknowledged. Group invite updates apply to one group at a time. Revoked, removed, or completed invitations clear that group's duplicate suppression so a later invitation can be handled under the current auto-accept and allowlist settings. ## Auto-accept settings Auto-accept DM invites from ships already on `dmAllowlist` (the owner is always auto-accepted regardless of this flag): ```json5 { channels: { tlon: { autoAcceptDmInvites: true, }, }, } ``` Auto-accept group invites from an allowlist (fails closed: with `autoAcceptGroupInvites: true` and an empty `groupInviteAllowlist`, no non-owner invite is accepted): ```json5 { channels: { tlon: { autoAcceptGroupInvites: true, groupInviteAllowlist: ["~zod"], }, }, } ``` ## Hot-reload via Urbit settings store Most of the settings above (`dmAllowlist`, `groupInviteAllowlist`, `groupChannels`, `defaultAuthorizedShips`, `autoDiscoverChannels`, `autoAcceptDmInvites`, `autoAcceptGroupInvites`, `ownerShip`, `showModelSignature`) are mirrored into the ship's `%settings` agent (desk `moltbot`, bucket `tlon`) on first run and then read live from there, so changes made via a Landscape client or the bundled skill's settings commands apply without a gateway restart. `channelRules` and pending approvals are also persisted there as JSON. File config stays the source of truth for values never written to the settings store. ## Delivery targets (CLI/cron) Use with `openclaw message send` or cron delivery: - DM: `~sampel-palnet` or `dm/~sampel-palnet` - Group: `chat/~host-ship/channel` or `group:~host-ship/channel` ## Bundled skill The plugin bundles [`@tloncorp/tlon-skill`](https://github.com/tloncorp/tlon-skill), a CLI for direct Urbit operations, available automatically once the plugin is installed: - **Activity**: mentions, replies, unreads - **Channels**: list, create, rename - **Contacts**: list/get/update profiles - **Groups**: create, join, invite/request flows, roles - **Hooks**: manage channel hooks - **Messages**: history, search - **DMs**: send, react, accept/decline - **Posts**: react, delete - **Notebook**: post to diary channels - **Settings**: hot-reload plugin config via the settings store above ## Capabilities `channels.tlon.mediaMaxMb` limits each inbound image download and outbound image load in MiB. Named accounts can override it with `accounts.<id>.mediaMaxMb`; otherwise the channel root and then `agents.defaults.mediaMaxMb` apply. The existing 6 MiB ceiling applies to image downloads and uploads. With a configured cap, a failed size check or download fails the send instead of embedding an unchecked URL. Upload failures after a successful bounded download can still use the original URL. Without a configured cap, the existing link fallback remains available even when the image cannot be downloaded within that ceiling. | Feature | Status | | --------------- | --------------------------------------------- | | Direct messages | Supported | | Groups/channels | Supported (mention-gated by default) | | Threads | Supported (keeps replying once it has joined) | | Rich text | Markdown converted to Tlon's native format | | Images | Downloaded inbound, uploaded outbound | | Reactions | Only via the [bundled skill](#bundled-skill) | | Polls | Not supported | | Native commands | Owner-only by default | ## Troubleshooting ```bash openclaw status openclaw gateway status openclaw logs --follow openclaw doctor ``` Common failures: - **DMs ignored**: sender not in `dmAllowlist` and no `ownerShip` configured for the approval flow. - **Group messages ignored**: channel not discovered/pinned, or sender fails authorization with no `ownerShip` to queue an approval. - **Connection errors**: check the ship URL is reachable; set `network.dangerouslyAllowPrivateNetwork` for local ships. - **Auth errors**: login codes rotate — copy the current code from your ship. ## Configuration reference Full configuration: [Configuration](/gateway/configuration) | Key | Meaning | | ------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------- | | `channels.tlon.enabled` | Enable/disable channel startup. | | `channels.tlon.ship` | Bot's Urbit ship name (e.g. `~sampel-palnet`). | | `channels.tlon.url` | Ship URL (e.g. `https://sampel-palnet.tlon.network`). | | `channels.tlon.code` | Ship login code. | | `channels.tlon.network.dangerouslyAllowPrivateNetwork` | Allow localhost/LAN ship URLs (SSRF opt-in). | | `channels.tlon.ownerShip` | Owner ship: always authorized, receives approval requests. | | `channels.tlon.dmAllowlist` | Ships allowed to DM (empty = none besides owner). | | `channels.tlon.autoAcceptDmInvites` | Auto-accept DMs from ships in `dmAllowlist`. | | `channels.tlon.autoAcceptGroupInvites` | Auto-accept group invites from `groupInviteAllowlist`. | | `channels.tlon.groupInviteAllowlist` | Ships whose group invites are auto-accepted. | | `channels.tlon.autoDiscoverChannels` | Auto-discover joined group channels (default: `false`). | | `channels.tlon.implicitMentions.threadParticipation` | Let participated-thread follow-ups bypass mention gating. | | `channels.tlon.requireMentionInBotThreads` | Override mention gating only in threads whose root this account's ship authored; omitted preserves existing behavior. | | `channels.tlon.groupChannels` | Manually pinned channel nests. | | `channels.tlon.defaultAuthorizedShips` | Ships authorized for all channels (used when no rule matches). | | `channels.tlon.authorization.channelRules` | Per-channel-nest auth mode, allowlist, and optional `requireMentionInBotThreads` override. | | `channels.tlon.showModelSignature` | Append `_[Generated by <model>]_` to replies. | | `channels.tlon.responsePrefix` | Automatic reply prefix: literal, `"auto"`, or a template such as `"[{model}]"`; account overrides win, and `""` disables it. | | `channels.tlon.accounts.<id>` | Additional named accounts (multi-ship setups). | ## Notes - Group replies need an @ mention (e.g. `~your-bot-ship`) unless thread participation or a bot-owned thread policy allows them. - Thread replies land in-thread; the bot also gets the last 10 messages of thread context prepended for the agent. - Rich text (bold, italic, code, headers, lists) converts to Tlon's native format. - Sending an inbound message that asks for a channel summary (for example "summarize this channel") triggers a built-in history summarization instead of the normal reply flow. ## Related - [Channels Overview](/channels) — all supported channels - [Pairing](/channels/pairing) — DM authentication for channels that declare it; Tlon is not one of them and uses the `dmAllowlist` plus `ownerShip` approval flow above instead - [Groups](/channels/groups) — group chat behavior and mention gating - [Channel routing](/channels/channel-routing) — session routing for messages - [Security](/gateway/security) — access model and hardening