Best use case
Text-to-Image Generation is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
## Metadata
Teams using Text-to-Image Generation should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
$curl -o ~/.claude/skills/text-to-image/SKILL.md --create-dirs "https://raw.githubusercontent.com/0gfoundation/0g-agent-skills/main/skills/compute/text-to-image/SKILL.md"
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/text-to-image/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How Text-to-Image Generation Compares
| Feature / Agent | Text-to-Image Generation | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
## Metadata
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
SKILL.md Source
# Text-to-Image Generation
## Metadata
- **Category**: compute
- **SDK**: `@0glabs/0g-serving-broker` ^0.6.5, `ethers` ^6.13.0
- **Activation Triggers**: "generate image", "text-to-image", "Flux", "image generation", "create
image"
## Purpose
Generate images from text prompts using 0G Compute Network providers running Flux Turbo. Supports
multiple resolutions and batch generation.
## Prerequisites
- Node.js >= 22
- `@0glabs/0g-serving-broker` and `ethers` installed
- Funded and acknowledged provider with `text-to-image` service
- `.env` with `PRIVATE_KEY`, `RPC_URL`, `PROVIDER_ADDRESS`
## Quick Workflow
1. Initialize broker
2. Get service metadata (endpoint, model)
3. Build request body with prompt, size, and count
4. Generate auth headers **with request body** (required for signing)
5. Make image generation request
6. Extract ChatID from `ZG-Res-Key` header ONLY (no body fallback)
7. **Call `processResponse(providerAddress, chatID)`** — no usage data needed
## Core Rules
### ALWAYS
- Include request body when generating auth headers (signing requirement)
- Get ChatID from `ZG-Res-Key` header only (no body fallback for images)
- Call `processResponse()` after every generation
- Use correct `processResponse()` param order: `(providerAddress, chatID, usageData)`
- Acknowledge provider before first use
- Start with smaller dimensions for cost-effective testing
### NEVER
- Skip including the body in `getRequestHeaders()` for image requests
- Try to extract ChatID from the response body (images only have header)
- Generate large batches without checking balance first
- Hardcode private keys
- Use ethers v5 syntax
## Code Examples
### Basic Image Generation
```typescript
import { ethers } from 'ethers';
import { createZGComputeNetworkBroker } from '@0glabs/0g-serving-broker';
import * as fs from 'fs';
import 'dotenv/config';
async function generateImage(prompt: string, size = '1024x1024'): Promise<string> {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const broker = await createZGComputeNetworkBroker(wallet);
const providerAddress = process.env.PROVIDER_ADDRESS!;
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);
const requestBody = { model, prompt, n: 1, size };
// IMPORTANT: Include body for request signing
const headers = await broker.inference.getRequestHeaders(
providerAddress,
JSON.stringify(requestBody),
);
const response = await fetch(`${endpoint}/images/generations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(requestBody),
});
const data = await response.json();
const imageUrl = data.data[0].url;
// ChatID from header ONLY for images
const chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
if (chatID) {
await broker.inference.processResponse(providerAddress, chatID);
}
return imageUrl;
}
// Usage
const imageUrl = await generateImage('A futuristic city skyline at sunset');
console.log('Image URL:', imageUrl);
```
### Generate and Save Locally
```typescript
async function generateAndSave(
prompt: string,
outputPath: string,
size = '512x512',
): Promise<void> {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const broker = await createZGComputeNetworkBroker(wallet);
const providerAddress = process.env.PROVIDER_ADDRESS!;
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);
const requestBody = { model, prompt, n: 1, size };
const headers = await broker.inference.getRequestHeaders(
providerAddress,
JSON.stringify(requestBody),
);
const response = await fetch(`${endpoint}/images/generations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(requestBody),
});
const data = await response.json();
// Process response for fee settlement
const chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
if (chatID) {
await broker.inference.processResponse(providerAddress, chatID);
}
// Download and save image
const imageData = data.data[0];
if (imageData.b64_json) {
fs.writeFileSync(outputPath, Buffer.from(imageData.b64_json, 'base64'));
} else if (imageData.url) {
const imgResponse = await fetch(imageData.url);
const buffer = Buffer.from(await imgResponse.arrayBuffer());
fs.writeFileSync(outputPath, buffer);
}
console.log(`Image saved to ${outputPath}`);
}
```
### Batch Generation
```typescript
async function batchGenerate(
prompts: string[],
outputDir: string,
size = '512x512',
): Promise<string[]> {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const broker = await createZGComputeNetworkBroker(wallet);
const providerAddress = process.env.PROVIDER_ADDRESS!;
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);
if (!fs.existsSync(outputDir)) fs.mkdirSync(outputDir, { recursive: true });
const results: string[] = [];
for (let i = 0; i < prompts.length; i++) {
console.log(`Generating ${i + 1}/${prompts.length}: "${prompts[i]}"`);
const requestBody = { model, prompt: prompts[i], n: 1, size };
const headers = await broker.inference.getRequestHeaders(
providerAddress,
JSON.stringify(requestBody),
);
const response = await fetch(`${endpoint}/images/generations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(requestBody),
});
const data = await response.json();
const chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
if (chatID) {
await broker.inference.processResponse(providerAddress, chatID);
}
const outputPath = `${outputDir}/image-${i + 1}.png`;
if (data.data[0].url) {
const imgResponse = await fetch(data.data[0].url);
fs.writeFileSync(outputPath, Buffer.from(await imgResponse.arrayBuffer()));
}
results.push(outputPath);
}
return results;
}
```
### Error Handling
```typescript
async function safeGenerateImage(prompt: string, size = '512x512'): Promise<string | null> {
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const wallet = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const broker = await createZGComputeNetworkBroker(wallet);
const providerAddress = process.env.PROVIDER_ADDRESS!;
try {
const { endpoint, model } = await broker.inference.getServiceMetadata(providerAddress);
const requestBody = { model, prompt, n: 1, size };
const headers = await broker.inference.getRequestHeaders(
providerAddress,
JSON.stringify(requestBody),
);
const response = await fetch(`${endpoint}/images/generations`, {
method: 'POST',
headers: { 'Content-Type': 'application/json', ...headers },
body: JSON.stringify(requestBody),
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${await response.text()}`);
}
const data = await response.json();
const chatID = response.headers.get('ZG-Res-Key') || response.headers.get('zg-res-key');
if (chatID) {
await broker.inference.processResponse(providerAddress, chatID);
}
return data.data[0].url || null;
} catch (error) {
console.error('Image generation failed:', error);
return null;
}
}
```
## Supported Sizes
| Size | Cost (approx.) | Best For |
| ----------- | -------------- | ------------------- |
| `256x256` | ~0.001 0G | Thumbnails, testing |
| `512x512` | ~0.002 0G | Standard images |
| `1024x1024` | ~0.003 0G | High quality |
## Anti-Patterns
```typescript
// BAD: Missing body in getRequestHeaders for images
const headers = await broker.inference.getRequestHeaders(providerAddress);
// Must include: getRequestHeaders(providerAddress, JSON.stringify(requestBody))
// BAD: Trying to get chatID from response body
const chatID = data.id; // WRONG for images — use header only
// BAD: Large batch without balance check
await batchGenerate(hundredPrompts, './out'); // May run out of funds
// BAD: Hardcoding private keys
const wallet = new ethers.Wallet('0xabc123...', provider); // NEVER do this
// BAD: ethers v5 syntax
const provider = new ethers.providers.JsonRpcProvider(url); // v5!
```
## Common Errors & Fixes
| Error | Cause | Fix |
| ------------------------- | --------------------------------- | ------------------------------------- |
| `Insufficient balance` | Sub-account empty | Transfer more funds |
| `Invalid request headers` | Missing body in header generation | Include body in `getRequestHeaders()` |
| `Fee verification failed` | Missing chatID | Ensure `ZG-Res-Key` header exists |
| `invalid size` | Unsupported dimensions | Use 256x256, 512x512, or 1024x1024 |
## Related Skills
- [Provider Discovery](../provider-discovery/SKILL.md) — find image providers
- [Account Management](../account-management/SKILL.md) — fund accounts
- [Compute + Storage](../../cross-layer/compute-plus-storage/SKILL.md) — generate and store
## References
- [Compute Patterns](../../../patterns/COMPUTE.md)
- [Network Config](../../../patterns/NETWORK_CONFIG.md)Related Skills
We are still matching the closest adjacent skills for this page. In the meantime, continue through the full directory.