Image Generation Chat
Build an image generation interface with multi-image references for image-to-image workflows.
Basic Setup
The simplest way to add image generation — just enable attachments and let the agent handle it.
tsx
<AgentChat
agentId="image-gen-agent"
enableAttachments
showToolCalls
onImageClick={(url) => window.open(url, '_blank')}
welcomeMessage="Upload reference images and describe what you'd like to create."
/>Custom Image Chat
For more control, use the hooks directly to build a custom interface with a reference image panel.
tsx
import { useAgentChat, useFileAttachments, FileDropZone } from '@cadraos/sdk/chat';
import { useState } from 'react';
function ImageChat() {
const [referenceImages, setReferenceImages] = useState<string[]>([]);
const attachments = useFileAttachments({
onUpload: async (file, metadata) => {
const res = await fetch('/api/attachments/upload', {
method: 'POST',
body: JSON.stringify(metadata),
});
const { uuid, uploadUrl } = await res.json();
// Upload to S3
await fetch(uploadUrl, { method: 'PUT', body: file });
// Add preview
setReferenceImages(prev => [...prev, URL.createObjectURL(file)]);
return { uuid, uploadUrl };
},
onConfirmUpload: async (uuid) => {
await fetch(`/api/attachments/${uuid}/confirm`, { method: 'POST' });
},
accept: 'image/*',
maxFiles: 5,
});
const chat = useAgentChat({
agentId: 'image-gen-agent',
onSend: (message) => {
const uuids = attachments.getReadyUuids();
return { attachmentIds: uuids };
},
});
return (
<FileDropZone {...attachments.dropZoneProps}>
<div style={{ display: 'flex', height: '100vh' }}>
{/* Reference panel */}
<div style={{ width: 300, borderRight: '1px solid #333', padding: 16 }}>
<h3>Reference Images</h3>
<div style={{ display: 'grid', gap: 8 }}>
{referenceImages.map((url, i) => (
<img key={i} src={url} style={{ width: '100%', borderRadius: 8 }} />
))}
</div>
{attachments.files.length > 0 && (
<p>{attachments.files.length} file(s) ready</p>
)}
</div>
{/* Chat area */}
<div style={{ flex: 1 }}>
{/* Render messages and input using chat state */}
</div>
</div>
</FileDropZone>
);
}Server-Side Image Generation
typescript
// Upload reference images first
const uploadRes = await fetch('/api/attachments/upload', {
method: 'POST',
body: JSON.stringify({ filename: 'ref.png', mimeType: 'image/png', sizeBytes: 1024 }),
});
const { uuid, uploadUrl } = await uploadRes.json();
await fetch(uploadUrl, { method: 'PUT', body: imageBuffer });
await fetch(`/api/attachments/${uuid}/confirm`, { method: 'POST' });
// Execute with reference images
const result = await client.agents.executeSync('image-gen-agent', {
task: 'Create a variation of this image in watercolor style',
attachmentIds: [uuid],
});
// Images appear in tool results
result.toolResults?.forEach(tr => {
if (tr.images) {
tr.images.forEach(img => console.log('Generated:', img.url));
}
});