We build custom applications 5x faster and cheaper 🚀
Book a Free Consultation
Stuck on an error? Book a 30-minute call with an engineer and get a direct fix + next steps. No pressure, no commitment.
Quick direct answer: Build a small, well-scoped OpenClaw skill that acts as a bridge: register a Feishu (Lark) app to get app credentials, implement Feishu authentication (tenant access token or OAuth as required), create a webhook endpoint that validates Feishu requests, store credentials securely in ClawHub (or an equivalent secret store) and environment variables, and have the skill invoke Feishu’s REST APIs to send messages or take actions. Keep long-lived state and scheduling outside the OpenClaw agent runtime, verify tokens/signatures on every request, and instrument logs and metrics so you can debug by inspecting API responses, scopes, and ClawHub invocation logs.
// Node.js example using fetch-style API
// <b>//</b> Install node-fetch or use Node 18+ built-in fetch
const fetch = require('node-fetch');
const FEISHU_TOKEN_URL = 'https://open.feishu.cn/open-apis/auth/v3/tenant_access_token/internal/';
const FEISHU_MESSAGE_URL = 'https://open.feishu.cn/open-apis/message/v4/send/';
const APP_ID = process.env.FEISHU_APP_ID;
const APP_SECRET = process.env.FEISHU_APP_SECRET;
async function getTenantToken() {
// <b>//</b> Acquire tenant token using app_id/app_secret
const resp = await fetch(FEISHU_TOKEN_URL, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ app_id: APP_ID, app_secret: APP_SECRET })
});
const body = await resp.json();
if (!resp.ok) throw new Error('Token fetch failed: ' + JSON.stringify(body));
// <b>//</b> body.tenant_access_token is the token field per Feishu docs versions
return { token: body.tenant_access_token, expire: Date.now() + (body.expire || 3600) * 1000 };
}
async function sendTextMessage(tenantToken, receiveId, text) {
// <b>//</b> Send a simple text message. Confirm payload shape (content often must be a JSON string).
const payload = {
receive_id: receiveId,
msg_type: 'text',
content: JSON.stringify({ text })
};
const resp = await fetch(FEISHU_MESSAGE_URL, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${tenantToken}`
},
body: JSON.stringify(payload)
});
const body = await resp.json();
if (!resp.ok || body.code !== 0) {
// <b>//</b> Log the full response for debugging
throw new Error('Send failed: ' + JSON.stringify(body));
}
return body;
}
// <b>//</b> Example run (wrap in your skill invocation)
(async () => {
try {
const { token } = await getTenantToken();
const result = await sendTextMessage(token, 'REPLACE_WITH_RECEIVE_ID', 'Hello from OpenClaw skill');
console.log('Message sent', result);
} catch (err) {
console.error('Error', err);
}
})();
Speak one‑on‑one with a senior engineer about your no‑code app, migration goals, and budget. In just half an hour you’ll leave with clear, actionable next steps—no strings attached.
1
Direct answer: The Feishu Bridge most often fails to obtain a tenant_access_token because the flow/endpoint being used requires the app to be installed/authorized by the tenant (or a different auth flow) and you’re attempting to exchange only App ID/App Secret without that tenant authorization, or because the request uses the wrong endpoint/parameters or malformed credentials.
2
Feishu webhooks are rejected because the Bridge’s verifier computes a different signature than Feishu sent. Common causes: wrong app secret, the request body was changed (JSON parsed/pretty-printed or middleware consumed the raw stream), incorrect canonical string (Feishu uses timestamp + "\n" + body), encoding/base64 mismatches, or replay/timestamp checks failing.
Checklist to resolve:
// Node.js Express example: preserve raw body for verification
const crypto = require('crypto');
app.use(express.json({
verify: (req, res, buf) => { req.rawBody = buf } // preserve raw bytes
}));
app.post('/webhook', (req, res) => {
// // compute signature exactly as Feishu expects
const timestamp = req.headers['x-lark-timestamp'];
const secret = process.env.FEISHU_APP_SECRET;
const base = `${timestamp}\n${req.rawBody}`;
const sig = crypto.createHmac('sha256', secret).update(base).digest('base64');
if (sig !== req.headers['x-lark-signature']) return res.status(401).end();
// forward to OpenClaw Bridge runtime
res.status(200).end();
});
3
Direct answer: Feishu event payloads often fail to map because their JSON envelope, field names and nesting, optional encryption/signature wrapper, or content-type differ from the exact OpenClaw event schema the bridge expects. When required keys are missing or differently named, the bridge mapping step throws parsing errors.
Typical causes and practical checks:
4
The Feishu Bridge hits 429s or timeouts because your agents/skills are sending more requests or concurrent connections than Feishu permits, or because retries and blocking code in the OpenClaw runtime create bursts. Missing backoff, shared credentials across many agents, lack of queuing, or slow network calls inside the agent runtime amplify the problem.
This prompt helps an AI assistant understand your setup and guide you through the fix step by step, without assuming technical knowledge.
From startups to enterprises and everything in between, see for yourself our incredible impact.
Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We’ll discuss your project and provide a custom quote at no cost.Â