Feishu Interactive Cards
by @leecyang
Create and send interactive cards to Feishu (Lark) with buttons, forms, polls, and rich UI elements. Use when replying to Feishu messages and there is ANY uncertainty - send an interactive card instead of plain text to let users choose via buttons. Automatically handles callbacks via long-polling connection. Use for confirmations, choices, forms, todos, polls, or any scenario requiring user interaction in Feishu.
clawhub install feishu-interactive-cardsπ About This Skill
name: feishu-interactive-cards version: 1.0.2 description: Create and send interactive cards to Feishu (Lark) with buttons, forms, polls, and rich UI elements. Use when replying to Feishu messages and there is ANY uncertainty - send an interactive card instead of plain text to let users choose via buttons. Automatically handles callbacks via long-polling connection. Use for confirmations, choices, forms, todos, polls, or any scenario requiring user interaction in Feishu.
Feishu Interactive Cards
Core Principle
When replying to Feishu and there is ANY uncertainty: send an interactive card instead of plain text.
Interactive cards let users respond via buttons rather than typing, making interactions faster and clearer.
When to Use
Must use interactive cards:
Plain text is OK:
Example:
Quick Start
1. Start Callback Server (Long-Polling Mode)
cd E:\openclaw\workspace\skills\feishu-interactive-cards\scripts
node card-callback-server.js
Features:
2. Send Interactive Card
# Confirmation card
node scripts/send-card.js confirmation "Confirm delete file?" --chat-id oc_xxxTodo list
node scripts/send-card.js todo --chat-id oc_xxxPoll
node scripts/send-card.js poll "Team activity" --options "Bowling,Movie,Dinner" --chat-id oc_xxxCustom card
node scripts/send-card.js custom --template examples/custom-card.json --chat-id oc_xxx
3. Use in Agent
When Agent needs to send Feishu messages:
// Wrong: Send plain text
await message({
action: "send",
channel: "feishu",
message: "Confirm delete?"
});// Right: Send interactive card
await exec({
command: node E:\\openclaw\\workspace\\skills\\feishu-interactive-cards\\scripts\\send-card.js confirmation "Confirm delete file test.txt?" --chat-id ${chatId}
});
Card Templates
See examples/ directory for complete card templates:
confirmation-card.json - Confirmation dialogstodo-card.json - Task lists with checkboxespoll-card.json - Polls and surveysform-card.json - Forms with input fieldsFor detailed card design patterns and best practices, see references/card-design-guide.md.
Callback Handling
Callback server automatically sends all card interactions to OpenClaw Gateway. For detailed integration guide, see references/gateway-integration.md.
Quick example:
// Handle confirmation
if (callback.data.action.value.action === "confirm") {
const file = callback.data.action.value.file;
// β οΈ SECURITY: Validate and sanitize file path before use
// Use OpenClaw's built-in file operations instead of shell commands
const fs = require('fs').promises;
const path = require('path');
try {
// Validate file path (prevent directory traversal)
const safePath = path.resolve(file);
if (!safePath.startsWith(process.cwd())) {
throw new Error('Invalid file path');
}
// Use fs API instead of shell command
await fs.unlink(safePath);
// Update card
await updateCard(callback.context.open_message_id, {
header: { title: "Done", template: "green" },
elements: [
{ tag: "div", text: { content: File ${path.basename(safePath)} deleted, tag: "lark_md" } }
]
});
} catch (error) {
// Handle error
await updateCard(callback.context.open_message_id, {
header: { title: "Error", template: "red" },
elements: [
{ tag: "div", text: { content: Failed to delete file: ${error.message}, tag: "lark_md" } }
]
});
}
}
Best Practices
Card Design
danger type for destructive operationsvalue to avoid extra queriesInteraction Flow
User request -> Agent decides -> Send card -> User clicks button
-> Callback server -> Gateway -> Agent handles -> Update card/execute
Error Handling
Performance
Configuration
Configure in ~/.openclaw/openclaw.json:
{
"channels": {
"feishu": {
"accounts": {
"main": {
"appId": "YOUR_APP_ID",
"appSecret": "YOUR_APP_SECRET"
}
}
}
},
"gateway": {
"enabled": true,
"port": 18789,
"token": "YOUR_GATEWAY_TOKEN"
}
}
Callback server reads config automatically.
Troubleshooting
Button clicks not working:
card.action.trigger event is subscribedGateway not receiving callbacks:
E:\openclaw\workspace\scripts\gateway.cmd~/.openclaw\openclaw.jsonCard display issues:
Security
β οΈ CRITICAL: Never pass user input directly to shell commands!
This skill includes comprehensive security guidelines. Please read references/security-best-practices.md before implementing callback handlers.
Key security principles:
References
β‘ When to Use
π‘ Examples
1. Start Callback Server (Long-Polling Mode)
cd E:\openclaw\workspace\skills\feishu-interactive-cards\scripts
node card-callback-server.js
Features:
2. Send Interactive Card
# Confirmation card
node scripts/send-card.js confirmation "Confirm delete file?" --chat-id oc_xxxTodo list
node scripts/send-card.js todo --chat-id oc_xxxPoll
node scripts/send-card.js poll "Team activity" --options "Bowling,Movie,Dinner" --chat-id oc_xxxCustom card
node scripts/send-card.js custom --template examples/custom-card.json --chat-id oc_xxx
3. Use in Agent
When Agent needs to send Feishu messages:
// Wrong: Send plain text
await message({
action: "send",
channel: "feishu",
message: "Confirm delete?"
});// Right: Send interactive card
await exec({
command: node E:\\openclaw\\workspace\\skills\\feishu-interactive-cards\\scripts\\send-card.js confirmation "Confirm delete file test.txt?" --chat-id ${chatId}
});
βοΈ Configuration
Configure in ~/.openclaw/openclaw.json:
{
"channels": {
"feishu": {
"accounts": {
"main": {
"appId": "YOUR_APP_ID",
"appSecret": "YOUR_APP_SECRET"
}
}
}
},
"gateway": {
"enabled": true,
"port": 18789,
"token": "YOUR_GATEWAY_TOKEN"
}
}
Callback server reads config automatically.
π Tips & Best Practices
Card Design
danger type for destructive operationsvalue to avoid extra queriesInteraction Flow
User request -> Agent decides -> Send card -> User clicks button
-> Callback server -> Gateway -> Agent handles -> Update card/execute