wechat.SKILL.md 8.9 KB


name: wechat description: > Active WeChat operations via the local wecli CLI — search contacts, look up contact detail, message a THIRD PARTY on WeChat, or fetch/search filtered chat history. Use ONLY for out-of-band WeChat requests where the OpenClaw user explicitly asks the agent to reach someone else or inspect prior conversations. For replying to an ongoing WeChat DM that is currently being routed to the agent, do NOT use this skill — the @fmode/openclaw-wechat-agent channel plugin handles those replies automatically; just reply normally in the conversation. metadata: {

"openclaw":
  {
    "emoji": "💬",
    "requires": { "bins": ["wecli"] },
    "install":
      [
        {
          "id": "local",
          "kind": "shell",
          "label": "Build + link wecli from the local checkout",
          "commands":
            [
              "cd cli && npm install && npm run build && npm link"
            ],
          "bins": ["wecli"]
        }
      ]
  }

}

wechat

Use wecli for WeChat operations that the current conversation's channel plugin cannot perform by itself — i.e. whenever the user asks the agent to reach OUT of the current DM and do something on the WeChat account.

When to Use

USE this skill when:

  • User explicitly says "message/text/send-wechat to "
  • User asks "search my WeChat history with about "
  • User asks "who is " or "look up this WeChat contact"
  • User asks "what conversations have I had on WeChat lately"
  • User asks to count / summarize / filter past messages by wxid or time range
  • When NOT to Use

    🚫 DON'T use this skill when:

    • Replying in the current WeChat conversation the agent is already talking in — OpenClaw's @fmode/openclaw-wechat-agent channel plugin auto-delivers your reply. Calling wecli messages send on the same recipient would cause a duplicate message.
    • Telegram / Signal / WhatsApp / iMessage → use those channels / skills.
    • Enterprise WeChat (企业微信) → needs a separate corp-wechat integration; wecli does NOT wrap /contacts/corp-*.
    • Moments / 朋友圈 (/sns/*), 视频号 (/finder/:name), profile management → intentionally out of scope for wecli (see cli/README.md).
    • Destructive group operations (create group, disband group, remove members, admin operations) → not supported; require human-in-the-loop.

    Requirements

    • wecli on $PATH. Install with the local install entry above, or run node <repo>/cli/dist/wecli.js directly.
    • Reachable wechat-agent backend (default http://8.138.37.248/api/wechat-agent).
    • apiBase configured via ONE of:
      • WECHAT_API_BASE env var
      • ~/.wecli/config.json{"apiBase":"..."}
      • ~/.openclaw/wechat-credentials.json{"wechatApiBase":"..."} (legacy, may already exist)
    • (Optional) appId for multi-device isolation — when multiple WeChat accounts share the same backend, pass --app-id <GEWE_APP_ID> or set via:
      • WECHAT_APP_ID env var
      • ~/.wecli/config.json{"apiBase":"...","appId":"wx_xxx"}
      • If omitted, the backend uses its default device (single-device setups need no change).

    Verify with wecli check-online — should print online yes.

    Common Commands

    Check connectivity

    wecli check-online                     # human-readable
    wecli check-online --json              # {"ok":true,"online":true,...}
    

    Look up a contact

    # Find someone by fuzzy keyword (name / wxid fragment / remark)
    wecli contacts search "zleo" --json | jq
    
    # Get full detail for a known wxid
    wecli contacts detail wxid_m6fljlymhrny22 --json
    
    # Dump the whole address book (cached variant is faster but may be stale)
    wecli contacts list --cache --json | jq '.contacts | length'
    

    Search chat history

    # All messages from a specific contact, last 20
    wecli messages history --wxid wxid_ay08t6ugo2h922 --limit 20 --json
    
    # Incremental: everything since a timestamp (server-side filter + dedupe)
    wecli messages history --since 2026-04-21T16:00:00.000Z --json
    
    # Only outbound (what the bot has sent)
    wecli messages history --direction sent --limit 50 --json
    
    # Pipe to jq for text-search
    wecli messages history --limit 200 --json \
      | jq '.messages[] | select(.content | test("合同|报价"; "i"))'
    

    Send a message to a third party

    # 1. Find the recipient's wxid first — NEVER guess.
    wecli contacts search "张三" --json
    
    # 2. After user confirms the wxid:
    wecli messages send \
      --to wxid_zhangsan \
      --text "今晚 7 点餐厅见" \
      --json
    
    # Group @mention (ats = comma-separated wxids)
    wecli messages send \
      --to 12345@chatroom \
      --text "@张三 开会了" \
      --at wxid_zhangsan \
      --json
    

    List recent conversations

    wecli conversations list --json | jq '.conversations[:10]'
    

    Safety Rules

    1. Never invent a wxid. If the user names someone without giving a wxid, run wecli contacts search "<name>" first and let the user pick.
    2. Confirm before sending. For every messages send, echo back the recipient (wxid + nickname/remark) and the message text, and wait for explicit user confirmation. Especially strict for:
      • First-time recipient (never messaged before)
      • Groups (messages fan out to many people)
      • Anything containing money / financial numbers / account details
    3. No bulk send. Never loop wecli messages send across many wxids without explicit per-recipient approval. If the user asks for "mass notify", ask them to confirm the list and then send sequentially with a short delay, NOT in parallel.
    4. Do not reply to the current DM via this tool. If the user is chatting with you on WeChat via the channel plugin, replies are routed automatically — wecli messages send --to <same wxid> would duplicate.
    5. Respect the ignore list. Never message weixin, fmessage, medianote, filehelper, floatbottle, or any wxid starting with gh_ (public accounts) — those are system channels, replies go nowhere useful.

    Example Workflows

    Workflow A — "帮我给李总发微信说会议改到周五"

    # Step 1: resolve the wxid
    wecli contacts search "李总" --json
    # → agent finds { wxid: "wxid_lilaozong", nickName: "李总", remark: "朝阳客户李总" }
    
    # Step 2: confirm with user
    # Agent: "Found 李总 (wxid_lilaozong, remark '朝阳客户李总'). Send '会议改到周五'? [y/N]"
    
    # Step 3: send after user confirmation
    wecli messages send --to wxid_lilaozong --text "会议改到周五" --json
    # → {"ok": true, "ret": 200, ...}
    
    # Step 4: report back
    # Agent: "Sent."
    

    Workflow B — "zleo 最近跟我说了啥关于合同的"

    # No need to look up — user gave a recognizable nick. But verify first:
    wecli contacts search "zleo" --json
    # → wxid_m6fljlymhrny22
    
    # Fetch recent messages from that contact, then filter by keyword
    wecli messages history --wxid wxid_m6fljlymhrny22 --limit 200 --json \
      | jq '[.messages[] | select(.direction == "received" and (.content | test("合同|协议"; "i")))]'
    # → agent summarizes the matched lines
    

    Workflow C — periodic inbox scan (not for the channel plugin's auto-reply path!)

    # Last state: store the timestamp of the newest message seen previously.
    # This time, fetch only new ones since then:
    wecli messages history --since "$LAST_SEEN_TS" --direction received --json \
      | jq '.messages[] | {fromWxid, nickName, content, timestamp}'
    
    # IMPORTANT: if this scan's purpose is to auto-reply, STOP and use the
    # channel plugin instead. `wecli` is for one-off human-initiated queries.
    

    Troubleshooting

    • cannot determine apiBase — set WECHAT_API_BASE or create ~/.wecli/config.json. See cli/README.md for the full chain.
    • online NO (offline) — the bot account is logged out of WeChat. Re-scan the login QR code via the web UI at the backend's host, then retry.
    • Empty results from contacts search — the upstream POST /contacts/search field name differs between GEWE builds. wecli sends both keyword and query for compatibility; if still empty, fall back to wecli contacts list --cache and filter client-side.
    • messages send returns ret other than 200 — read the msg field; common causes are "recipient not a contact" (add first via the WeChat UI) and "rate limited" (wait and retry).

    Notes

    • Output is human-readable tables by default; pass --json everywhere when piping to jq or feeding back to the agent's reasoning loop.
    • wecli is zero-dep Node and ships as a single ~80 KiB bundled dist/wecli.js. The whole CLI + skill is designed to be copied into a second machine with nothing but node >= 20 and this repo's cli/ folder.
    • For the symmetric "incoming message auto-reply" side of the same backend, see the @fmode/openclaw-wechat-agent channel plugin at ../../channel-plugin/.