You've got your OpenClaw QQ bot running. It responds to messages, it runs skills, it does its thing. But what if you want to go beyond the built-in features? What if you need to programmatically control the bot, build custom integrations, or extend its behavior in ways the config file can't handle?
That's where the SDK comes in.
The OpenClaw SDK is your programmatic interface to the bot runtime. Instead of editing YAML files and restarting daemons, you can:
Think of it as the difference between using a GUI and writing a script — both get the job done, but the script scales.
On your Tencent Cloud Lighthouse instance:
# Install the OpenClaw SDK
npm install @openclaw/sdk
# Or if you prefer Python
pip install openclaw-sdk
// /opt/clawdbot/scripts/hello-sdk.js
const { OpenClawClient } = require('@openclaw/sdk');
const client = new OpenClawClient({
endpoint: 'http://localhost:8080',
apiKey: process.env.CLAWDBOT_API_KEY,
channel: 'qq'
});
// Listen for incoming messages
client.on('message', async (msg) => {
console.log(`[${msg.group_id}] ${msg.user_id}: ${msg.content}`);
// Custom logic: respond to specific keywords
if (msg.content.toLowerCase().includes('ping')) {
await client.sendMessage({
group_id: msg.group_id,
content: `Pong! Latency: ${Date.now() - msg.timestamp}ms`
});
}
});
// Start listening
client.connect();
console.log('SDK client connected');
Run it:
CLAWDBOT_API_KEY=your_key node /opt/clawdbot/scripts/hello-sdk.js
The SDK lets you intercept messages before they hit the default OpenClaw pipeline:
const { OpenClawClient } = require('@openclaw/sdk');
const client = new OpenClawClient({ /* config */ });
// Priority handler — runs before the AI model
client.registerHandler({
name: 'custom-router',
priority: 10, // Lower = higher priority
match: (msg) => msg.content.startsWith('/'),
handle: async (msg) => {
const [command, ...args] = msg.content.split(' ');
switch (command) {
case '/status':
return { reply: `Bot uptime: ${process.uptime()}s` };
case '/help':
return { reply: 'Available commands: /status, /help, /version' };
case '/version':
return { reply: `OpenClaw SDK v${client.version}` };
default:
return null; // Pass to default handler
}
}
});
client.connect();
Returning null from a handler passes the message to the next handler in the chain — eventually reaching the AI model if no handler claims it.
// /opt/clawdbot/skills/weather-skill.js
const { Skill } = require('@openclaw/sdk');
class WeatherSkill extends Skill {
constructor() {
super({
name: 'weather',
description: 'Get current weather for any city',
triggers: ['weather', 'temperature', 'forecast']
});
}
async execute(context) {
const city = context.extractEntity('city') || 'Beijing';
const weather = await this.fetchWeather(city);
return {
reply: `Weather in ${city}: ${weather.temp}C, ${weather.condition}. ` +
`Humidity: ${weather.humidity}%. Wind: ${weather.wind}km/h.`
};
}
async fetchWeather(city) {
const res = await fetch(
`https://api.weather.example.com/current?city=${encodeURIComponent(city)}`
);
return res.json();
}
}
module.exports = new WeatherSkill();
Register the skill:
const weatherSkill = require('./skills/weather-skill');
client.registerSkill(weatherSkill);
For more on skill development, check the OpenClaw Skills guide.
// Get the last 10 messages from a group
const history = await client.getConversationHistory({
group_id: 'group_123',
limit: 10
});
history.forEach(msg => {
console.log(`[${msg.timestamp}] ${msg.user_id}: ${msg.content}`);
});
Don't run SDK scripts in a terminal. Make them proper services:
# /etc/systemd/system/clawdbot-custom.service
[Unit]
Description=OpenClaw Custom SDK Scripts
After=clawdbot.service
Requires=clawdbot.service
[Service]
Type=simple
ExecStart=/usr/bin/node /opt/clawdbot/scripts/custom-handlers.js
Restart=always
RestartSec=5
Environment=NODE_ENV=production
EnvironmentFile=/opt/clawdbot/.env
[Install]
WantedBy=multi-user.target
sudo systemctl enable clawdbot-custom
sudo systemctl start clawdbot-custom
The SDK works best on a properly configured instance where the OpenClaw daemon is already running.
The SDK transforms your QQ bot from a configuration-driven tool into a programmable platform. Start with simple handlers, then build your way up to custom skills and integrations.
The config file gets you started. The SDK gets you everywhere else.