In 2026, edge AI is no longer a novelty—it's a competitive requirement. Cloudflare Workers AI runs inference at over 300 points of presence worldwide, delivering sub-50ms responses for users regardless of geography. Paired with Antigravity IDE's AI agent capabilities, you can go from blank project to deployed, production-ready API in a single afternoon.
Understanding Cloudflare Workers AI
Workers AI executes AI model inference directly on Cloudflare's edge network. The key advantages:
- Near-zero latency: Models run at the closest PoP to each user, eliminating round-trips to centralized GPU clusters.
- No cold starts: Unlike traditional serverless GPU functions, Workers AI allocates resources instantly.
- Consumption-based pricing: Billed in Inference Units (IUs). Free tier includes 10,000 IUs per day.
- Wide model selection: LLaMA 3.3, Mistral, Whisper, BAAI/bge embeddings, and more.
Project Structure
my-edge-ai/
├── src/
│ ├── index.ts ← Main Worker entry point
│ ├── rag.ts ← RAG pipeline
│ └── types.ts ← Type definitions
├── wrangler.toml ← Cloudflare configuration
└── package.json
Rapid Setup with Antigravity
Antigravity's Agent mode (Cmd+I) accelerates the setup phase significantly. Ask it to scaffold the project structure, generate the wrangler config, or explain bindings—and it responds with context-aware code tailored to Workers AI.
wrangler.toml Configuration
name = "edge-ai-api"
main = "src/index.ts"
compatibility_date = "2026-01-01"
compatibility_flags = ["nodejs_compat"]
[ai]
binding = "AI" # Access via env.AI in TypeScript
[[vectorize]]
binding = "VECTORIZE"
index_name = "knowledge-base" # Vector DB for RAG
[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-namespace-id" # Response cache
[vars]
ENVIRONMENT = "production"
MAX_TOKENS = "1024"Tip: In Antigravity, open agent mode and type "add Workers AI and Vectorize bindings to wrangler.toml" — it will generate the exact configuration with inline comments.
Streaming AI Inference Endpoint
// src/index.ts
import { Hono } from "hono";
import { cors } from "hono/cors";
import { stream } from "hono/streaming";
import { RagPipeline } from "./rag";
interface Env {
AI: Ai;
VECTORIZE: VectorizeIndex;
CACHE: KVNamespace;
}
const app = new Hono<{ Bindings: Env }>();
// In production, restrict origin to your actual domains
app.use("*", cors({ origin: ["https://your-domain.com"] }));
// ─── Text generation endpoint with optional streaming ───
app.post("/api/generate", async (c) => {
const { prompt, stream: useStream = false } = await c.req.json();
if (!prompt || prompt.length > 2000) {
return c.json({ error: "prompt must be between 1 and 2000 characters" }, 400);
}
// Cache check for non-streaming requests
if (!useStream) {
const cached = await c.env.CACHE.get(`gen:${btoa(prompt)}`);
if (cached) return c.json({ result: cached, cached: true });
}
if (useStream) {
return stream(c, async (s) => {
const response = await c.env.AI.run(
"@cf/meta/llama-3.3-8b-instruct",
{ prompt, stream: true, max_tokens: 1024 }
) as ReadableStream;
const reader = response.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
await s.write(decoder.decode(value));
}
});
}
// Standard non-streaming response
const result = await c.env.AI.run(
"@cf/meta/llama-3.3-8b-instruct",
{ prompt, max_tokens: 1024 }
) as { response: string };
// Cache for 5 minutes
await c.env.CACHE.put(`gen:${btoa(prompt)}`, result.response, { expirationTtl: 300 });
return c.json({ result: result.response, cached: false });
});
export default app;
// Expected response:
// POST /api/generate
// Body: {"prompt": "What are the benefits of edge computing?"}
// → {"result": "Edge computing brings several key advantages...", "cached": false}Building a RAG Pipeline with Vectorize
RAG (Retrieval-Augmented Generation) lets your API answer questions using your own knowledge base rather than the model's training data alone.
// src/rag.ts
interface QueryResult {
answer: string;
sources: string[];
confidence: number;
}
export class RagPipeline {
constructor(
private ai: Ai,
private vectorize: VectorizeIndex,
) {}
async embed(text: string): Promise<number[]> {
const result = await this.ai.run(
"@cf/baai/bge-large-en-v1.5",
{ text: [text] }
) as { data: number[][] };
return result.data[0];
}
async query(userQuery: string): Promise<QueryResult> {
// Step 1: Embed the query
const queryVector = await this.embed(userQuery);
// Step 2: Retrieve top 5 semantically similar documents
const matches = await this.vectorize.query(queryVector, {
topK: 5,
returnMetadata: "all",
});
if (matches.matches.length === 0) {
return { answer: "No relevant information found.", sources: [], confidence: 0 };
}
// Step 3: Build context from retrieved docs
const context = matches.matches
.map((m) => m.metadata?.text ?? "")
.join("\n\n---\n\n");
const sources = matches.matches
.map((m) => m.metadata?.source as string)
.filter(Boolean);
const avgConfidence =
matches.matches.reduce((sum, m) => sum + m.score, 0) / matches.matches.length;
// Step 4: Generate grounded answer
const prompt = `Answer the question based ONLY on the context provided below.
Do not use information outside the context.
Context:
${context}
Question: ${userQuery}
Answer:`;
const result = await this.ai.run(
"@cf/meta/llama-3.3-8b-instruct",
{ prompt, max_tokens: 512 }
) as { response: string };
return {
answer: result.response.trim(),
sources: [...new Set(sources)],
confidence: avgConfidence,
};
}
async ingest(docs: { id: string; text: string; source: string }[]): Promise<number> {
const vectors = await Promise.all(
docs.map(async (doc) => ({
id: doc.id,
values: await this.embed(doc.text),
metadata: { text: doc.text, source: doc.source },
}))
);
await this.vectorize.upsert(vectors);
return vectors.length;
}
}
// Example response from the RAG endpoint:
// {
// "answer": "Cloudflare Workers AI runs inference at the edge...",
// "sources": ["cloudflare-docs.pdf", "blog-post.html"],
// "confidence": 0.87
// }Cost Optimization Strategies
| Strategy | IU Savings | Implementation Effort |
|---|---|---|
| KV caching identical queries | Up to 80% | Low |
| Prompt compression | 20–40% | Medium |
| Dynamic model routing by query length | 30–50% | Medium |
| RAG (reduce token context) | Variable | High |
// Auto-select model based on query complexity
function selectModel(prompt: string): string {
const wordCount = prompt.split(/\s+/).length;
if (wordCount < 50) return "@cf/meta/llama-3.3-8b-instruct";
if (wordCount < 200) return "@cf/mistral/mistral-7b-instruct-v0.2";
return "@cf/meta/llama-3.3-70b-instruct-fp8-fast";
}Deploying to Production
# Local development with hot reload
npx wrangler dev --local
# Deploy to staging
npx wrangler deploy --env staging
# Deploy to production
npx wrangler deploy --env production
# Test the deployed endpoint
curl -X POST https://edge-ai-api.your-subdomain.workers.dev/api/generate \
-H "Content-Type: application/json" \
-d '{"prompt": "Summarize the benefits of edge AI in 3 points"}'Wrapping Up
Antigravity IDE and Cloudflare Workers AI form a powerful combination for building edge-first AI applications:
- Use Antigravity's agent mode to accelerate scaffolding, configuration, and refactoring.
- Deploy streaming inference with Hono for responsive user experiences.
- Add Vectorize-backed RAG to ground responses in your own knowledge base.
- Apply model routing and KV caching to keep IU costs in check.
For Cloudflare deployment fundamentals, see the Cloudflare Workers Deploy Guide. To explore Antigravity's multi-agent capabilities, visit the Agent Manager Framework guide and the Cloudflare MCP Server guide.