Feishu runbook for agents
Read this when you are handling Feishu work and the normal anima command help is not enough: what the Feishu identifiers mean, which settings humans must configure, the direct API calls for what anima does not cover yet, and how to avoid blind retries.
The mental model
Your Feishu identity is a Feishu app with a bot account. Anima delivers Feishu messages to you and sends your replies back through that app. For ordinary visible output, use audited Anima commands: anima message send, anima message read, anima message update, anima file fetch, and anima message react.
Some Feishu actions do not have first-class Anima commands yet, such as creating a group or adding members to a group. For those, you may call Feishu OpenAPI directly with FEISHU_TENANT_ACCESS_TOKEN. Do not print or log that token. Anything a human should see still goes through anima message, so the action is visible in Anima's audit trail.
Do not start with web search. First inspect the delivery envelope and this runbook.
Feishu identifiers
chat_idstarts withoc_. It names a Feishu conversation. It can be a DM, a group, or a topic container. Use it withanima message send --chat-id <chat_id>.message_idusually starts withom_. It names a message. For a topic reply, pass the topicthread_idwhen present, otherwise the rootmessage_id, as--thread-ts.open_idusually starts withou_. It is the stable user identifier you normally want for mentions and human invites.user_idis the tenant user identifier. Use it only when the envelope or user gave it explicitly.app_idstarts withcli_. It identifies a Feishu app. Use an Anima-created agent's Feishu App ID when inviting another bot into a chat.
Display names are not identifiers. If you only have a name, ask the user to mention that person in Feishu and send the request again. The mention metadata gives Anima stable IDs.
Permissions are not visibility
Feishu has two separate gates:
- API permissions, also called scopes. These let the app perform actions like send messages, read group messages from users and bots, add group members, look up users by email or phone, or work with Feishu Drive and cloud documents. Users authorize these in Anima's Feishu setup flow and publish a new app version.
- App visibility or availability range. This controls which users can see or use the app. It is configured in the Feishu developer console or admin console. The app cannot grant itself wider visibility through OpenAPI.
If an API call says a scope is missing, ask the user to add the recommended permission and publish a new app version. If a member invite fails with 232024 and says users do not have app visibility, ask the user to add the target person, department, or all members to the app's visibility or availability range, save or publish that change, then retry.
Replying, reading, and editing
Use the envelope. In a Feishu chat:
anima message send --chat-id <chat_id> <<'ANIMA_MESSAGE'
<reply>
ANIMA_MESSAGEFor a topic, include the topic id:
anima message send --chat-id <chat_id> --thread-ts <thread_id_or_root_message_id> <<'ANIMA_MESSAGE'
<reply>
ANIMA_MESSAGEUse anima message read --chat-id <chat_id> when you need recent chat history. Add --thread-ts when you need a topic's thread history. Use anima message update --chat-id <chat_id> --message-ts <message_id> only for messages you sent.
Mentioning people
When you know a user's open_id, mention them in message text like this:
<mention open_id="ou_...">Name</mention>Anima sends that as a Feishu rich-text mention. Do not write raw @Name when the user needs a real mention. Do not invent an open_id from a name.
Creating a group
There is no first-class anima command for Feishu group creation yet.
Get at least one user
open_idfrom the envelope, usually the person who asked you. Do not guess people from display names.Call the chat-create API once:
curl -sS -X POST \ "https://open.feishu.cn/open-apis/im/v1/chats?user_id_type=open_id" \ -H "Authorization: Bearer $FEISHU_TENANT_ACCESS_TOKEN" \ -H "Content-Type: application/json" \ --data '{"name":"<chat_name>","description":"<description>","user_id_list":["<owner_open_id>"],"chat_mode":"group","chat_type":"private"}'Read the JSON response. If it contains
chat_id, the group exists.Send the visible confirmation or first message with
anima message send --chat-id <chat_id>.
Do not create another group just because you are unsure whether the first call worked. Check the response first.
Inviting people or bots
There is no first-class anima command for invites yet. The current agent must already be in the chat, and you need the chat's oc_... id from the envelope.
A human teammate is invited by open_id:
- If the teammate appears in the envelope or readable history, use their
open_id. - If the user gives an email address or phone number, resolve it to an
open_idfirst. - If you only have a tenant
user_id, invite withmember_id_type=user_idand pass that id. - If you only have a display name, ask the user to mention the teammate in Feishu and send the request again, or to give an email, phone number,
open_id, oruser_id.
Resolve an email or phone number, passing only the fields you have:
curl -sS -X POST \
"https://open.feishu.cn/open-apis/contact/v3/users/batch_get_id?user_id_type=open_id" \
-H "Authorization: Bearer $FEISHU_TENANT_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
--data '{"emails":["<email>"],"mobiles":["<phone>"],"include_resigned":false}'If Feishu returns no matching user, ask the user to mention the teammate in Feishu and send the request again, or for another deterministic identifier. Then invite:
curl -sS -X POST \
"https://open.feishu.cn/open-apis/im/v1/chats/<chat_id>/members?member_id_type=open_id" \
-H "Authorization: Bearer $FEISHU_TENANT_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
--data '{"id_list":["<target_open_id>"]}'Another Anima-created Feishu bot is invited by that agent's Feishu App ID (cli_...), not by its bot open_id: the same members call with member_id_type=app_id and the App ID in id_list. If you cannot see the App ID, ask the user to copy it from the target agent's Profile page. Do not guess it from the bot name.
When invite calls fail:
232024or "visibility of the app" means app visibility is missing for the target user. Ask the user to add the target person to the app's availability range, save or publish that change, then retry. An external collaborator may also need external collaboration permission.- A permission error means the current app probably lacks the group-member or user-lookup scope, or the new app version has not been published.
- A group management error means this bot may not be allowed to manage members in that specific group.
Report the specific error and the next human action. Do not keep trying the same identifiers after the platform has returned a configuration error.
Safe direct API use
Use FEISHU_TENANT_ACCESS_TOKEN only as an HTTP bearer token. Do not echo it, write it into a file, paste it into chat, or include it in command output. It is acceptable to check whether it exists without printing the value.
Keep visible communication separate from direct API work. A curl call may create a group or invite a member, but the human-facing explanation should still be sent with anima message send.