Bijaya Dangol

Most agent chat channels assume a platform bot identity. You register a bot username, a phone number, an application account, or some other platform-managed endpoint, and the agent becomes reachable through that platform’s identity model.

That works well enough in many cases, but it is not the only model worth supporting.

What I wanted for OpenClaw was more specific: a private, end-to-end encrypted transport for agents, without having to provision another phone number and without relying on an unofficial integration path for a core channel.

I built @dangoldbj/openclaw-simplex, a SimpleX Chat channel plugin for OpenClaw, to support a different model: no public bot identity, invitation-based onboarding, and an explicit runtime boundary between the agent platform and the transport layer.

The problem with normal bot channels

For most chat integrations, your agent is reachable because the platform says it exists. That reachability usually depends on some centralized registration step:

In other words, the transport decides how the agent is discovered.

That is often convenient. But it is not always a good fit for more constrained deployments:

What I actually wanted was something closer to Signal-level privacy, or better, without the awkward parts that usually come with personal-account-oriented messaging systems.

One obvious route would have been an existing phone-number-centered messaging channel. In OpenClaw, the Signal path is one example: it goes through signal-cli, and signal-cli describes itself as an unofficial interface for Signal. That does not make it unusable, but it was enough to make me cautious about depending on that path for a core agent channel.

There was also the onboarding model. Phone-number-based setup is common in personal messaging systems, but I did not want to buy and manage another phone number just to make an OpenClaw agent reachable. For an agent transport, that is unnecessary operational friction. A personal messaging identity model is often the wrong abstraction for an agent.

So the requirement set was more specific than “I want invite links”. I wanted a channel that was:

SimpleX matched that shape much better. Invitation-first reachability was the result of those constraints, not the starting point.

Why SimpleX

SimpleX is interesting because it gives a very different trust and onboarding model from mainstream chat platforms.

With this plugin, the contact surface begins with a SimpleX invite link or address link. The agent is not globally discoverable through a public bot username. There is no phone number to provision. There is no hosted platform account that has to exist before the first conversation starts.

That creates a different shape of access:

This is a better fit for deployments where explicit onboarding matters more than broad discoverability.

Just as importantly, SimpleX makes it possible to think about self-hosted transport more seriously. A lot of people talk about self-hosting the model runtime while the transport path still goes through someone else’s platform identity and account system. With SimpleX, if you want, you can run the runtime locally and keep the relay path under infrastructure you control.

What the plugin actually adds to OpenClaw

The shortest description is that it makes OpenClaw reachable over SimpleX, but that undersells what a real channel integration has to do.

The plugin has to:

In practical terms, the package now supports:

That is what turns the project from “a bridge script” into a real OpenClaw channel implementation.

The architecture that mattered

The most important design choice in the project is that OpenClaw should not own the lifecycle of the SimpleX runtime for this plugin.

The architecture looks like this:

            +-------------------------+
            |        OpenClaw         |
            |  (agent + router/core)  |
            +------------+------------+
                         |
                         | channel plugin API
                         v
            +-------------------------+
            | @dangoldbj/openclaw-    |
            |        simplex          |
            | - inbound monitor       |
            | - outbound translation  |
            | - account/runtime state |
            +------------+------------+
                         |
                         | WebSocket API
                         v
            +-------------------------+
            |   SimpleX CLI Runtime   |
            |      (simplex-chat)     |
            +------------+------------+
                         |
                         | network
                         v
            +-------------------------+
            |      SimpleX Network    |
            +-------------------------+

OpenClaw is responsible for routing and policy. The plugin is responsible for translating channel behavior. The simplex-chat runtime is a separately managed process.

This separation is deliberate.

If the plugin spawned and supervised simplex-chat itself, the integration would look simpler at first glance, but it would blur the runtime boundary and hide operational assumptions inside plugin startup. I wanted the deployment model to stay explicit:

Over time I pushed that separation further by removing the earlier managed mode and making the external runtime path the supported model.

Reachability is not authorization

One subtle point in this integration is that invitation-based messaging is not, by itself, the whole security story.

SimpleX gives the first boundary: who can reach the agent at all.

OpenClaw then adds another boundary: who is allowed to trigger agent work after a message arrives.

That second layer matters. In this plugin, OpenClaw still applies:

So the security model is not just “messages are encrypted” or “the link is private”. It is a layered model:

  1. the invite or address link creates the initial contact path
  2. OpenClaw policy determines whether that sender is allowed to interact with the agent
  3. the runtime boundary determines where process and relay trust live

That is the kind of distinction that becomes important once a project moves from demo to something operators may actually rely on.

The operator workflow

The operator flow is intentionally small.

You run simplex-chat as a separate process, point OpenClaw at its WebSocket endpoint, and generate an invite link for the first contact. After that, the interesting parts are not the setup steps themselves but the operational surfaces around them:

That was an important part of the design. I did not want the project to stop at “messages can be exchanged.” I wanted the channel to be operable.

The docs and screenshots for the project live at openclaw-simplex.mintlify.app.

Why I think this matters

What interests me most about this project is not that OpenClaw can now talk over SimpleX. It is that this integration expands what a channel can mean inside an agent platform.

Instead of assuming a public platform bot identity, the channel can start from an invitation. Instead of hiding the transport runtime inside the plugin, the runtime boundary can stay explicit. Instead of treating transport choice as only a UX detail, it can shape the trust model of the deployment.

I think that is a useful direction.

There are many cases where a public bot account is exactly the right abstraction. But there are also cases where private, operator-controlled messaging is a better fit, and I wanted OpenClaw to have that option.

The package, source, and docs are here: