Skip to main content

Step 1 of 7: Launch your first agent

By the end you will be able to:

  • Explain what the three building blocks do: the Agents SDK runs the agent, Workers AI supplies the model, AI Gateway watches and controls every model call
  • Describe how a Worker, a hostname and a gateway fit together in your own team account
  • Take an agent from a zip file to a live URL, and follow one request through your logs
Your team and account

Checking your assignment… If it cannot load, ask a host and continue with the guide.

The account id and hostname below are placeholders. They appear here once a host assigns you to a team.

Account
shown here once your team is assigned
Account id
TEAM_ACCOUNT_ID
Demo hostname
TEAM_HOSTNAME
Worker
agent
AI Gateway
agent-gateway

Use the Cloudflare account on your team card (also on the Workspace page). No account yet? Ask a host: you can read on, but you can't deploy until it is ready.

Why it matters​

  • A URL you can open beats a perfect agent nobody has seen.
  • Every later step changes this agent. A live, working starter first means each step is a small change to something that already runs.
  • It shows you how the pieces fit together, once. Agents SDK, Workers AI and AI Gateway are all in play before you write any code.

The concepts​

Your agent is three Cloudflare products working together. This is the path one chat message takes. Below, each product gets a short reason you need it, then you see how the starter wires them up.

  1. 1YouThe chat page in a browser, or curlPOST /api/chat
  2. 2Your WorkerAgents SDK: the agent, its tools and its memoryagent
  3. 3AI GatewayLogs and controls every model callagent-gateway
  4. 4Workers AIThe model that does the thinking@cf/google/gemma-4-26b-a4b-it
The answer travels back the same way, and the gateway writes down each call it saw.

Agents SDK: the agent itself​

The Agents SDK is Cloudflare's TypeScript library for building agents. You write a class that extends Agent (the starter's ChatAgent does), and Cloudflare runs each instance as a Durable Object: a small, named server-side object that keeps its own state.

Why you need it. A model on its own answers one message and forgets it. It has no memory, cannot wait for anything, cannot do anything in the world and cannot ask a person first. Those are exactly the things that turn a model into an agent, and without the SDK each one is yours to build and host: a server, a database, a WebSocket layer, a scheduler, an approval flow. The Agents SDK gives you all of them as one class, so your time goes into what the agent does for your users instead of the plumbing around it.

What it gives you:

  • Every agent is its own small server. One instance per name (a user, a case, a team), created on first use and found again by name, running on Cloudflare with nothing for you to provision or scale.
  • It remembers. this.state and a built-in SQLite database (this.sql) are saved on every change, so what the agent knows survives restarts, redeploys and idle time. Step 3 uses this.
  • It works when nobody is typing. this.schedule() runs code after a delay, at a date or on a cron, and an idle agent hibernates and wakes on the next request or schedule.
  • It talks to people in real time. WebSockets and streaming HTTP are built in, and state can sync straight to the browser, which is how the starter chat streams answers as they are written.
  • Tools are plain functions. The model decides when to call one, and your code runs it inside your Worker with your bindings. Step 2 adds one.
  • A person can stay in control. Human-in-the-loop is a first-class pattern: an action can wait for an Approve click before it runs. Step 5 adds one.
  • It plugs into the rest of the platform. The same class can start Workflows for long tasks, act as an MCP server, or react to email. Step 4 picks one.

Docs: Agents overview · Agent class API

Workers AI: the model​

Workers AI runs AI models on Cloudflare's GPUs and hands them to your Worker through one binding, env.AI.

Why you need it. An agent needs a model to read the request and decide what to do. Normally that means choosing a vendor, opening an account, agreeing a price and keeping an API key safe, before you have written a line of agent code. Workers AI removes all of it: the model is a binding on your Worker, in the account you already have, with no key to store or leak. That is why you can have a working agent in minutes.

Which model, and why. The starter uses @cf/google/gemma-4-26b-a4b-it, a small, fast model that can call tools and read images. It is set as MODEL in src/server.ts. We start small on purpose: the first replies come back quickly, and the tools, memory and approvals in Steps 2 to 6 do not need a large model. Larger models, such as @cf/moonshotai/kimi-k2.7-code, reason better and answer more slowly. Nothing else in the starter depends on the choice, so you can change MODEL whenever you want to try a bigger one.

