AI Image Generation with FLUX and OpenClaw: Building a Custom Skill
OpenClaw's extensible skill system lets you integrate any tool or API into your AI assistant workflow. In this tutorial, we'll walk through creating a custom skill that brings Black Forest Labs' FLUX image generation directly into OpenClaw.
What is FLUX?
FLUX is a family of state-of-the-art text-to-image models from Black Forest Labs (BFL), the team behind Stable Diffusion. The FLUX.2 lineup offers several models optimized for different use cases:
- flux-2-pro — Best balance of quality and speed (recommended)
- flux-2-max — Highest quality output, slower generation
- flux-2-klein-4b — Fastest generation, good for iteration
- flux-dev — Open model for experimentation
FLUX excels at photorealistic images, accurate text rendering, and following complex prompts with remarkable fidelity.
Prerequisites
Before we begin, you'll need:
- OpenClaw installed — Get it from openclaw.ai
- BFL API key — Sign up at api.bfl.ai
- Node.js 20+ — For the generation script
Step 1: Store Your API Key
First, let's securely store the BFL API key. Create a secrets directory in your OpenClaw workspace:
mkdir -p ~/.openclaw/workspace/.secrets
echo "your-api-key-here" > ~/.openclaw/workspace/.secrets/bfl.key
chmod 600 ~/.openclaw/workspace/.secrets/bfl.key
Step 2: Create the Skill Structure
OpenClaw skills follow a simple directory structure:
~/.openclaw/skills/flux/
├── SKILL.md # Main skill file (required)
├── scripts/
│ └── flux-gen.js # Generation script
└── references/
└── prompting.md # Prompting best practices
Create the directories:
mkdir -p ~/.openclaw/skills/flux/{scripts,references}
Step 3: Write the Generation Script
Create scripts/flux-gen.js:
#!/usr/bin/env node
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
import { join } from 'path';
import { homedir } from 'os';
const API_BASE = 'https://api.bfl.ai/v1';
const MODELS = ['flux-2-pro', 'flux-2-max', 'flux-2-klein-4b', 'flux-dev'];
// Load API key
const keyPath = join(homedir(), '.openclaw/workspace/.secrets/bfl.key');
if (!existsSync(keyPath)) {
console.error('Error: BFL API key not found at', keyPath);
process.exit(1);
}
const API_KEY = readFileSync(keyPath, 'utf8').trim();
async function generateImage(prompt, width = 1024, height = 1024, model = 'flux-2-pro') {
// Validate model
if (!MODELS.includes(model)) {
console.error(`Invalid model. Choose from: `);
process.exit(1);
}
console.log(`Submitting to …`);
// Submit request
const submitRes = await fetch(`/`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Key': API_KEY
},
body: JSON.stringify({
prompt,
width: Math.round(width / 32) * 32, // Must be multiple of 32
height: Math.round(height / 32) * 32
})
});
if (!submitRes.ok) {
const err = await submitRes.text();
console.error('Submit failed:', err);
process.exit(1);
}
const { id } = await submitRes.json();
console.log('Request ID:', id);
// Poll for result
let result;
while (true) {
const pollRes = await fetch(`/get_result?id=`, {
headers: { 'X-Key': API_KEY }
});
result = await pollRes.json();
console.log('Status:', result.status);
if (result.status === 'Ready') break;
if (result.status === 'Error') {
console.error('Generation failed:', result.error);
process.exit(1);
}
await new Promise(r => setTimeout(r, 1000));
}
// Download and save
console.log('Downloading…');
const imgRes = await fetch(result.result.sample);
const buffer = Buffer.from(await imgRes.arrayBuffer());
const outDir = join(homedir(), '.openclaw/workspace/generated');
mkdirSync(outDir, { recursive: true });
const outPath = join(outDir, `flux_.jpg`);
writeFileSync(outPath, buffer);
console.log(outPath);
return outPath;
}
// CLI
const [,, prompt, width, height, model] = process.argv;
if (!prompt) {
console.log('Usage: flux-gen.js "prompt" [width] [height] [model]');
console.log(`Models: `);
process.exit(1);
}
generateImage(prompt, parseInt(width) || 1024, parseInt(height) || 1024, model || 'flux-2-pro');
Make it executable:
chmod +x ~/.openclaw/skills/flux/scripts/flux-gen.js
Step 4: Create the SKILL.md
The SKILL.md file tells OpenClaw when and how to use the skill. Create ~/.openclaw/skills/flux/SKILL.md:
—
name: flux
description: Generate images using FLUX AI models from Black Forest Labs. Use when asked to create, generate, or make images, artwork, illustrations, or visual content.
—
# FLUX Image Generation
Generate high-quality images using Black Forest Labs' FLUX models.
## Quick Usage
```bash
node ~/.openclaw/skills/flux/scripts/flux-gen.js "your prompt" [width] [height] [model]
Available Models
| Model | Best For | Speed |
|---|---|---|
| flux-2-pro | General use, balanced quality/speed | Medium |
| flux-2-max | Highest quality output | Slow |
| flux-2-klein-4b | Quick iterations, drafts | Fast |
| flux-dev | Experimentation | Medium |
Prompting Tips
- Be specific and descriptive
- Include style cues: "photorealistic", "digital art", "watercolor"
- Specify lighting: "golden hour", "studio lighting", "dramatic shadows"
- Define composition: "centered", "wide shot", "close-up portrait"
- For dark backgrounds, specify hex colors: "#0d1117"
Dimensions
- Width and height must be multiples of 32
- Common sizes: 1024×1024, 1920×1080, 1024×1792 (portrait)
- Max dimensions vary by model
Output
Generated images are saved to:
~/.openclaw/workspace/generated/flux_[timestamp].jpg
## Step 5: Add Prompting References
Create `references/prompting.md` with best practices:
```markdown
# FLUX Prompting Best Practices
## Structure Your Prompts
1. **Subject** — What is the main focus?
2. **Style** — Photorealistic, illustration, oil painting?
3. **Lighting** — Natural, studio, dramatic?
4. **Composition** — Close-up, wide shot, centered?
5. **Details** — Colors, textures, mood
## Example Prompts
**Tech visualization:**
> Abstract digital cloud computing visualization, flowing data streams,
> network nodes connected by glowing blue lines (#58a6ff), dark background
> (#0d1117), minimalist tech aesthetic, cinematic depth
**Portrait:**
> Professional headshot of a software developer, natural lighting,
> neutral background, sharp focus, confident expression
**Product shot:**
> Modern laptop on minimal desk, soft window light from left,
> clean white background, commercial photography style
Step 6: Register the Skill
Add your skills directory to OpenClaw's configuration. Edit ~/.openclaw/openclaw.json:
{
"skills": {
"load": {
"extraDirs": ["/home/yourusername/.openclaw/skills"]
},
"entries": {
"flux": {
"enabled": true
}
}
}
}
Restart OpenClaw to load the skill:
openclaw gateway restart
Using the Skill
Now you can simply ask OpenClaw to generate images:
"Generate an image of a futuristic city skyline at sunset"
OpenClaw will automatically invoke the FLUX skill, run the generation script, and return the path to your image.
Advanced: Banner Images
For website hero images, use wide aspect ratios:
node ~/.openclaw/skills/flux/scripts/flux-gen.js \
"Abstract cloud computing visualization, blue glow on dark background" \
1920 600 flux-2-pro
Conclusion
Custom skills transform OpenClaw from a chatbot into a powerful automation platform. The FLUX skill we built demonstrates the pattern:
- Secure credentials — Store API keys safely
- Wrapper script — Handle API calls and file I/O
- SKILL.md — Describe when to trigger and how to use
- References — Document best practices for the AI
This same pattern works for any API or CLI tool you want to integrate. OpenClaw's skill system is your gateway to infinite extensibility.
Ready to create more skills? Check out the OpenClaw documentation and share your creations on ClawHub.