feishu-interactive-cards
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:
- User needs to make a choice (yes/no, multiple options)
- Confirmation required before action
- Displaying todos or task lists
- Creating polls or surveys
- Collecting form input
- Any uncertain situation
Plain text is OK:
- Simple notifications (no response needed)
- Pure data display (no interaction)
- Confirmed command results
Example:
- Wrong: "I deleted the file for you" (direct execution)
- Right: Send card "Confirm delete file?" [Confirm] [Cancel]
Quick Start
1. Start Callback Server (Long-Polling Mode)
cd E:\openclaw\workspace\skills\feishu-interactive-cards\scripts
node card-callback-server.js
Features:
- Uses Feishu long-polling (no public IP needed)
- Auto-reconnects
- Sends callbacks to OpenClaw Gateway automatically
2. Send Interactive Card
# Confirmation card
node scripts/send-card.js confirmation "Confirm delete file?" --chat-id oc_xxx
# Todo list
node scripts/send-card.js todo --chat-id oc_xxx
# Poll
node scripts/send-card.js poll "Team activity" --options "Bowling,Movie,Dinner" --chat-id oc_xxx
# Custom 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 fields
For 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;
// Execute operation
await exec({ command: `rm ${file}` });
// Update card
await updateCard(callback.context.open_message_id, {
header: { title: "Done", template: "green" },
elements: [
{ tag: "div", text: { content: `File ${file} deleted`, tag: "lark_md" } }
]
});
}
Best Practices
Card Design
- Clear titles and content
- Obvious button actions
- Use
dangertype for destructive operations - Carry complete state in button
valueto avoid extra queries
Interaction Flow
User request -> Agent decides -> Send card -> User clicks button
-> Callback server -> Gateway -> Agent handles -> Update card/execute
Error Handling
- Timeout: Send reminder if user doesn't respond
- Duplicate clicks: Built-in deduplication (3s window)
- Failures: Update card to show error message
Performance
- Async processing: Quick response, long tasks in background
- Batch operations: Combine related actions in one card
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:
- Check callback server is running
- Verify Feishu backend uses "long-polling" mode
- Ensure
card.action.triggerevent is subscribed
Gateway not receiving callbacks:
- Start Gateway:
E:\openclaw\workspace\scripts\gateway.cmd - Check token in
~/.openclaw\openclaw.json
Card display issues:
- Use provided templates as base
- Validate JSON format
- Check required fields