What it gives you:

  • No GPUs and no API keys. env.AI.run(model, input) is the whole call. There is nothing to provision and no secret to store or leak.
  • A catalogue of open models. Text, embeddings, image and speech models, all listed in the model catalogue. Switching model is changing the one MODEL string in src/server.ts.
  • Serverless, pay per use. No GPU to rent or keep warm. Usage is metered in Neurons (a unit of GPU compute) and there is a free daily allocation.
  • Runs on the same network as your Worker. The model and your code sit on Cloudflare's network, so a request does not leave for a separate AI vendor.
  • Works with the AI SDK. The starter calls it through workers-ai-provider and the AI SDK, so tools, streaming and structured output work the same way they would with any other model.

One thing to know: Workers AI has no local simulator, so npm run dev calls the real model on Cloudflare.

Docs: Workers AI · Models

AI Gateway: the control point​

AI Gateway sits between your Worker and the model. Your code passes a gateway id with each call ({ gateway: { id } }), and every request goes through that gateway on its way to the model and back.

Why you need it. As soon as a real person talks to your agent you need answers to four questions: what was it asked, what did it say, what did that cost, and how do I stop it going wrong? Without a gateway, the record lives in your own code, which you have to write and then trust, and there are no brakes. The gateway sits outside your code, so the record and the controls stay in one place even when the agent changes. That is why Step 6 builds on it, and why every call goes through it from the start.

What it gives you:

  • One place every model call passes through. You change how calls are handled in the gateway, not in your code.
  • Logs and analytics. Each request is recorded with its status, latency, tokens and an estimate of its cost, so you can see what your agent actually sent and received.
  • Caching and rate limits. Identical requests can be answered from cache, and request rates can be capped, which keeps latency and cost down.
  • Spend limits, retries and fallbacks. Set a budget that blocks requests once it is used up, retry failed calls, or fall back to another model when one fails.
  • Guardrails and DLP. Screen prompts and answers for unsafe content or sensitive data such as card numbers. Step 6 turns these on.
  • Provider-neutral. It works with 20+ model providers, so the same gateway can front a different model later without rewriting your agent.

Your team has its own gateway, agent-gateway, so its logs show only your requests. You will see your first one at the end of this step.

Docs: AI Gateway · Guardrails · DLP

Your team account​

Your team has its own Cloudflare account, and a host only invites you to it. It starts empty: you create everything in it yourself. Your first npm run deploy creates the Worker and its hostname, and you create the AI Gateway in the dashboard (part 3). Only two values differ between teams:

WhatNameSame for every team?
Worker (name in wrangler.jsonc)agentyes
AI Gateway (AI_GATEWAY_ID)agent-gatewayyes
Account id (account_id)on your team cardno
Demo hostname (the routes entry)agent.<your zone>, on your team cardno

Build it​

Commands below can be copied and pasted as they are, once you replace anything in <...> (each one is marked where it appears). Each command shows the system you picked below (the same choice is on the Workspace page).

Your system:

This step assumes Step 0 is done: npx wrangler whoami lists your team account (the name and id are on your team card). If it does not, finish Step 0 first.

Prefer to let your coding agent do the typing? Copy this prompt into your agent, with your two team values filled in. It does everything except part 3, creating the AI Gateway, which is a dashboard click only you can do.

Prompt for your coding agent
I am doing Step 1 of Build with Cloudflare Stockholm. If you have the build-stockholm MCP server, call get_step with step 1 and follow it.
1. Unpack the starter zip I downloaded (2026.11.0.zip, probably in my Downloads folder) into a new folder called stockholm-agent, and work inside it.
2. In wrangler.jsonc change ONLY two values and keep the commas: "account_id" to <ACCOUNT ID FROM MY TEAM CARD>, and the pattern in "routes" to <DEMO HOSTNAME FROM MY TEAM CARD>.
3. Run npm install, then npm run check:team, and show me the output.
4. Stop and tell me to create the AI Gateway agent-gateway in the dashboard (AI > AI Gateway > Create custom gateway, Gateway ID agent-gateway). Wait until I say it exists. Do not try to create it yourself.
5. Then run npm run deploy, wait until my hostname answers, and send POST /api/chat with {"message":"hello"} to it. Show me the reply.
Do not change anything else in wrangler.jsonc, and do not create or delete resources I did not ask for.
When it works, give me one good prompt to try in the chat page and say what I should see.

Paste it into your coding agent: the terminal, the IDE panel or the desktop app all work.

