{"skill":{"slug":"feishu-interactive-cards","displayName":"Feishu Interactive Cards","summary":"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.","description":"---\nname: feishu-interactive-cards\nversion: 1.0.2\ndescription: 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.\n---\n\n# Feishu Interactive Cards\n\n## Core Principle\n\n**When replying to Feishu and there is ANY uncertainty: send an interactive card instead of plain text.**\n\nInteractive cards let users respond via buttons rather than typing, making interactions faster and clearer.\n\n## When to Use\n\n**Must use interactive cards:**\n- User needs to make a choice (yes/no, multiple options)\n- Confirmation required before action\n- Displaying todos or task lists\n- Creating polls or surveys\n- Collecting form input\n- Any uncertain situation\n\n**Plain text is OK:**\n- Simple notifications (no response needed)\n- Pure data display (no interaction)\n- Confirmed command results\n\n**Example:**\n- Wrong: \"I deleted the file for you\" (direct execution)\n- Right: Send card \"Confirm delete file?\" [Confirm] [Cancel]\n\n## Quick Start\n\n### 1. Start Callback Server (Long-Polling Mode)\n\n```bash\ncd E:\\openclaw\\workspace\\skills\\feishu-interactive-cards\\scripts\nnode card-callback-server.js\n```\n\n**Features:**\n- Uses Feishu long-polling (no public IP needed)\n- Auto-reconnects\n- Sends callbacks to OpenClaw Gateway automatically\n\n### 2. Send Interactive Card\n\n```bash\n# Confirmation card\nnode scripts/send-card.js confirmation \"Confirm delete file?\" --chat-id oc_xxx\n\n# Todo list\nnode scripts/send-card.js todo --chat-id oc_xxx\n\n# Poll\nnode scripts/send-card.js poll \"Team activity\" --options \"Bowling,Movie,Dinner\" --chat-id oc_xxx\n\n# Custom card\nnode scripts/send-card.js custom --template examples/custom-card.json --chat-id oc_xxx\n```\n\n### 3. Use in Agent\n\nWhen Agent needs to send Feishu messages:\n\n```javascript\n// Wrong: Send plain text\nawait message({ \n  action: \"send\", \n  channel: \"feishu\", \n  message: \"Confirm delete?\" \n});\n\n// Right: Send interactive card\nawait exec({\n  command: `node E:\\\\openclaw\\\\workspace\\\\skills\\\\feishu-interactive-cards\\\\scripts\\\\send-card.js confirmation \"Confirm delete file test.txt?\" --chat-id ${chatId}`\n});\n```\n\n## Card Templates\n\nSee `examples/` directory for complete card templates:\n- `confirmation-card.json` - Confirmation dialogs\n- `todo-card.json` - Task lists with checkboxes\n- `poll-card.json` - Polls and surveys\n- `form-card.json` - Forms with input fields\n\nFor detailed card design patterns and best practices, see [references/card-design-guide.md](references/card-design-guide.md).\n\n## Callback Handling\n\nCallback server automatically sends all card interactions to OpenClaw Gateway. For detailed integration guide, see [references/gateway-integration.md](references/gateway-integration.md).\n\n**Quick example:**\n\n```javascript\n// Handle confirmation\nif (callback.data.action.value.action === \"confirm\") {\n  const file = callback.data.action.value.file;\n  \n  // ⚠️ SECURITY: Validate and sanitize file path before use\n  // Use OpenClaw's built-in file operations instead of shell commands\n  const fs = require('fs').promises;\n  const path = require('path');\n  \n  try {\n    // Validate file path (prevent directory traversal)\n    const safePath = path.resolve(file);\n    if (!safePath.startsWith(process.cwd())) {\n      throw new Error('Invalid file path');\n    }\n    \n    // Use fs API instead of shell command\n    await fs.unlink(safePath);\n    \n    // Update card\n    await updateCard(callback.context.open_message_id, {\n      header: { title: \"Done\", template: \"green\" },\n      elements: [\n        { tag: \"div\", text: { content: `File ${path.basename(safePath)} deleted`, tag: \"lark_md\" } }\n      ]\n    });\n  } catch (error) {\n    // Handle error\n    await updateCard(callback.context.open_message_id, {\n      header: { title: \"Error\", template: \"red\" },\n      elements: [\n        { tag: \"div\", text: { content: `Failed to delete file: ${error.message}`, tag: \"lark_md\" } }\n      ]\n    });\n  }\n}\n```\n\n## Best Practices\n\n### Card Design\n- Clear titles and content\n- Obvious button actions\n- Use `danger` type for destructive operations\n- Carry complete state in button `value` to avoid extra queries\n\n### Interaction Flow\n```\nUser request -> Agent decides -> Send card -> User clicks button \n-> Callback server -> Gateway -> Agent handles -> Update card/execute\n```\n\n### Error Handling\n- Timeout: Send reminder if user doesn't respond\n- Duplicate clicks: Built-in deduplication (3s window)\n- Failures: Update card to show error message\n\n### Performance\n- Async processing: Quick response, long tasks in background\n- Batch operations: Combine related actions in one card\n\n## Configuration\n\nConfigure in `~/.openclaw/openclaw.json`:\n\n```json\n{\n  \"channels\": {\n    \"feishu\": {\n      \"accounts\": {\n        \"main\": {\n          \"appId\": \"YOUR_APP_ID\",\n          \"appSecret\": \"YOUR_APP_SECRET\"\n        }\n      }\n    }\n  },\n  \"gateway\": {\n    \"enabled\": true,\n    \"port\": 18789,\n    \"token\": \"YOUR_GATEWAY_TOKEN\"\n  }\n}\n```\n\nCallback server reads config automatically.\n\n## Troubleshooting\n\n**Button clicks not working:**\n- Check callback server is running\n- Verify Feishu backend uses \"long-polling\" mode\n- Ensure `card.action.trigger` event is subscribed\n\n**Gateway not receiving callbacks:**\n- Start Gateway: `E:\\openclaw\\workspace\\scripts\\gateway.cmd`\n- Check token in `~/.openclaw\\openclaw.json`\n\n**Card display issues:**\n- Use provided templates as base\n- Validate JSON format\n- Check required fields\n\n## Security\n\n**⚠️ CRITICAL: Never pass user input directly to shell commands!**\n\nThis skill includes comprehensive security guidelines. Please read [references/security-best-practices.md](references/security-best-practices.md) before implementing callback handlers.\n\nKey security principles:\n- Always validate and sanitize user input\n- Use Node.js built-in APIs instead of shell commands\n- Implement proper permission checks\n- Prevent command injection vulnerabilities\n- Use event_id for deduplication\n\n## References\n\n- [Security Best Practices](references/security-best-practices.md) - **READ THIS FIRST!**\n- [Feishu Card Documentation](https://open.feishu.cn/document/ukTMukTMukTM/uczM3QjL3MzN04yNzcDN)\n- [OpenClaw Docs](https://docs.openclaw.ai)\n","topics":["Feishu"],"tags":{"latest":"1.0.2"},"stats":{"comments":0,"downloads":4081,"installsAllTime":154,"installsCurrent":25,"stars":6,"versions":3},"createdAt":1770382904659,"updatedAt":1778486065752},"latestVersion":{"version":"1.0.2","createdAt":1770386690427,"changelog":"Critical security fix: Prevent arbitrary file read via --template parameter. Added directory whitelist, file extension validation, and JSON format validation.","license":null},"metadata":null,"owner":{"handle":"leecyang","userId":"s1750vjewhh79h5cadsx397r3x83wb62","displayName":"leecyang","image":"https://avatars.githubusercontent.com/u/164771957?v=4"},"moderation":null}