Persoenlicher AI Agent laesst sich gratis auf Cloudflare betreiben
Ein persoenlicher AI Agent laesst sich auf Cloudflares Free Tier ohne laufende Kosten betreiben und in rund 15 Minuten deployen. Workers liefert 100.000 Anfragen pro Tag, Durable Objects bieten je Chat eigene SQLite-Speicherung, Workers AI stellt zusaetzlich 10.000 Neurons taeglich bereit.

Posted on Oct 15 • Originally published at wowhow.cloud
A personal AI agent on Cloudflare's free tier costs $0 a month for about 70 Telegram conversations a day, and it deploys in 15 minutes. The Workers free plan gives you 100,000 requests a day, Durable Objects give each chat its own SQLite memory, and Workers AI includes 10,000 free neurons daily. The first thing you run out of is neurons, not requests. Below you get the free quotas (checked against Cloudflare's docs on 15 October 2026), a Workers AI versus bring-your-own-key cost comparison in dollars, and a complete project: wrangler.jsonc, an Agents SDK class, and a Telegram webhook handler. It builds on the Cloudflare Workers guide and the Agents Week memory guide.
Free plan: 100,000 Worker requests a day, 10 ms CPU per request, 100,000 Durable Object requests a day.
Workers AI: 10,000 neurons a day free. At 30 chats a day on Llama 3.3 70B that is about 4,000 neurons, so $0.
Bring your own Claude Haiku 5.5 key: about $0.36 a month at the same usage. Sonnet 5.5: about $7.20.
Per-chat memory lives in the agent's built-in SQLite. No D1 needed to start.
Outgrow order: neurons first, then Durable Object row writes, then CPU time.
These are the numbers that matter for an agent. All daily limits reset at 00:00 UTC.
| Workers | 100,000 requests/day, 10 ms CPU per request, 50 subrequests, 5 cron triggers | Telegram webhook entry point |
| Durable Objects | 100,000 requests/day, 13,000 GB-s/day, 5M rows read/day, 100,000 rows written/day, 5 GB SQLite | One agent instance per user, with memory |
| Workers AI | 10,000 neurons/day | Model inference with no API key |
| KV | 100,000 reads/day, 1,000 writes/day, 1 GB | Config and cached lookups |
| D1 | 5M rows read/day, 100,000 rows written/day, 5 GB | Shared data across users |
| R2 | 10 GB-month, 1M Class A and 10M Class B ops/month | Files the agent saves |
| Vectorize | 5M stored and 30M queried dimensions/month | Semantic memory |
| Queues | 10,000 operations/day, 24-hour retention | Background jobs (about 3,300 messages) |
| Workflows | 10 ms CPU per step, 100 concurrent instances, 1,024 steps | Multi-step durable tasks |
Two details save you debugging time. Free accounts can only create SQLite-backed Durable Objects, which is what the Agents SDK uses anyway. And the 10 ms CPU cap counts compute only. Waiting on a model response, a KV read or a fetch does not count against it, so an agent that spends 2 seconds waiting on inference still uses a few milliseconds of CPU.
Telegram sends each message to a Worker via webhook. The Worker checks a secret header, looks up an agent instance named after your chat ID, and calls a method on it. The agent stores the message in SQLite, calls a model with the last 12 messages, stores the reply, and returns it. The Worker posts the reply back through the Telegram Bot API. A cron schedule inside the agent sends you a morning summary. One Worker file, one Durable Object class.
Workers AI needs no key and no card. Its free allocation is 10,000 neurons a day, and Llama 3.3 70B fp8-fast is priced at 26,668 neurons per million input tokens and 204,805 per million output tokens. The usage assumption below: 30 chats a day, 2,000 input tokens (system prompt plus history) and 400 output tokens per chat, over 30 days. That is 1.8M input and 0.36M output tokens a month.
| Workers AI, Llama 3.3 70B fp8-fast | 26,668 / 204,805 neurons | $0 (about 4,060 neurons a day, inside the 10,000 free) |
| Workers AI, Llama 3.1 8B | 25,608 / 75,147 neurons | $0 (about 2,440 neurons a day) |
| Claude Haiku 5.5 (own key) | $0.10 / $0.50 | $0.36 |
| Claude Sonnet 5.5 (own key) | $2 / $10 | $7.20 |
Workers AI pricing is from Cloudflare's pricing page; Claude pricing is from Anthropic's, both checked 15 October 2026. The math for Haiku: 1.8 × $0.10 plus 0.36 × $0.50 equals $0.36. For Sonnet: 1.8 × $2 plus 0.36 × $10 equals $7.20.
The practical split: start on Workers AI because it costs nothing and needs no secrets. Switch the single model call to Claude when answers need tool use or better reasoning. At $0.36 a month, Haiku 5.5 is cheaper than the time you would spend tuning a free model. To price your own workload, plug your token counts into the agent run cost simulator.
mkdir personal-agent && cd personal-agent npm init -y npm i agents npm i -D wrangler typescript @cloudflare/workers-types mkdir src Enter fullscreen mode Exit fullscreen mode Install is a single package: npm i agents. Create a Telegram bot with @botfather and keep the token. Send your new bot any message, then open https://api.telegram.org/bot<TOKEN>/getUpdates and copy message.chat.id. That is your owner ID.
{ "name": "personal-agent", "main": "src/index.ts", "compatibility_date": "2026-10-01", "compatibility_flags": ["nodejs_compat"], "ai": { "binding": "AI" }, "durable_objects": { "bindings": [{ "name": "PersonalAgent", "class_name": "PersonalAgent" }] }, "migrations": [{ "tag": "v1", "new_sqlite_classes": ["PersonalAgent"] }] } Enter fullscreen mode Exit fullscreen mode The binding name becomes the property on env, class_name must match the exported class exactly, and new_sqlite_classes is what enables SQLite storage.
import { Agent, getAgentByName } from " agents "; interface Env { AI: Ai; PersonalAgent: DurableObjectNamespace; TELEGRAM_TOKEN: string; WEBHOOK_SECRET: string; OWNER_CHAT_ID: string; } type Turn = { role: " user " | " assistant "; content: string }; const MODEL = " @cf/meta/llama-3.3-70b-instruct-fp8-fast "; const SYSTEM = " You are a terse personal assistant. Answer in under 120 words. "; async function sendTelegram ( env: Env, chatId: string, text: string ) { await fetch ( `https://api.telegram.org/bot ${ env.
TELEGRAM_TOKEN } /sendMessage`, { method: " POST ", headers: { " content-type ": " application/json " }, body: JSON. stringify ({ chat_id: chatId, text }), }); } export class PersonalAgent extends Agent { async onStart () { this. sql `CREATE TABLE IF NOT EXISTS memory ( id INTEGER PRIMARY KEY AUTOINCREMENT, role TEXT NOT NULL, content TEXT NOT NULL, ts INTEGER NOT NULL )`; } async chat ( chatId: string, text: string ): Promise { // Cron schedules are idempotent by default, so repeating this is safe. await this. schedule ( " 30 3 * * * ", " morningBrief ", { chatId }); this. sql `INSERT INTO memory (role, content, ts) VALUES ('user', ${ text }, ${ Date. now ()} )`; const history = this. sql ` SELECT role, content FROM (SELECT * FROM memory ORDER BY id DESC LIMIT 12) ORDER BY id`; const result = ( await this. env. AI. run ( MODEL, { messages: [{ role: " system ", content: SYSTEM },... history ], })) as { response?: string }; const reply = result. response?? " The model returned nothing.
"; this. sql `INSERT INTO memory (role, content, ts) VALUES ('assistant', ${ reply }, ${ Date. now ()} )`; return reply; } async morningBrief ( payload: { chatId: string }) { const notes = this. sql ` SELECT content FROM memory WHERE role = 'user' ORDER BY id DESC LIMIT 20`; const result = ( await this. env. AI. run ( MODEL, { messages: [ { role: " system ", content: " List open tasks and reminders from these notes in 5 lines max. " }, { role: " user ", content: notes. map (( n ) => n. content ). join ( " \n " ) }, ], })) as { response?: string }; await sendTelegram ( this. env, payload. chatId, result. response?? " Nothing to report.
" ); } } export default { async fetch ( request, env, ctx ): Promise { if ( request. method!== " POST " ) return new Response ( " ok " ); if ( request. headers. get ( " X-Telegram-Bot-Api-Secret-Token " )!== env. WEBHOOK_SECRET ) { return new Response ( " forbidden ", { status: 403 }); } const update = ( await request. json ()) as { message?: { chat: { id: number }; text?: string }; }; const text = update. message?. text; const chatId = String ( update. message?. chat. id?? "" ); if (! text || chatId!== env.
OWNER_CHAT_ID ) return new Response ( " ok " ); ctx. waitUntil ( ( async () => { const agent = await getAgentByName ( env. PersonalAgent, chatId ); const reply = await agent. chat ( chatId, text ); await sendTelegram ( env, chatId, reply ); })(), ); return new Response ( " ok " ); }, } satisfies ExportedHandler; Enter fullscreen mode Exit fullscreen mode Every piece here is a documented Agents SDK call. this.sql is a tagged template for the instance's embedded SQLite, getAgentByName(namespace, name) returns a typed stub you can call methods on, and this.schedule(when, callback, payload) takes a delay in seconds, a Date, or a cron string, with the callback given as a method name on the same class. A callback name that does not exist throws, so keep the string and the method in sync.
The cron string 30 3 * * * runs in UTC. That is 9:00 AM in India. Adjust it for your timezone.
npx wrangler secret put TELEGRAM_TOKEN npx wrangler secret put WEBHOOK_SECRET npx wrangler secret put OWNER_CHAT_ID npx wrangler deploy curl "https://api.telegram.org/bot/setWebhook" \ -d "url=https://personal-agent..workers.dev" \ -d "secret_token=" Enter fullscreen mode Exit fullscreen mode Telegram's secret_token accepts 1 to 256 characters from A-Z, a-z, 0-9, underscore and hyphen, and arrives in the X-Telegram-Bot-Api-Secret-Token header on every update. That header check is the only thing stopping strangers from posting to your Worker URL, so do not skip it. The owner-ID check is the second lock: it means a leaked bot username cannot burn your neuron budget.
The handler returns 200 immediately and does the work inside ctx.waitUntil. Telegram retries a webhook that is slow to answer, and a 5-second model call would otherwise produce duplicate replies.
Replace the env.AI.run call with a plain fetch to the Messages API. Store the key with npx wrangler secret put ANTHROPIC_API_KEY.
const res = await fetch ( " https://api.anthropic.com/v1/messages ", { method: " POST ", headers: { " x-api-key ": this. env. ANTHROPIC_API_KEY, " anthropic-version ": " 2023-06-01 ", " content-type ": " application/json ", }, body: JSON. stringify ({ model: " claude-haiku-5-5 ", max_tokens: 512, system: SYSTEM, messages: history, }), }); const data = ( await res. json ()) as { content: { type: string; text?: string }[] }; const reply = data. content. find (( b ) => b. type === " text " )?. text?? " No text returned.
"; Enter fullscreen mode Exit fullscreen mode The Haiku 5.5 API ID is claude-haiku-5-5 and Sonnet 5.5 is claude-sonnet-5-5. Add ANTHROPIC_API_KEY: string to the Env interface. The fetch wait does not count toward the 10 ms CPU cap, but parsing a large JSON response does, so keep max_tokens modest.
Start with the agent's own SQLite, as in the code above. It is per-user, free to query from inside the class, and allows 5 GB total. Use D1 only when you need one query across several agents, such as an admin view of every chat. Skip KV for conversation logs: 1,000 writes a day to different keys is about 500 chats if you store two entries per turn. Use KV for read-heavy config you rarely change.
For semantic recall over old notes, add Vectorize. The 5M stored-dimension allowance holds roughly 3,900 vectors at 1,280 dimensions each, and the 30M queried-dimension allowance covers about 23,000 queries a month at that size. A personal notebook will not hit either.
Ordered by how soon you hit them, on the usage assumption above:
Workers AI neurons. 10,000 a day is about 74 chats of 2,000 input and 400 output tokens on the 70B model. Long history windows eat it faster. Fix: switch to Llama 3.1 8B (about 120 chats a day), shorten history from 12 messages to 6, or move to Haiku at a few cents a week.
Durable Object row writes. 100,000 a day. Each chat writes two memory rows plus index and schedule overhead, so you have headroom for thousands of chats. A chatty multi-user bot reaches this before requests.
CPU time. 10 ms per request. Chat logic uses a fraction of that. It breaks when you add PDF parsing, image handling or crypto inside the request path. Move that work to a Workflow step, which has the same 10 ms free limit, or upgrade.
Requests. 100,000 a day at roughly two requests per chat (Worker plus Durable Object) is about 50,000 chats. You will not get there alone.
When any limit trips, operations of that type start failing until midnight UTC. Your agent does not degrade gracefully, so wrap the model call in a try/catch and reply with a short "out of budget until 05:30 IST" message instead of silence. If your agent later needs to buy things or provision services on its own, the Cloudflare and Stripe agent provisioning guide covers that path.
The agents package is an npm library with no license fee. You pay only for the platform services it runs on, and all of those have free tiers: Workers, Durable Objects (SQLite-backed) and Workers AI.
The binding constraint is Workers AI at 10,000 neurons a day, roughly 74 chats on Llama 3.3 70B with 2,000 input and 400 output tokens each. The request caps allow far more, about 50,000 chats.
No. The 10,000 daily neurons are included on the free plan. The $0.011 per 1,000 neurons overage applies only on the paid Workers plan, so on free you hit a limit and wait for the reset.
Yes. this.schedule accepts a cron string and fires the named method on the agent without any incoming request.
It is public by necessity, since Telegram must reach it. Protect it with the webhook secret header and the owner chat ID check. Never log message text to an external service, and keep API keys in wrangler secret, never in wrangler.jsonc.
Workers AI if you want $0 and simple chat, notes and summaries. Claude Haiku 5.5 at about $0.36 a month for 30 chats a day when you need better instruction following. Sonnet 5.5 at about $7.20 a month only pays off for hard reasoning.
Cloudflare Workers limits (accessed 15 October 2026)
Cloudflare Workers AI pricing (accessed 15 October 2026)
Cloudflare Durable Objects pricing and free plan quotas (accessed 15 October 2026)
Anthropic Claude API pricing (accessed 15 October 2026)
Cloudflare Agents: add to an existing project (accessed 15 October 2026)
Cloudflare Agents: schedule tasks (accessed 15 October 2026)
Telegram Bot API: setWebhook (accessed 15 October 2026)
Anthropic models overview (accessed 15 October 2026)