1. Download, unpack and explore the starter​

Download the starter (2026.11.0.zip)

Starter version 2026.11.0. You are already signed in, so the download just works. Do not run npm create cloudflare: that fetches the stock starter and loses the event additions.

The starter is Cloudflare's agents-starter: a working chat agent on the Agents SDK that calls Workers AI, with no API key needed. The event adds a few things on top.

Unpack it

The zip has no top-level folder, so these commands unpack it into one called stockholm-agent and move you inside (adjust the path if your browser saved it somewhere other than Downloads):

macOS / Linux
mkdir stockholm-agent && unzip ~/Downloads/2026.11.0.zip -d stockholm-agent && cd stockholm-agent && ls

You should see: package.json, wrangler.jsonc and a src folder.

The starter at a glance

Click a box or an arrow to see what it does.

The same map comes back in later steps with the part you are changing lit up. Four things were added for the event:

  • POST /api/chat: a plain JSON endpoint that every shield in Step 6 tests your agent through. It is the same agent as the chat page (same tools, notes and schedules); each call is a one-off question with no chat history.
  • AI_GATEWAY_ID in wrangler.jsonc: model calls go through your own AI Gateway (agent-gateway), already filled in.
  • /mcp: a small MCP server with one ask_agent tool, the server that Step 6's Secure MCP shield protects. It makes its own single model call; it does not run the chat agent's tools or memory.
  • workers_dev and preview_urls are off, and your hostname is a Custom Domain on your own zone. Switching the workers.dev address off does not make the agent private: your demo hostname is public too, so use synthetic data only.

src/server.ts is the file you change in steps 2 to 5.

Take a tour with your coding agent

Open the stockholm-agent folder in your coding agent (set up in Step 0) and paste this. It only reads; it changes nothing.

Prompt for your coding agent
You are inside a Cloudflare Agents SDK starter project. Do not change any files.
Read package.json, wrangler.jsonc, src/server.ts, src/mcp.ts and src/app.tsx. If you are unsure about the Agents SDK, check the live docs at https://developers.cloudflare.com/agents/ first.
Then give me a short tour, in plain language, for a developer who has never used the Agents SDK:
1. The big picture in five lines: what ChatAgent is, how a chat message becomes a model call, and where Workers AI and AI Gateway come in (look for AI_GATEWAY_ID).
2. Where the agent keeps state and memory today, and how the Agents SDK features (setState, this.sql, this.schedule) would be used to add more.
3. How tools are defined in tools(), which ones exist, and exactly where I would add a new one.
4. What POST /api/chat does and how it differs from the chat page and from /mcp.
5. The three places I should read first, with file and line numbers, and one thing in this project that would surprise a newcomer.
Keep it under 400 words.

Paste it into your coding agent: the terminal, the IDE panel or the desktop app all work.

No coding agent? Spend five minutes in src/server.ts instead: read ChatAgent, tools() and the /api/chat route.

2. Point the starter at your team account​

Open wrangler.jsonc. Only two values are yours, and both are on your team card at the top of this page: your account id and your demo hostname. Edit these two lines in place; do not replace the whole file, or you lose the Durable Object and binding settings.

- "account_id": "TEAM_ACCOUNT_ID",
+ "account_id": "<the account id from your team card>",
...
- "routes": [{ "pattern": "TEAM_HOSTNAME", "custom_domain": true }],
+ "routes": [{ "pattern": "<the demo hostname from your team card>", "custom_domain": true }],

Do this before you run anything. The model runs on Cloudflare (Workers AI has no local simulator), so even npm run dev uses whichever account account_id names. Then check it:

npm run check:team

You should see: Team check OK: account 1a2b3c..., demo hostname ... with your own values. The check only reads your files and terminal: it does not need anything to exist in your account yet. npm run dev and npm run deploy run it first and stop if a value is still a placeholder (TEAM_ACCOUNT_ID, TEAM_HOSTNAME), if the account is the old shared event account, or if a CLOUDFLARE_ACCOUNT_ID in your terminal is a different account. It only warns about an old CLOUDFLARE_API_TOKEN; that token overrides your login, so remove it. The clear-old-settings commands are in Step 0. It is a safety net, not a lock: Cloudflare permissions decide where you can really deploy.

3. Create your AI Gateway agent-gateway​

