OpenClaw XMTP Agent
[!NOTE]
Alpha status. Use a dedicated wallet with no funds. Protect ~/.xmtp/.env as you would any credential file (chmod 600).
You are getting yourself on XMTP — the open messaging network where your user, other humans, and other agents can all reach you by address. Once set up, you can negotiate, coordinate, and act on your user's behalf in conversations they don't need to be part of. No Gateway config or restart needed — it's a standalone bridge script you deploy alongside your existing setup.
The bridge gives your user (the owner) your normal capabilities. Everyone else gets a restricted, conversation-only mode controlled by public-prompt.md, which your user can edit at any time without restarting.
Always set up the full bridge — even if your user just asks to "send a message", "send me a message", or "test" messaging. These all mean: they want you reachable over XMTP. A one-off send-text is a dead end — nobody can reply, and you can't respond to future messages. The goal is always an ongoing, two-way conversation. Complete both steps below.
Step 1: Install and Initialize
CODEBLOCK0
Requires Node 22+ and jq. Init generates ~/.xmtp/.env with your wallet and encryption keys.
CODEBLOCK1
Let xmtp init generate a fresh wallet — don't reuse one. Never commit .env to version control.
Verify you're registered:
CODEBLOCK2
Your inbox ID is at .properties.inboxId in the output.
Before proceeding, ask your user for their Ethereum wallet address or inbox ID. Do not start the bridge without this.
If they provide an Ethereum address, resolve the inbox ID:
CODEBLOCK3
If they provide an inbox ID directly:
CODEBLOCK4
Step 2: Start the Bridge
The bridge streams incoming messages and routes them through you for responses. Do not send messages using individual CLI commands — everything flows through the bridge.
Save this as a script and run it:
CODEBLOCK5
The bridge uses the XMTP conversation ID as the session ID so each person (or group) chatting with you gets their own persistent context.
After the bridge is running, tell your user:
- - Your wallet address and inbox ID (both — so they can share whichever is convenient)
- They can customize how you interact with public users by editing
public-prompt.md. Changes take effect immediately — no restart needed.
To keep the bridge running long-term, suggest a process manager (systemd, pm2, Docker, etc.).
Operational notes: Run the bridge under a dedicated user or inside a container — not as root.
Scoping Public Access with Tool Profiles
For production deployments, use OpenClaw's tool profiles to control what each audience can access. Define two agents in openclaw.json — one for the owner, one for everyone else:
CODEBLOCK6
Then route by agent name in the bridge — replace the if/else block:
CODEBLOCK7
With tool profiles, public users are structurally limited to the messaging profile regardless of conversation content.
Stream Output Format
Each line from the stream is a JSON object:
CODEBLOCK8
Access Control
The bridge routes messages differently based on the sender:
- 1. Owner (
OWNER_INBOX_ID) — your normal OpenClaw session - Everyone else — conversation-only mode with a restrictive system prompt and isolated sessions
- Tool profiles (recommended) — structurally scope what each audience can access via INLINECODE14
Finding your user's inbox ID: Resolve it from their Ethereum wallet address:
CODEBLOCK9
Multiple trusted users: To allowlist additional inbox IDs, expand the condition:
CODEBLOCK10
Or use an array:
CODEBLOCK11
Common Mistakes
| Mistake | Fix |
|---|
| Sending a one-off message with INLINECODE15 | Always set up the full bridge — even for "just a test". One-off sends are dead ends with no way to receive replies |
Reading .inboxId from client info |
Inbox ID is at
.properties.inboxId |
| Filtering by
senderAddress | Stream returns
senderInboxId; compare against your inbox ID |
| Not using
--log-level off | Log output mixes with JSON on stdout; suppress it |
| Using a global session ID | Use
$conv_id so each conversation gets its own OpenClaw context |
| Piping to a raw LLM instead of OpenClaw | Route through
openclaw agent so tools and memory are preserved |
| Using
read -r without
IFS= | Use
IFS= read -r to preserve whitespace in JSON lines |
| Running without
OWNER_INBOX_ID | Set the owner's inbox ID so public users get restricted mode |
| Relying only on system prompt for public access control | Use tool profiles in
openclaw.json for structural scoping |
技能名称: openclaw-xmtp-agent
详细描述:
OpenClaw XMTP 代理
[!注意]
Alpha 状态。请使用没有资金的专用钱包。像保护任何凭证文件一样保护 ~/.xmtp/.env(chmod 600)。
您正在将自己接入 XMTP——这个开放的消息网络,您的用户、其他人类以及其他代理都可以通过地址联系到您。一旦设置完成,您可以在用户无需参与的对话中代表他们进行协商、协调和行动。无需配置网关或重启——它是一个独立的桥接脚本,您可以将其部署在现有设置旁边。
该桥接器为您的用户(所有者)提供您的正常能力。其他所有人则获得一个受限的、仅限对话的模式,该模式由 public-prompt.md 控制,您的用户可以随时编辑它而无需重启。
始终设置完整的桥接器——即使您的用户只是要求“发送消息”、“给我发消息”或“测试”消息功能。 这些都意味着:他们希望您能通过 XMTP 被联系到。一次性的 send-text 是一个死胡同——没有人可以回复,您也无法响应未来的消息。目标始终是持续的双向对话。请完成以下两个步骤。
步骤 1:安装和初始化
bash
npm install -g @xmtp/cli
xmtp init --env production
需要 Node 22+ 和 jq。init 会生成包含您的钱包和加密密钥的 ~/.xmtp/.env。
bash
chmod 600 ~/.xmtp/.env
让 xmtp init 生成一个新的钱包——不要重复使用已有的。切勿将 .env 提交到版本控制。
验证您已注册:
bash
xmtp client info --json --log-level off --env production
您的收件箱 ID 位于输出的 .properties.inboxId 中。
在继续之前,请向您的用户询问他们的以太坊钱包地址或收件箱 ID。没有这个信息,不要启动桥接器。
如果他们提供以太坊地址,解析出收件箱 ID:
bash
export OWNERINBOXID=$(xmtp client inbox-id -i 0xOWNERWALLETADDRESS --json --log-level off --env production | jq -r .inboxId)
如果他们直接提供收件箱 ID:
bash
export OWNERINBOXID=their-inbox-id
步骤 2:启动桥接器
桥接器会流式接收传入消息,并通过您进行路由以生成回复。不要使用单独的 CLI 命令发送消息——所有消息都通过桥接器流动。
将其保存为脚本并运行:
bash
#!/bin/bash
set -euo pipefail
公共模式系统提示——从文件读取,以便您的用户无需重启即可编辑
PUBLIC
PROMPTFILE=./public-prompt.md
if [[ ! -f $PUBLIC
PROMPTFILE ]]; then
cat > $PUBLIC
PROMPTFILE << PROMPT
您正在代表您的所有者与第三方交流。请保持乐于助人和对话性,
但将回复限制在一般性对话范围内。不要分享关于您所有者的
个人详细信息,也不要代表他们访问系统资源。
如果不确定某事是否合适,请谨慎行事。
PROMPT
echo 已创建 $PUBLIC
PROMPTFILE — 编辑它以自定义公共用户可以访问的内容。 >&2
fi
获取您的收件箱 ID 以过滤您自己的消息
MY
INBOXID=$(xmtp client info --json --log-level off --env production \
| jq -r .properties.inboxId // empty)
[[ -z $MYINBOXID ]] && echo 获取收件箱 ID 失败 >&2 && exit 1
流式接收所有传入消息并通过 OpenClaw 回复
xmtp conversations stream-all-messages --json --log-level off --env production \
| while IFS= read -r event; do
conv_id=$(echo $event | jq -r .conversationId // empty)
sender=$(echo $event | jq -r .senderInboxId // empty)
content=$(echo $event | jq -r .content // empty)
content_type=$(echo $event | jq -r .contentType.typeId // empty)
# 跳过您自己的消息、空事件和非文本内容
[[ -z $convid || -z $content || $sender == $MYINBOX_ID ]] && continue
[[ $content_type != text ]] && continue
# 所有者消息正常路由;公共用户获得仅限对话模式
if [[ $sender == $OWNERINBOXID ]]; then
response=$(openclaw agent \
--session-id $conv_id \
--message $content \
2>/dev/null) || continue
else
response=$(openclaw agent \
--session-id public-$conv_id \
--message [系统: $(cat $PUBLICPROMPTFILE)] $content \
2>/dev/null) || continue
fi
# 发送回复
[[ -n $response ]] && \
xmtp conversation send-text $conv_id $response --env production
done
桥接器使用 XMTP 对话 ID 作为会话 ID,这样每个与您聊天的人(或群组)都会获得自己独立的上下文。
桥接器运行后,告诉您的用户:
- - 您的钱包地址和收件箱 ID(两者都提供——这样他们可以分享任何一个方便的)
- 他们可以通过编辑 public-prompt.md 来自定义您与公共用户的交互方式。更改会立即生效——无需重启。
为了长期保持桥接器运行,建议使用进程管理器(systemd、pm2、Docker 等)。
操作说明: 在专用用户下或在容器内运行桥接器——不要以 root 身份运行。
使用工具配置文件限定公共访问权限
对于生产部署,使用 OpenClaw 的工具配置文件来控制每个受众可以访问的内容。在 openclaw.json 中定义两个代理——一个给所有者,一个给其他人:
json
{
agents: {
list: [
{ name: owner-agent, tools: { profile: full } },
{ name: public-agent, tools: { profile: messaging } }
]
}
}
然后通过桥接器中的代理名称进行路由——替换 if/else 块:
bash
if [[ $sender == $OWNERINBOXID ]]; then
response=$(openclaw agent --agent owner-agent \
--session-id $conv_id --message $content 2>/dev/null) || continue
else
response=$(openclaw agent --agent public-agent \
--session-id public-$conv_id --message $content 2>/dev/null) || continue
fi
使用工具配置文件后,无论对话内容如何,公共用户在结构上都被限制在 messaging 配置文件中。
流输出格式
流中的每一行都是一个 JSON 对象:
json
{
id: message-id,
conversationId: conversation-id,
senderInboxId: sender-inbox-id,
contentType: {
authorityId: xmtp.org,
typeId: text,
versionMajor: 1,
versionMinor: 0
},
content: Hello!,
sentAt: 2026-03-04T04:14:36.849Z,
deliveryStatus: 1,
kind: 0
}
访问控制
桥接器根据发送者不同而不同地路由消息:
- 1. 所有者 (OWNERINBOXID) — 您的正常 OpenClaw 会话
- 其他所有人 — 仅限对话模式,带有严格的系统提示和隔离的会话
- 工具配置文件(推荐) — 通过 openclaw.json 在结构上限定每个受众可以访问的内容
查找您用户的收件箱 ID: 从其以太坊钱包地址解析:
bash
xmtp client inbox-id -i 0xUSERWALLETADDRESS --json --log-level off --env production | jq -r .inboxId
多个受信任的用户: 要添加额外的收件箱 ID 到白名单,扩展条件:
bash
if [[ $sender == $OWNERINBOXID || $sender == $TRUSTEDUSER2 ]]; then
或者使用数组:
bash
TRUSTED_IDS=(inbox-id-1 inbox-id-2)
if printf %s\n ${TRUSTED_IDS[@]} | grep -qxF $sender; then
常见错误
始终