Build, send, and update Feishu interactive cards.
Prefer keeping the main skill concise; only when the task explicitly needs card examples, then read the references/ JSON templates under it.
Base URL: https://open.feishu.cn/open-apis/im/v1
When to use
Use it directly when the user has these needs:
- Send an interactive card to a certain
open_id、chat_idor user - Build a Feishu message card with buttons, notes, and dividers
- Send a JSON card as an
interactivemessage - After the user clicks a card button, need to handle based on the
action.valuein the callback - A card has already been sent, and now the same message needs to be updated instead of resent
Token acquisition
This skill reuses by default the system token capability provided by feishu-user-auth .
Priority order is as follows:
- If
feishu-authis already in PATH, execute directly:
feishu-auth system-token
- If there is no PATH command, execute the bin in the installation directory:
./.agents/skills/feishu-user-auth/bin/feishu-auth.js system-token
For global installation:
~/.agents/skills/feishu-user-auth/bin/feishu-auth.js system-token
If the returned value is JSON, take the accessToken in it as the Authorization: Bearer <token>。
Send card
POST /open-apis/im/v1/messages?receive_id_type=open_id
POST /open-apis/im/v1/messages?receive_id_type=chat_id
Request body:
{
"receive_id": "ou_xxx",
"msg_type": "interactive",
"content": "{\"config\":{\"wide_screen_mode\":true},\"header\":{\"title\":{\"tag\":\"plain_text\",\"content\":\"标题\"}},\"elements\":[...]}"
}
Key points:
msg_typemust beinteractivecontentmust be "stringified JSON", not an objectreceive_id_typemust match the type ofreceive_idtypes are consistent
Card structure
{
"config": { "wide_screen_mode": true },
"header": {
"title": { "tag": "plain_text", "content": "标题" },
"template": "blue"
},
"elements": [
{
"tag": "div",
"text": { "tag": "lark_md", "content": "**加粗内容**" }
},
{
"tag": "action",
"actions": [
{
"tag": "button",
"text": { "tag": "plain_text", "content": "确认" },
"type": "primary",
"value": { "action": "confirm" }
}
]
}
]
}
Common elements:
div: text blockhr: divideraction: button areanote: note area
Callback and update
After the user clicks a button, the callback event usually focuses on:
{
"type": "card.action.trigger",
"action": {
"value": {
"action": "confirm",
"data": "extra_info"
}
}
}
After handling the callback, the original card message can be updated:
PATCH /open-apis/im/v1/messages/{message_id}
Reference templates
Only when the task needs ready-made templates, then read these files:
references/card-alert.jsonreferences/card-morning-briefing.jsonreferences/card-skill-test.json
Best practices
- Buttons must carry
value, otherwise the callback is hard to identify the specific action. - When the state needs to be changed, prefer updating the original card to avoid repeated flooding.
- Use the
dangertype for dangerous operation buttons. - Before sending a card, first confirm whether
receive_id_typeandreceive_idmatch. - If
feishu-auth system-tokenreturns JSON, do not stuff the entire JSON as-is into the request header; only takeaccessToken。