Your account starts with no gateway, and the starter sends every model call through one named agent-gateway. If it does not exist, the chat answers with an error (code 2001, shown by curl as gateway_not_configured). Create it now, once, in the dashboard (a gateway cannot be created with wrangler: its login has no AI Gateway permission):

  1. Open the AI Gateway page and choose your team account if asked. The account name at the top left must be the one on your team card.
  2. Choose Create custom gateway. Do not use the default gateway the dashboard offers: Cloudflare names it default, and the starter looks for another name.
  3. Gateway ID: agent-gateway, exactly, lowercase. This is the id the starter sends with every call (AI_GATEWAY_ID), so do not add a suffix or change it: the starter and npm run check:team expect this one.
  4. Workers AI Billing: leave the default (Standard billing), if the dashboard asks.
  5. Select Create. Leave the other settings as they are for now; Step 6 changes some of them. Log collection is on by default, which is what Part 7 below needs.

You should see: agent-gateway in the gateway list. If Create custom gateway is missing or refused, tell a host: your invitation should give you the Administrator role in this account, and yours may be missing it.

4. Run it locally​

npm install
npx wrangler --version
npm run dev

The first line downloads the starter's packages. It should end with found 0 vulnerabilities; a line saying that some packages are looking for funding is only a notice, not a problem. The second prints the Wrangler version the starter ships with (4.146.0 in this release). npm run dev starts the starter on your laptop. Open http://localhost:5173 in a browser and say hello. It needs the wrangler login from Step 0, because the model runs on Cloudflare, and it needs the gateway from part 3. Stop it with Ctrl+C when the chat answers.

5. Deploy​

npm run deploy

What this does: it runs the team check, builds the chat page, creates the Worker agent in your team account (there is nothing to update yet) and creates the Custom Domain from routes: Cloudflare adds the DNS record and issues the certificate in your zone. You should see Uploaded agent and a Current Version ID. The first deploy in a new account can take a little longer than later ones.

There is no workers.dev link: it is off on purpose. Depending on the Wrangler version the output may say No targets deployed, or list your hostname as a custom domain; either is fine as long as your hostname answers in part 6. If Wrangler stops with a message about a DNS record that conflicts with your hostname, read the Stuck? entry below before answering it.

6. Wait for your hostname, set your demo URL and talk to it​

A brand-new hostname is not instant. Cloudflare creates the DNS record and the certificate after the deploy, so for the first minutes your laptop may say the host does not exist, or fail the secure connection. That is normal. Check it (replace the host with the one on your team card):

macOS / Linux
curl -sS -o /dev/null -w "%{http_code}\n" https://<your demo hostname>/

You should see: 200. Run it again every 30 seconds or so. Most of the time it answers within a few minutes; the Cloudflare docs give no exact time for the certificate, so if it is still failing after about ten minutes, see Stuck? below.

Then set your demo URL once per terminal, using the hostname from your team card. Every curl and PowerShell example in the later steps reuses it, so open a new terminal later and you set it again:

macOS / Linux
export DEMO_URL=https://<your demo hostname>

Open your demo URL in a browser and chat. Then call the JSON endpoint the way the shields will later:

macOS / Linux
curl -s -X POST "$DEMO_URL/api/chat" \
-H 'content-type: application/json' \
-d '{"message":"hello"}'

You should see: a reply from the agent, as {"reply":"..."} (PowerShell shows it as a reply field). If you see gateway_not_configured instead, go back to part 3.

7. Find your request in the AI Gateway log​

In your team account's Cloudflare dashboard, open AI Gateway > agent-gateway > Logs. Your messages are there, each with its model, status and token counts. That log is how you will see what your agent does for the rest of the day.

Check it worked​

  • npm run check:team prints Team check OK.
  • agent-gateway exists in your team account's AI Gateway page.
  • The chat page loads on your demo hostname and answers.
  • The curl (or Invoke-RestMethod) call returns a reply.
  • In the dashboard, AI Gateway > agent-gateway > Logs shows your request.
