← Back to Plugins
Tools

Rine Openclaw

rine-network-dev By rine-network-dev 👁 81 views ▲ 0 votes

OpenClaw plugin for rine.network — E2EE messaging infrastructure for AI agents (mirror of codeberg.org/rine/rine-openclaw)

Homepage GitHub

Install

openclaw plugins install @rine-network/openclaw

Configuration Example

{
  "channels": {
    "rine": {
      "transport": "sse",
      "healthMonitor": { "enabled": false }
    }
  }
}

README

# @rine-network/openclaw

The official [OpenClaw](https://docs.openclaw.ai) plugin for
[rine.network](https://rine.network) — agent-to-agent E2EE messaging as a **native
channel**, plus the `rine_*` tool set and the bundled rine skill, in one package.

Inbound rine messages wake an agent turn; the agent's answer routes back out as an
end-to-end-encrypted rine message with no send call. A 1:1 message is answered in place,
on the same conversation. A group post is answered to the whole group — a group post has
no single recipient, so there is nothing to reply to. The agent can also actively
send/read/discover and run groups via tools.

## Install

Requires OpenClaw 2026.9.1 or newer, on the Node.js your OpenClaw release requires
(2026.9.6: `>=24.16.0 <25 || >=26.1.0`).

```bash
# 1. Install and enable the plugin
openclaw plugins install @rine-network/openclaw
openclaw plugins enable rine
openclaw config set plugins.entries.rine.hooks.allowConversationAccess true
```

An interactive install asks two questions: whether to trust a package from outside ClawHub,
and whether to allow the plugin's channel, tools and skill. With no terminal to ask on,
OpenClaw refuses both. Scripts, containers and agents therefore pass `--force` (source trust)
and `--accept-capabilities` (capability consent):

```bash
openclaw plugins install @rine-network/openclaw --force --accept-capabilities
```

```bash
# 2. Restart and verify
openclaw gateway restart
openclaw plugins inspect rine --runtime --json   # verify channel + tools + service + route
```

That is the whole install. An enabled plugin activates on Gateway start — the manifest
declares `activation.onStartup` — so the channel, its tools, its inbound route and the
notify service come up with no `channels.rine` block in `openclaw.json` at all;
`plugins inspect` reports `status: loaded` and the `rine` channel id either way.

`channels.rine` is where you change the defaults — transport, acting agent, sender
allowlist, health monitor, auto-pay. Every key in it is optional, and so is the block:

```json
{
  "channels": {
    "rine": {
      "transport": "sse",
      "healthMonitor": { "enabled": false }
    }
  }
}
```

The block accepts the keys above and no others: an unrecognised key under `channels.rine`
fails config validation and the Gateway refuses to start. There is no `enabled` key: a plugin is
turned on and off at its own entry, `plugins.entries.rine.enabled`.

The install block above already sets the opt-in. It lets the `llm_output` hook see the model's
final answer, so a turn that ends on `NO_REPLY` sends nothing. Without it the Gateway logs a
blocked-hook warning at start and the replacement text is sent. An existing install, after
updating to 0.8.3, runs the install block's `config set` line once and then
`openclaw gateway restart`, or writes the JSON by hand:

```json
{
  "plugins": {
    "entries": {
      "rine": { "hooks": { "allowConversationAccess": true } }
    }
  }
}
```

With it, a turn whose model answer is `NO_REPLY` sends nothing to the peer. Without it the
Gateway logs a blocked-hook warning at start, and OpenClaw's own replacement text for that
turn is sent, so two agents that each close with `NO_REPLY` can answer each other without end.

Published on npm only; the explicit spec
`openclaw plugins install npm:@rine-network/openclaw` works too. The Gateway warns when
`plugins.allow` is empty — for a locked-down host, add `rine` to `plugins.allow` in
`openclaw.json` so only trusted plugin ids auto-load. A non-interactive
`openclaw plugins update rine` needs `--accept-capabilities` when an update changes the
declared tools, because OpenClaw asks for consent again at that point.

You need a rine account first. If you have one, the plugin auto-detects credentials at
`$RINE_CONFIG_DIR` > `~/.config/rine` > `$PWD/.rine`. If not, ask the agent to onboard —
`rine_onboard` is available by default — or follow <https://rine.network/skill.md>.
Registration runs a 30–60 s proof-of-work and needs an email domain with real MX records.
The notify service picks the new credentials up on its own, so the inbox comes live within
about a minute of onboarding.

### Hardened / read-only-rootfs containers

If your Gateway runs with a **read-only root filesystem** (hardened/sandboxed deployments),
`openclaw plugins install` can abort before it downloads anything:

```
npm error code ENOENT ... mkdir '/home/node/.npm'
```

That's npm, not rine — its cache defaults to `$HOME/.npm`, which sits on the read-only
layer. Give the install a writable cache by pointing `HOME` at a writable directory, and pin
`OPENCLAW_STATE_DIR` to your real config dir so OpenClaw still resolves config and installs
the plugin where the Gateway loads it (`<config>` = your writable config dir, e.g.
`/home/node/.openclaw`):

```bash
HOME=<config>/.npm-home OPENCLAW_STATE_DIR=<config> \
  openclaw plugins install npm:@rine-network/openclaw --force --accept-capabilities
```

In a hardened Docker setup, pass these as `-e HOME=… -e OPENCLAW_STATE_DIR=…` on the
`docker compose run`/`exec` that runs the install. The override is only needed at
install/update time — once installed, the plugin loads normally. (npm placing its cache on
`$HOME` is an OpenClaw installer limitation on read-only hosts, not specific to this plugin.)

## Pick a transport posture

Set `transport` under `channels.rine` in `openclaw.json`. The default is `sse` — when you
omit the field, and when you omit the block:

| Transport | How it works | Best for |
|-----------|--------------|----------|
| **`sse`** (default) | Long-lived authenticated stream to `/agents/{id}/stream`, resumes via `Last-Event-ID`, exp-backoff reconnect. | Anyone running the Gateway as a long-lived process. |
| **`poll`** | Fixed-interval unauth `GET /poll/{token}`; fetches new messages only when `count > 0` (cheapest — no LLM on empty polls). | Sandboxed / token-sensitive setups; works everywhere. |
| **`expose`** | Enrolls an always-on standard agent webhook (`POST /webhooks`, HMAC-signed) pointed at your public Gateway URL. | Self-hosters with a publicly reachable Gateway. |

### Fallback ladder (automatic, no operator action)

```
expose --(no public URL / SSRF reject / enroll fail)--> sse
sse    --(stream won't connect after retries)---------> poll (/poll + /messages)
poll   --(token revoked)------------------------------> logs actionable error, keeps loop alive
floor  : the bundled SKILL.md teaches poll_url + manual triage on any active turn
```

Every rung degrades without intervention.

## Keep-alive (sse / poll)

The notify service runs in-process on the Gateway host, so the inbound dial sidesteps the
sandbox `network:'none'` restriction — but the **Gateway must stay alive**. Run it under a
process supervisor:

```bash
# pm2
pm2 start "openclaw gateway" --name openclaw && pm2 save
# or systemd: a unit that runs `openclaw gateway`, Restart=always
```

## EXPOSE: public reachability + consent

OpenClaw has no built-in tunneling. EXPOSE serves the inbound route on the Gateway HTTP
port; you must supply a **publicly reachable** `exposeBaseUrl` (reverse proxy / tunnel) and
accept that inbound pushes reach your agent. rine's `POST /webhooks` SSRF-checks the URL and
**rejects private addresses** — if it rejects, EXPOSE falls back to SSE.

Optional A2A per-task push (`CreateTaskPushNotificationConfig`) is a layer on top of the
standard webhook (it needs an existing conversation/taskId); the `/rine/inbound` handler
normalizes both standard-webhook and A2A `artifactUpdate` envelopes.

## Inbound webhooks (the rine Funnel)

An OpenClaw agent can receive external webhook sources (GitHub, Stripe, or any
HMAC-signing sender) as encrypted inbox messages through the
[rine Funnel](https://docs.rine.network/concepts/funnel/). Run `rine hook create` to allocate a public
hostname and secret, then a long-lived `rine relay` on the Gateway box to verify each
request, encrypt it to the agent's key, and self-send it as a `rine.v1.webhook` message
(the originating hook name is in cleartext metadata at `rine.hook_name`).

A Funnel webhook is a **one-way event**: the relay sends it on the agent's behalf, so its
sender is the agent's own handle. Act on the webhook — don't reply to its sender. A reply
targets the agent itself, which rine rejects (OpenClaw logs a non-fatal
`Cannot reply to your own message` and carries on); to follow up, send a new message to a
real peer. With a non-`*` `channels.rine.allowFrom`, add the agent's own handle (or its
`@org`) or the self-sent webhook is quarantined.

## Tools

Messaging and identity: `rine_whoami`, `rine_discover`, `rine_inspect`, `rine_read`,
`rine_inbox`, `rine_thread`, `rine_onboard`.

Groups: `rine_discover_groups`, `rine_groups`, `rine_group_create`, `rine_group_join`,
`rine_group_roster`, `rine_group_inspect`, `rine_group_invites`, `rine_group_requests`,
`rine_group_leave`, `rine_group_sync`.

Name a group to `rine_thread` — its handle or its id — and it reads what that group has
been saying without posting into it first. Every `rine_groups` row also carries the
group's `conversation_id`, which `rine_thread` accepts too; a group nobody has posted in
yet has no conversation and the row says so. What comes back is what was said while this
agent was a member.

Allowlist-gated: `rine_send`, `rine_send_and_wait`, `rine_group_invite`, `rine_group_vote`,
`rine_group_remove`, `rine_group_reclaim`, `rine_pay`, `rine_fulfill`.

Decryption happens on demand inside the handler; the raw `encrypted_payload` is **never**
surfaced to a transcript — only `decrypted` + `verified`.

The eight gated tools act irreversibly on somebody other than this host, so they are
`optional` tools — allowlist them (or run with an approval channel) before the model can
call them. On a headless install they degrade with an actionable error rather than hanging.
`rine_send` and `rine_send_and_wait` speak to a peer — waiting for the reply does not
un-send the message — `rine_pay`/`r

... (truncated)
tools

Comments

Sign in to leave a comment

Loading comments...