The agent is alive in its cell. Now we give it a phone one that’s encrypted, allowlisted, and answers only to you.
In Part 2 we installed NemoClaw and bootstrapped the four-layer sandbox. The agent is reachable from the OpenClaw dashboard over Tailscale, gated behind mTLS, and isolated from the host. That’s enough for development. It’s not enough for the way most people will actually want to use this agent day-to-day: from their phone, from their laptop, from wherever they happen to be.
We need a chat channel.
The default candidates Telegram, Discord, WhatsApp, Slack share one disqualifying property i.e. the platform operator can read your messages. For a channel that’s about to carry high-privilege instructions to an autonomous agent (“delete the staging environment”, “transfer this file”, “post on my behalf”), that’s the wrong threat model. Matrix is the channel where the messages are end-to-end encrypted by default, the protocol is open, you can self-host if you want, and an enterprise audit trail is possible without trusting a third party.
This article gets a Matrix-controlled NemoClaw bot from zero to “type a message, get an answer” in about thirty minutes. By the end you’ll have:
- A dedicated Matrix account for your bot, registered on matrix.org (or your own homeserver)
- An access token authorising OpenClaw to act as that account
- A network policy granting the sandbox exactly the access it needs to talk to Matrix and nothing more
- An allowlist so only your Matrix ID can DM the bot
- Verified end-to-end encryption between your client and the agent
The clean path is straightforward. The sharp edges are real but they’re in sidebars, not in your way.
What You’re Building
Three actors, one channel:
┌──────────────┐ E2EE ┌──────────────┐ ┌─────────────────┐
│ You │ ┌────────┐ │ matrix.org │ │ Your VPS │
│ Element on │──┤ Matrix │──│ homeserver │───┤ NemoClaw │
│ phone/laptop │ │ room │ │ (relays only │ │ sandbox │
└──────────────┘ └────────┘ │ ciphertext) │ │ (decrypts here) │
└──────────────┘ └─────────────────┘
You and the bot share an end-to-end-encrypted room. Your homeserver and the bot’s homeserver — they can be the same (matrix.org) or different (matrix.org ↔ self-hosted Synapse) — relay encrypted bytes between you. Neither homeserver can read the content. The bot's plaintext only ever exists inside two places: your Element client and the NemoClaw sandbox itself.
If that property doesn’t matter to your threat model, stop reading and use Telegram. If it does, keep going.

