Docs / Lark / Feishu chat

Drive an agent from Lark / Feishu

Send a task in a Lark (international) or Feishu (China) chat and your agent does it — from your phone, no terminal needed after setup. You bring your own bot; its credentials stay on your machine.

The model

One bot → one owner (concord im) → many bound chats → each chat drives one agent. The owner holds the bot's single connection, keeps the chat→room bindings, and relays messages both ways. Each agent is just a resident process doing the work in a room.

Prerequisites

1 · Create + log in your bot — scan one QR

concord login lark --qr      # Lark (international)
concord login feishu --qr    # Feishu (China)

A QR renders in your terminal. Open the Lark/Feishu app on your phone and scan it, then tap Agree. That one scan:

Then put the bot in a chat:

Prefer the developer console?

You can also create a Custom App manually (Add the Bot capability, set event subscription to long connection / WebSocket — not webhook, subscribe to im.message.receive_v1, add the message scopes, and release a version), then store creds with concord login lark --app-id <id> --app-secret <secret>. The QR flow avoids all of that.

2 · Start the IM owner

concord im            # background daemon — one per bot
concord im status     # is it up?
concord im logs -f     # what is it doing
concord im stop       # stop it (bindings are kept)
One bot = one owner

Don't run two concord im for the same app, and don't point another listener at the same bot — Lark delivers each event to only one connection, so a second listener steals messages at random.

3 · Bind a chat to an agent

In the chat (group: @ the bot; private: just send):

/concord-bind

The bot replies with a ready-to-copy command. Run it on the machine where the agent should work — its working directory is wherever you run it:

concord host claude --bind <chat_id>   # the bot fills in the chat_id for you
# for a group the command includes a budget:
concord host claude --bind <chat_id> --budget 1000000

The agent comes up, joins its room, and posts a short “connected” note in the chat. From now on, just send tasks in the chat. Re-bind to a different agent with --force; want a different folder? cd there first (or pass --cwd).

4 · Daily use — from the chat

5 · Manage from the terminal

concord list          # every agent + the owner, with status + bound chat
concord bindings      # chat → room bindings with end-to-end health
concord restart <id>  # restart, keeping its binding
concord shutdown      # stop owner + all agents, KEEP configs + bindings (reversible)
concord up            # bring the whole fleet back — no re-binding

See the CLI reference for the full command set and the fleet lifecycle.

Token safety

Enterprise tenants & troubleshooting

If you're not an org admin, the scan may succeed but the bot stays pending admin approval — creds are saved but messages won't route until an admin approves the app. Easiest workarounds: use a personal account (Feishu: register → pick 「个人使用」; Lark: sign up at larksuite.com), or ask your admin to create a Custom App and hand you the App ID + Secret.

SymptomMost likely cause
no <platform> credsRun concord login lark --qr (or feishu) and scan.
Scanned, creds saved, but messages don't reach the agentEnterprise tenant — the app is pending admin approval. Approve it, or use a personal account.
Group only answers when @-mentionedExpected — unless it's a solo group (you + bot), which the --qr scopes allow.
Bound, but nothing routesIs the owner running? concord list should show im-… as running (or run concord up).
Messages land erraticallyTwo listeners on one bot — keep one concord im per app.
Sender shows as a short id, not a nameAdd the optional contact:contact.base:readonly scope.