Stuck?
  • npm install hangs or errors. A corporate laptop may block the npm registry. Try a phone hotspot, or ask a host.
  • npm install reports vulnerabilities, or Wrangler is older than 4.146.0. You have an older copy of the starter. Download it again from part 1 (this page links version 2026.11.0) and unpack it into a fresh folder. In a pinch, npm audit fix clears the warnings in your current folder.
  • Replies are slow. The starter uses a small, fast model (@cf/google/gemma-4-26b-a4b-it), so a slow reply is usually the first call after a deploy or a busy moment. Wait a few seconds and ask again; npx wrangler tail shows what the Worker is doing. If you changed MODEL to a larger model, that is the cause: switch it back.
  • npm run dev says you must log in. Run npx wrangler login in an interactive terminal with the email your team's invitation went to.
  • npm run check:team stops with an error. Read the message: it names the value to fix. A placeholder is still in wrangler.jsonc, the account is the old shared event account, or an old CLOUDFLARE_ACCOUNT_ID or CLOUDFLARE_API_TOKEN is set in your terminal, a .env file or a .dev.vars file. Use the clear-old-settings commands in Step 0.
  • wrangler whoami does not list your team account, or a command says you cannot reach it. You have not accepted your team account invitation yet: check your inbox, or open Get ready to see where a host has got to. Then re-run npx wrangler login with the same email. Still missing? Tell a host.
  • You deployed under a different name. Set "name": "agent" and deploy again. A different name creates a second, separate Worker; delete the extra one with npx wrangler delete --name <that name>.
  • The chat is silent, or answers with a gateway error (gateway_not_configured, or agent error with an older starter and 2001: Please configure AI Gateway in npx wrangler tail). The gateway does not exist in your team account yet, or its name is not exactly agent-gateway. Create it as in part 3 (it takes a minute) and ask again; no redeploy is needed. The browser chat page does not show this error, it just stays silent: the cause is in npx wrangler tail, and the curl call in part 6 names it. To keep going without it, set AI_GATEWAY_ID to "" and redeploy: the starter then calls Workers AI directly, but Step 6 needs the gateway later.
  • npm run deploy fails with an authentication or permission error (code 10000), or says it could not find the zone. "Could not find zone for …" means the account_id and the hostname do not belong together: both must come from your team card, and npx wrangler whoami must list that account. A permission error on the hostname or the Worker means your role in this account is not Administrator, so it cannot create Workers or Custom Domains: tell a host, who checks your invitation. Do not work around it with a workers.dev link.
  • Wrangler says a DNS record for your hostname conflicts. Something already has that name in your zone (for example a record added by hand, or a half-finished earlier try). If you are sure the record is not needed, answer yes and Wrangler points the name at your Worker. A CNAME on the name cannot be replaced that way: delete it in the dashboard under your zone's DNS records, then deploy again. If you did not create it, ask a host first.
  • A deploy was interrupted, or the hostname was only half created. Run npm run deploy again. It is safe to repeat: it brings the Worker and the Custom Domain to the state in wrangler.jsonc.
  • Your demo hostname shows nothing, "could not resolve host" or a certificate error right after deploying. The DNS record and certificate are created after the deploy: wait and retry the check in part 6. Your laptop remembers a failed lookup for a while: use a phone hotspot, or curl --resolve <your demo hostname>:443:<an IP from nslookup against 1.1.1.1>, or wait about five minutes. Still failing after about ten minutes? Check that the routes pattern is exactly the hostname on your team card with nothing else around it, that the deploy printed no route error, and that the Custom Domain appears in the dashboard under Workers & Pages > agent > Settings > Domains & Routes. Then tell a host. Never use build-stockholm.events-cloudflare.com. That is the event site, not your account; npm run check:team refuses it.
  • $DEMO_URL is empty, or a URL starts with https:///. You opened a new terminal since part 6. Set it again.
  • curl fails on Windows. In PowerShell curl is not the real curl; use the Invoke-RestMethod line.
  • Windows and unzip. Use the PowerShell line in part 1, or right-click the zip and Extract All.
Go further
  • Point your coding agent at live docs so it does not write from memory: paste Fetch https://developers.cloudflare.com/agent-setup/prompt.md into Claude Code, Cursor, Copilot, OpenCode or Codex. The event's own MCP server is https://build-stockholm.events-cloudflare.com/mcp; Get set up has the details.
  • Watch your Worker live: npx wrangler tail.
  • Use synthetic data for this workshop. Your demo URL and chat may be publicly reachable; do not upload real customer, employee or proprietary data.

Finished step 1?

Checking your team…


Back: Step 0: Get set up. Next: Step 2: First tool.

Need help? Raise a hand for a host, or ask the Mentor dock (it escalates to a host when unsure). Remote: remote help channel to be confirmed by the event owner.