app-ai-binding
Build AI features in generated apps using the platform-provided Workers AI binding. Load this skill for chatbots, summarization, classification, embeddings, semantic search, image understanding, transcription, translation, or other model inference.
Generated apps can call Workers AI from the App Durable Object through this.env.AI. The platform provides this binding automatically in Dynamic Worker previews and native Cloudflare deployments. Do not add an ai section to the generated app's wrangler.json.
Use only AI.run(model, inputs, options?). Preview uses a restricted proxy with this method, while deployed Workers receive the native Workers AI binding. Methods such as AI.gateway(), AI.models(), AI.autorag(), and AI.toMarkdown() are not portable between preview and deployment.
Type and usage
import { DurableObject } from "cloudflare:workers";
interface Env {
AI: Ai;
}
export class App extends DurableObject<Env> {
async fetch(request: Request): Promise<Response> {
const { prompt } = await request.json<{ prompt: string }>();
const result = await this.env.AI.run("@cf/meta/llama-4-scout-17b-16e-instruct", {
messages: [
{ role: "system", content: "Answer clearly and concisely." },
{ role: "user", content: prompt },
],
});
return Response.json(result);
}
}
Keep AI calls in the server-side App class. Browser code should call an app API route; it must never receive model credentials or call the binding directly.
Common tasks
Text generation
Use @cf/meta/llama-4-scout-17b-16e-instruct with either prompt or messages:
const result = await this.env.AI.run("@cf/meta/llama-4-scout-17b-16e-instruct", {
messages: [{ role: "user", content: userPrompt }],
max_tokens: 512,
});
Embeddings
Use @cf/baai/bge-base-en-v1.5. The response contains embedding vectors in data:
const result = await this.env.AI.run("@cf/baai/bge-base-en-v1.5", {
text: ["first document", "second document"],
});
Image classification
Use @cf/microsoft/resnet-50 with image bytes converted to a number array:
const image = [...new Uint8Array(await request.arrayBuffer())];
const result = await this.env.AI.run("@cf/microsoft/resnet-50", { image });
Speech transcription
Use @cf/openai/whisper with audio bytes:
const audio = [...new Uint8Array(await request.arrayBuffer())];
const result = await this.env.AI.run("@cf/openai/whisper", { audio });
Model input and output shapes differ. Keep model-specific parsing close to the call and validate user input before inference. Use only active model IDs from the current Workers AI model catalog; never generate code with a deprecated model.
Limits and errors
Dynamic Worker previews enforce a per-app AI call limit. AI features must fail transparently when inference is unavailable.
- Never return canned, random, mock, placeholder, or hard-coded content as a fallback for an AI response.
- Never catch an
AI.run()error and continue with an apparently successful response. - Never return
200with fields such asfallbackUsedafter inference fails. - Return a non-2xx JSON response containing a safe, useful error message. The frontend must display that error to the user.
- Do not retry rate-limit failures in a loop.
try {
const result = await this.env.AI.run("@cf/meta/llama-4-scout-17b-16e-instruct", {
messages: [{ role: "user", content: userPrompt }],
});
return Response.json(result);
} catch (error) {
const message = error instanceof Error ? error.message : "AI inference failed";
return Response.json({ error: "AI inference failed", details: message }, { status: 503 });
}
Frontend callers must inspect both the HTTP status and error body:
const response = await fetch("./api/chat", requestOptions);
const body = await response.json<{ content?: string; error?: string; details?: string }>();
if (!response.ok) throw new Error(body.details || body.error || "AI request failed");
Use non-streaming calls for preview-compatible code. Native Workers AI deployments support { stream: true }, but streaming across the preview proxy is not guaranteed.
Files of this skill
This skill has no supporting files.