**STOP.** Your knowledge of the Agents SDK may be outdated. Prefer retrieval over pre-training for any Agents SDK task. Fetch current docs from `https://github.com/cloudflare/agents/tree/main/docs` before implementing. Topic
https://github.com/cloudflare/agents/tree/main/docs before implementing.docs/getting-started.mddocs/state.mdsetState, validateStateChange, persistencedocs/routing.mdrouteAgentRequest, basePathdocs/callable-methods.md@callable, RPC, streaming, timeoutsdocs/scheduling.mdschedule(), scheduleEvery(), crondocs/workflows.mdAgentWorkflow, durable multi-step tasksdocs/http-websockets.mddocs/email.mddocs/mcp-client.mddocs/mcp-servers.mdMcpAgentdocs/client-sdk.mduseAgent, useAgentChat, React hooksdocs/human-in-the-loop.mddocs/resumable-streaming.md@callable() methods invoked over WebSocketscheduleEvery), and cron tasksAgentWorkflowMcpAgentAIChatAgent with resumable streamsuseAgent, useAgentChat for client appsnpm ls agents # Should show agents packagenpm install agents{ "durable_objects": { "bindings": [{ "name": "MyAgent", "class_name": "MyAgent" }] }, "migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyAgent"] }] } `## Agent Class` import { Agent, routeAgentRequest, callable } from "agents"; type State = { count: number }; export class Counter extends Agent<Env, State> { initialState = { count: 0 }; // Validation hook - runs before state persists (sync, throwing rejects the update) validateStateChange(nextState: State, source: Connection | "server") { if (nextState.count < 0) throw new Error("Count cannot be negative"); } // Notification hook - runs after state persists (async, non-blocking) 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 }) };
/agents/{agent-name}/{instance-name}:Counter/agents/counter/user-123ChatRoom/agents/chat-room/lobbyuseAgent({ agent: "Counter", name: "user-123" })this.state.countthis.setState({ count: 1 })this.sqlSELECT * FROM users WHERE id = ${id}``await this.schedule(60, "task", payload)await this.schedule("0 * * * *", "task", payload)await this.scheduleEvery(30, "poll")@callable() myMethod() { ... }@callable({ streaming: true }) stream(res) { ... }await this.runWorkflow("ProcessingWorkflow", params)import { useAgent } from "agents/react"; function App() { const [state, setLocalState] = useState({ count: 0 }); const agent = useAgent({ agent: "Counter", name: "my-instance", onStateUpdate: (newState) => setLocalState(newState), onIdentity: (name, agentType) => console.log(`Connected to ${name}`) }); return ( <button onClick={() => agent.setState({ count: state.count + 1 })}> Count: {state.count} </button> ); }