Use Feishu or Lark when you want to message your assistant from team chat.
Cue and OpenClaw use separate Feishu config files. Cue reads ~/.cue/config.json or ~/.cue/agents/<agent>/agent.json. OpenClaw uses ~/.openclaw/openclaw.json.
If you are setting up Feishu for OpenClaw inside a sandbox, use the OpenClaw docs instead: /openclaw/setup/feishu.

Before You Start

  • You need access to the Feishu Open Platform.
  • Lark tenants should use Lark Open Platform and set domain: "lark" in config.
  • Cue Feishu runtime currently reads config from ~/.cue/config.json or a per-agent override in ~/.cue/agents/<agent>/agent.json.
  • Cue currently uses Feishu WebSocket mode. Webhook mode is not part of the runtime contract.

Step 1: Create the Feishu App

In Feishu or Lark Open Platform:
  1. Create an app.
  2. Enable bot capability.
  3. Copy the App ID and App Secret.
  4. Enable event subscription / long connection.
  5. Add the event im.message.receive_v1.
  6. Publish the app in your tenant.
Treat the App Secret like a password. Do not commit it or paste it into public docs.

Working Permission Set

If you want the fastest first setup, use this known working batch-import permission set:
{
  "scopes": {
    "tenant": [
      "aily:file:read",
      "aily:file:write",
      "application:application.app_message_stats.overview:readonly",
      "application:application:self_manage",
      "application:bot.menu:write",
      "cardkit:card:read",
      "cardkit:card:write",
      "contact:user.employee_id:readonly",
      "corehr:file:download",
      "event:ip_list",
      "im:chat.access_event.bot_p2p_chat:read",
      "im:chat.members:bot_access",
      "im:message",
      "im:message.group_at_msg:readonly",
      "im:message.p2p_msg:readonly",
      "im:message:readonly",
      "im:message:send_as_bot",
      "im:resource"
    ],
    "user": [
      "aily:file:read",
      "aily:file:write",
      "im:chat.access_event.bot_p2p_chat:read"
    ]
  }
}
This is a working broad set, not a minimal audited permission list. Start here for first-time setup, then reduce it later if your tenant requires a tighter policy.

Step 2: Add the Config to Cue

Edit one of these files:
  • Global config: ~/.cue/config.json
  • Per-agent override: ~/.cue/agents/<agent>/agent.json
Start with global config unless you already run multiple agents with different channel identities. Example:
{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "<FEISHU_APP_ID>",
      "appSecret": "<FEISHU_APP_SECRET>",
      "domain": "feishu",
      "connectionMode": "websocket",
      "typingIndicator": true,
      "requireMention": true,
      "groupPolicy": "open",
      "dm": {
        "policy": "open",
        "allowFrom": ["*"]
      },
      "groupAllowFrom": ["*"],
      "includeThinking": true,
      "textChunkLimit": 2000
    }
  }
}
Notes:
  • For Lark tenants, change domain to "lark".
  • requireMention: true is the safest first configuration for group chats.
  • groupPolicy must be set explicitly if you want group messages to work.
  • channel-config.json is not the runtime source of truth for Feishu.

Optional: Bind One Feishu Chat to One Existing Cue Conversation

Use bindings when one specific Feishu DM or group chat should always route into one existing Cue conversation. This is especially useful when:
  • you want Feishu replies to appear in the same Cue conversation you already use in web
  • you want that chat to run with agentType: "openclaw" instead of normal Cue runtime
Example ~/.cue/agents/<agent>/agent.json:
{
  "channels": {
    "feishu": {
      "enabled": true,
      "appId": "<FEISHU_APP_ID>",
      "appSecret": "<FEISHU_APP_SECRET>",
      "domain": "feishu",
      "connectionMode": "websocket",
      "typingIndicator": true,
      "requireMention": false,
      "groupPolicy": "open",
      "groupAllowFrom": ["*"],
      "dm": {
        "policy": "open",
        "allowFrom": ["*"]
      },
      "textChunkLimit": 2000,
      "bindings": [
        {
          "chatId": "<FEISHU_CHAT_ID>",
          "conversationId": "<CUE_CONVERSATION_ID>",
          "agentType": "openclaw"
        }
      ]
    }
  }
}
Replace:
  • <FEISHU_CHAT_ID> with the Feishu chat id, often an oc_... value
  • <CUE_CONVERSATION_ID> with the Cue conversation UUID you want this chat to use
Quick way to find the chat id:
  • open the target Feishu chat
  • open chat settings / details
  • scroll near the bottom and look for a field like Chat ID: oc_xxxxxx
Notes:
  • Put this in agent.json when you want one specific local agent to own the Feishu connection and binding.
  • agentType can be cue or openclaw.
  • conversationId is the Cue conversation identity, not an OpenClaw session id.
  • Do not paste real App Secrets or production chat ids into committed config files or docs.

Step 3: Restart Cue

After saving config:
cue -m restart --json
If you use a specific agent:
cue -m restart --agent <agent> --json

Step 4: Validate

Check runtime status:
cue channel status --json
cue -m status --agent <agent> --json
Then send a small test:
  • DM the bot directly, or
  • mention it in a group chat if groupPolicy is enabled

Sandbox / code-server Setup

If you are doing this inside a Cue sandbox or code-server session, the same config belongs inside the sandbox home directory:
  • /home/user/.cue/config.json
  • /home/user/.cue/agents/<agent>/agent.json
Open the file in code-server, save the App ID and App Secret there, then restart Cue inside the sandbox terminal.

Troubleshooting

  • App shows offline or Feishu reports no long connection: Restart the target Cue worker and check cue -m status --agent <agent> --json.
  • DMs work but group messages do not: Check groupPolicy, requireMention, and your allowlists.
  • Feishu blocks the bot on missing permissions: Re-check the batch-import set above, especially im:message:send_as_bot, im:message:readonly, and im:chat.members:bot_access.
  • You edited channel-config.json and nothing changed: Move the config into agent.json or ~/.cue/config.json.
  • You run both Cue and OpenClaw: Confirm which App ID and App Secret belong to which runtime before changing anything.