之前和群友聊天时,偶然提到cloudflare的skill非常优秀,今天我们就来看看,什么是好的skill?
skill-name/
├── SKILL.md # 必需:触发条件 + Agent 指令
├── references/ # 可选:详细知识文档
│ ├── README.md
│ ├── api.md
│ ├── patterns.md
│ └── gotchas.md
├── scripts/ # 可选:确定性执行脚本
└── assets/ # 可选:模板、schema、数据
这是所有skill文件夹的格式,很普通,我们来看看里面的skill.md
Agents SDK
name: agents-sdk
description: Build, debug, or review Cloudflare Agents SDK applications using the agents package.
Cloudflare Agents SDK
Your knowledge of the Agents SDK may be outdated. Prefer retrieval over pre-training for any Agents SDK task.
Retrieval Sources
Cloudflare docs: https://developers.cloudflare.com/agents/
| Topic | Docs URL | Use for |
|---|---|---|
| Getting started | Quick start | First agent, project setup |
| Adding to existing project | Add to existing project | Install into existing Workers app |
| Configuration | Configuration | wrangler.jsonc, bindings, assets, deployment |
| Agent class | Agents API | Agent lifecycle, patterns, pitfalls |
| State | Store and sync state | setState, validateStateChange, persistence |
| Routing | Routing | URL patterns, routeAgentRequest |
| Callable methods | Callable methods | @callable, RPC, streaming, timeouts |
| Scheduling | Schedule tasks | schedule(), scheduleEvery(), cron |
| Workflows | Run workflows | AgentWorkflow, durable multi-step tasks |
| HTTP/WebSockets | WebSockets | Lifecycle hooks, hibernation |
| Chat agents | Chat agents | AIChatAgent, streaming, tools, persistence |
| Client SDK | Client SDK | useAgent, AgentClient, state, RPC, HTTP |
| Client tools | Client tools | Client-side tools, autoContinueAfterToolResult |
| Server-driven messages | Autonomous responses | saveMessages, waitUntilStable, server-initiated turns |
| Resumable streaming | Chat agents | Stream recovery on disconnect |
| Email routing, secure reply resolver | ||
| MCP client | MCP client | Connecting to MCP servers |
| MCP server | MCP server | Building MCP servers with createMcpHandler |
| MCP transports | MCP transports | Streamable HTTP, SSE, RPC transport options |
| Securing MCP servers | Securing MCP | OAuth, proxy MCP, hardening |
| Human-in-the-loop | Human-in-the-loop | Workflow approvals, elicitation, timeout handling |
| Durable execution | Durable execution | runFiber(), stash(), surviving DO eviction |
| Queue | Queue | Built-in FIFO queue, queue() |
| Retries | Retries | this.retry(), backoff/jitter |
| Observability | Observability | Diagnostics-channel events |
| Push notifications | Push notifications | Web Push + VAPID from agents |
| Webhooks | Webhooks | Receiving external webhooks |
| Cross-domain auth | Cross-domain auth | WebSocket auth, tokens, CORS |
| Readonly connections | Readonly | shouldConnectionBeReadonly |
| Voice | Voice | Experimental STT/TTS, withVoice |
| Browse the web | Browser tools | Experimental CDP browser automation |
| Think | Think | Experimental higher-level chat agent class |
| Migrations | AI SDK v5, AI SDK v6 | Upgrading @cloudflare/ai-chat |
Capabilities
The Agents SDK provides:
- Persistent state — SQLite-backed, auto-synced to clients via setState
- Callable RPC — @callable() methods invoked over WebSocket
- Scheduling — One-time, recurring (scheduleEvery), and cron tasks
- Workflows — Durable multi-step background processing via AgentWorkflow
- Durable execution — runFiber() / stash() for work that survives DO eviction
- Queue — Built-in FIFO queue with retries via queue()
- Retries — this.retry() with exponential backoff and jitter
- MCP integration — Connect to MCP servers or build your own with createMcpHandler
- Email handling — Receive and reply to emails with secure routing
- Streaming chat — AIChatAgent with resumable streams, message persistence, tools
- Server-driven messages — saveMessages, waitUntilStable for proactive agent turns
- React hooks — useAgent, useAgentChat for client apps
- Observability — diagnostics_channel events for state, RPC, schedule, lifecycle
- Push notifications — Web Push + VAPID delivery from agents
- Webhooks — Receive and verify external webhooks
- Voice (experimental) — STT/TTS via @cloudflare/voice
- Browser tools (experimental) — CDP-powered browsing via agents/browser
- Think (experimental) — Higher-level chat agent via @cloudflare/think
FIRST: Verify Installation
npm ls agents # Should show agents package
If not installed:
npm install agents
For chat agents:
npm install agents @cloudflare/ai-chat ai @ai-sdk/react
Wrangler Configuration
{ "compatibility_flags": ["nodejs_compat"], "durable_objects": { "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }] }, "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }]}
Gotchas:
- Do NOT enable experimentalDecorators in tsconfig (breaks @callable)
- Never edit old migrations — always add new tags
- Each agent class needs its own DO binding + migration entry
- Add "ai": { "binding": "AI" } for Workers AI
Agent Class
import { Agent, routeAgentRequest, callable } from "agents";type State = { count: number };export class Counter extends Agent<Env, State> { initialState = { count: 0 }; validateStateChange(nextState: State, source: Connection | "server") { if (nextState.count < 0) throw new Error("Count cannot be negative"); } onStateUpdate(state: State, source: Connection | "server") { console.log("State updated:", state); } @callable() increment() { this.setState({ count: this.state.count + 1 }); return this.state.count; }}export default { fetch: (req, env) => routeAgentRequest(req, env) ?? new Response("Not found", { status: 404 })};
Routing
Requests route to /agents/{agent-name}/{instance-name}:
| Class | URL |
|---|---|
| Counter | /agents/counter/user-123 |
| ChatRoom | /agents/chat-room/lobby |
Client: useAgent({ agent: "Counter", name: "user-123" })
Custom routing: use getAgentByName(env.MyAgent, "instance-id") then agent.fetch(request).
Core APIs
| Task | API |
|---|---|
| Read state | this.state.count |
| Write state | this.setState({ count: 1 }) |
| SQL query | this.sqlSELECT * FROM users WHERE id = ${id} |
| Schedule (delay) | await this.schedule(60, "task", payload) |
| Schedule (cron) | await this.schedule("0 * * * *", "task", payload) |
| Schedule (interval) | await this.scheduleEvery(30, "poll") |
| RPC method | @callable() myMethod() { ... } |
| Streaming RPC | @callable({ streaming: true }) stream(res) { ... } |
| Start workflow | await this.runWorkflow("ProcessingWorkflow", params) |
| Durable fiber | await this.runFiber("name", async (ctx) => { ... }) |
| Enqueue work | this.queue("handler", payload) |
| Retry with backoff | await this.retry(fn, { maxAttempts: 5 }) |
| Broadcast to clients | this.broadcast(message) |
| Get connections | this.getConnections(tag?) |
React Client
Read client-sdk.md for client selection and current connection examples. For chat UI and tools, also read streaming-chat.md.
References
Core
- references/state-scheduling.md — State persistence, scheduling, SQL
- references/callable.md — RPC methods, streaming, timeouts
- references/routing.md — URL patterns, custom routing, getAgentByName
- references/configuration.md — Wrangler config, bindings, Vite setup
Chat & Streaming
- references/streaming-chat.md — AIChatAgent, resumable streams, tools
- references/client-sdk.md — useAgent, useAgentChat, AgentClient
- references/server-driven-messages.md — Trigger patterns, saveMessages
- references/human-in-the-loop.md — Approval flows, needsApproval
Background Processing
- references/workflows.md — Durable Workflows integration
- references/durable-execution.md — runFiber, stash, surviving eviction
- references/queue-retries.md — Built-in queue, retry with backoff
Integrations
- references/mcp.md — MCP client and server, transports, securing
- references/email.md — Email routing and handling
- references/webhooks-push.md — Webhooks, push notifications
- references/observability.md — Diagnostics-channel events
Experimental
- references/think.md — @cloudflare/think higher-level chat agent
- references/voice.md — @cloudflare/voice STT/TTS
- references/codemode.md — Code Mode for tool orchestration
- references/browse-the-web.md — CDP browser tools
Cloudflare 的 skills 仓库遵循 Agent Skills 这个开放规范Specification - Agent Skills
以agent sdk这个skill为例,它帮助了解cloudflare的agent sdk开发相关内容,学习“怎么正确开发”。
skill一开始就告诉agent,模型记忆可能过时,要优先查最新资料。随机提供了各个doc的链接。这其实很有趣,一般来说,我们会将文档的链接放到最后,而cloudflare可能更关心防止agent使用过期知识。
然后介绍agent sdk提供的能力,帮助agent快速判断agent sdk能做什么,判断用户的需求是否属于这个sdk。这里的use for使用的是关键词的组合,而不是模糊的表述。
接下来进行环境检查,基础运行条件确认,给出一个最小完整 Agent,让 Agent 知道代码主体长什么样。有了 Agent class 后,再解释请求如何路由到具体实例。理解基本代码后,再提供 state、RPC、schedule、workflow 等操作入口。然后才是客户端扩展,以及更细节的reference。整个skill形成了一个很清晰的执行漏斗:
name + description
是否触发 Skill
│
▼
Retrieval Sources
Topic + Use for 路由
│
▼
Capabilities
SDK 能不能解决需求
│
▼
Verify Installation
环境是否准备好
│
▼
Wrangler Config
基础配置正确
│
▼
Agent Class
核心代码范式
│
▼
Routing / Core APIs
实际使用能力
│
▼
React Client
客户端接入
│
▼
References
按需加载详细知识
显然,这个skill不是简单的知识分类,而更接近Agent 实际执行任务时的决策顺序。
而其他的skill并不是全部都按照执行顺序,cloudflare提供的skill可以大体分为4类:
| 类型 | 例子 | 主要排版原则 |
|---|---|---|
| Workflow | wrangler、turnstile-spin |
执行顺序 |
| Knowledge | agents-sdk、durable-objects |
从概览 → 核心知识 → 细节 |
| Policy / Review | workers-best-practices |
按规则 / 检查维度组织 |
| Router | cloudflare |
用户需求 → 能力选择 → 下一个 Skill |
knowledge部分我已经举例,接下来以turnstile-spin为例,来聊一聊workflow类的Skill.
Turnstile 是 Cloudflare 提供的人机验证 / Bot 防护服务,而turnstile-spin要实现的,就是让Coding Agent 自动把这整套 Turnstile 验证接进用户已有项目。这是一个非常常见的场景.
来看看skill的第一部分:
Skill goal
Turns the prompt "set up Turnstile" into a working end-to-end integration:
a widget,
frontend snippets at every chosen insertion point,
canonical server-side siteverify in the customer's existing backend,
and a real validation pass before reporting success.
你会发现这个Skill的目标叙述非常明确,简洁,高效。规定agent要做一个组件,并且将它插入前端用户指定的位置,在后端实现标准Siteverify的验证,最后在向用户报告之前,要执行一次真正的验证流程。
分工
You are the agent. Run the wizard below by invoking the scripts under scripts/ and branching on their JSON output.
The scripts hold the deterministic logic (API calls, retry/error handling); your job is orchestration, codebase reading, confirmation, and the frontend + backend edits.
接下来,给agent明确任务,定义哪些任务交给程序,哪些任务交给agent:流程编排,读代码库,与用户交流并确认,修改前后端代码。这是workflow skil非常核心的设计。
然后展示的是不同前端的框架对应的适配文档链接,不仅减少了无关context,也会让后续的代码修改更加准确。下一部分是什么时候调用这个skill,我认为这部分也可以放到靠前的位置,但先介绍skill的基本信息,再说什么时候使用这个skill,可能会更有助于ai理解,但这部分顺序不是非常重要。