e2ee secure communication chain
Step 1: Create the Bot’s Matrix Account
You can either register a fresh account on matrix.org (free, easy) or on your own self-hosted Synapse. The setup is identical from here on; pick whichever matches your existing posture.
For matrix.org:
- Open https://account.matrix.org in a browser
- Click Create account
- Choose a username for the bot — something descriptive likeagent-orion-bot, nightowl-bot. This becomes the bot's Matrix ID: @nightowl-bot:matrix.org
- Use a real email you can verify — matrix.org requires it
- Set a strong password, save it to a password manager, then forget you ever typed it (we’ll authenticate via access token from here on)
Sidebar** matrix.org migrated to OIDC.** As of late 2025, account registration and login on matrix.org runs through OpenID Connect (MSC3861). You'll be bounced through a federated login flow rather than the old "username + password" page. This is fine for humans. It matters when you start scripting against the API see Step 2.
Once registered, open Element Web (https://app.element.io) and log in as the bot. Set a display name and avatar so messages from the bot look like messages, not like infrastructure. This is a one-time human-friendliness step.

Create the Bot’s Matrix Account
Step 2: Get an Access Token
OpenClaw authenticates against Matrix using an access token rather than a password. The token represents a single device session if it leaks, you revoke that device and the rest of your account is unaffected.
In Element Web, logged in as the bot:
- Settings → Help & About
- Scroll to Advanced
- Click the disclosure triangle next to Access Token
- Copy the long string starting with syt_…
Keep it on the clipboard. Treat it like an SSH key.
Sidebar: Why not generate the token programmatically? On a pre-OIDC homeserver, you’d POST /_matrix/client/v3/login with a username and password and get a token back. On matrix.org post-MSC3861, that endpoint returns errors for accounts created through the OIDC flow. Element's settings panel sidesteps the issue by exposing the token already minted by your interactive login. For a single bot, that's plenty. If you're at the scale of "many bots, automated provisioning", run your own Synapse where the legacy login API still works the way you'd expect.
Step 3: Allow the Sandbox to Reach Matrix
By default, the NemoClaw policy denies the sandbox almost all outbound traffic — including matrix.org. The bot will silently fail to connect until you write a policy that allows it.
On the host:
NEMOCLAW_POLICIES="$(npm root -g)/nemoclaw/nemoclaw-blueprint/policies"
nano $NEMOCLAW_POLICIES/openclaw-sandbox.yaml
Add the following entry under the existing network_policies: block (don't replace the file — append):
matrix:
name: matrix
endpoints:
- host: matrix-client.matrix.org
port: 443
protocol: rest
tls: terminate
enforcement: enforce
rules:
- allow: { method: GET, path: "/**" }
- allow: { method: POST, path: "/**" }
- allow: { method: PUT, path: "/**" }
- host: matrix.org
port: 443
binaries:
- { path: /usr/bin/node }
Apply the updated policy:
openshell policy set --policy $NEMOCLAW_POLICIES/openclaw-sandbox.yaml nemoclaw-sandbox
Verify it landed:
nemoclaw nemoclaw-sandbox policy-list
You should see matrix in the list. If you're self-hosting Synapse, swap matrix-client.matrix.org and matrix.org for your own homeserver hostnames — the policy structure is identical.
Sidebar:** openshell policy set replaces the entire policy.** This is not a merge command. Always edit the full policy file and reapply it. If you cat only a partial policy and apply that, you've just removed every other endpoint your agent depended on. Edit; don't shard.
Step 4: Configure OpenClaw
Open the OpenClaw dashboard at http://:18789 and navigate to Settings → Config.
Find the channels block (or add one if it doesn't exist) and configure matrix:
channels: {
matrix: {
enabled: true,
homeserverUrl: 'https://matrix-client.matrix.org',
userId: '@chip1-bot:matrix.org',
accessToken: 'syt_xxxxxxxxxxxxxxxxxxxxxxxx',
e2ee: true,
dmPolicy: 'allowlist',
allowFrom: [
'@you:matrix.org',
],
streaming: 'partial',
},
},
Replace the four placeholders: homeserverUrl (your homeserver — leave as-is for matrix.org), userId (the bot's full Matrix ID), accessToken (the syt_… string from Step 2), and allowFrom (your own Matrix ID — this is who's allowed to DM the bot).
Save the config.
e2ee: true is the only setting that matters for security. Don't ever flip it to false "just to test" — the bot's device keys get generated on first run, and switching encryption modes later forces a device-key rotation that you do not want to debug. Set it once, on.
streaming: 'partial' makes the bot post incremental responses as the agent generates them, which feels conversational rather than "send message → wait 30 seconds → wall of text". 'full' waits for completion and posts once.
Restart NemoClaw’s auxiliary services so the Matrix bridge picks up the new config:
nemoclaw stop
nemoclaw start

OpenClaw e2ee Communication Channel Configure
Step 5: Verify the Bot Is Online
From your own Matrix account (Element on phone or web), start a new direct message to the bot’s Matrix ID. Send hello.
Within a few seconds you should see:
- A reply from the bot
- A shield icon on the room indicating end-to-end encryption is active
- A device-verification prompt (one-time, see below)
If nothing happens within thirty seconds, check the logs:
nemoclaw nemoclaw-sandbox logs --follow | grep -i matrix
Common failure modes and what they mean:
Step 6: Verify End-to-End Encryption
E2EE on Matrix only protects you if you actually verify the other device’s keys. Without verification, the room is encrypted but vulnerable to a homeserver-side key swap that you wouldn’t notice.
In Element, in the room with the bot:
- Click the room name → People
- Click the bot’s name
- Click Verify
- Compare the emoji sequence shown in Element with the emoji sequence printed by the bot in the room
- If they match, confirm
The shield icon should now turn from grey (“encrypted, unverified”) to green (“encrypted, verified”). This is a one-time step per device pair.
If verification fails or the bot never sends the emoji message, the device is in a confused state — see the next sidebar.
A Known Wart: Stale Devices
If you’ve logged into the bot account before — to test, to check something, to set the display name — every login created a device (a session key). Matrix tracks these per-account, and if the bot tries to send an encrypted message while another stale device holds conflicting crypto keys, E2EE breaks.
You will see one of:
- The bot replies but messages are flagged “unable to decrypt” on your end
- The bot logs an error like OlmSessionError: no matching session
- Device verification (Step 6) loops forever
Recovery is mechanical but slightly painful, because matrix.org has neither a "delete all devices" button nor a working bulk-delete API. The endpoints DELETE /_matrix/client/v3/devices/{deviceId} and the older /logout/all both return M_UNRECOGNIZED for OIDC-managed accounts.
The path that actually works:
- Go to https://account.matrix.org/account/
- Sign in as the bot
- Sessions → review every active session
- For each one that isn’t the current OpenClaw bot session: click the session, then Sign out
- If you can’t tell which one is OpenClaw’s, sign out of all of them, restart nemoclaw stop && nemoclaw start, let the bot create a fresh device, and then verify that single device with Element
If the dashboard refuses to let you delete a specific stale device (it sometimes does, depending on which device created the others), the working trick is to log in as that stale device from a fresh Element session — using the bot’s password — and then Sign out from within. The device gets purged server-side because you’re inside its own session.
This is the one place in Part 3 where the path is genuinely uglier than Matrix’s marketing implies. Do the cleanup once, verify once, and you won’t revisit it.
Verification Checklist
Before moving on to Part 4:
- The bot account exists at @yourbot:matrix.org (or your homeserver) and is reachable in Element
- matrix-client.matrix.org appears in the sandbox's network policy
- nemoclaw nemoclaw-sandbox policy-list shows matrix as applied
- From your own Matrix account, DM’ing the bot returns a response within 5 seconds
- The room shows a green shield icon (encrypted and verified)
- DMs from any Matrix ID not on the allowFrom list are silently ignored — test by asking a friend to message the bot and confirm nothing happens
- nemoclaw nemoclaw-sandbox logs shows no recurring M_FORBIDDEN or device-key errors
Where You Are Now
You have an autonomous AI agent reachable from any Matrix client, anywhere, over an end-to-end encrypted channel that you’ve verified. Only your Matrix ID can talk to it. The sandbox can reach matrix.org and nothing else relevant on the public internet. The host has no public ports open.
This is the configuration most consumer agents simply don’t offer. ChatGPT-on-iOS reads your messages; so does any LLM-backed Discord bot, Slack bot, or Telegram bot. The plaintext lives somewhere outside your control. With this setup, plaintext lives in exactly two places your phone and your sandbox and the path between them is bytes you’ve cryptographically verified.
The threat model that remains: anyone who compromises your Matrix account can talk to your agent. Hardware-level account security (FIDO2 on Element, account-recovery key offline) is now load-bearing in a way it wasn’t before. This is the right place for security to live, because it’s the same security perimeter you already protect for everything else important in your digital life.
What’s Next
Part 4. Policy Engineering. Your agent can now receive instructions over an encrypted channel. The next question is what the agent is actually allowed to do once it receives them. OpenShell’s policy engine is the reason NemoClaw exists rather than just running OpenClaw directly — we’ll write per-domain network policies, set up filesystem allowlists, walk through live policy updates with openshell policy set --wait, and look at how policy revisions work as an audit trail.
Part 5. Skills, Plugins, and Model Switching. The agent currently has the empty-shell capabilities OpenClaw ships with. We’ll install skills from ClawHub safely (the docker-cp-then-kubectl-cp pattern), enable plugins from inside the sandbox, and swap between Nemotron and Claude Sonnet without a restart.

Next AI agent with policy boundaries
I’m collecting Matrix deployment stories for the Part 4 appendix. If you hit a homeserver-specific quirk, an Element verification edge case, or a federation issue I didn’t cover — drop the details in the comments. Every reader who shares makes the next article sharper.






Top comments (0)