# API Reference ## Agent Classes ### AIChatAgent For AI chat with auto-streaming, message history, tools, resumable streaming. ```ts import { AIChatAgent } from "agents"; import { openai } from "@ai-sdk/openai"; export class ChatAgent extends AIChatAgent { async onChatMessage(onFinish) { return this.streamText({ model: openai("gpt-4"), messages: this.messages, // Auto-managed message history tools: { getWeather: { description: "Get weather", parameters: z.object({ city: z.string() }), execute: async ({ city }) => `Sunny, 72°F in ${city}` } }, onFinish, // Persist response to this.messages }); } } ``` ### Agent (Base Class) Full control for custom logic, WebSockets, email, and SQL. ```ts import { Agent } from "agents"; export class MyAgent extends Agent { // Lifecycle methods below } ``` **Type params:** `Agent` - Env bindings, agent state, connection state ## Lifecycle Hooks ```ts onStart() { // Init/restart this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT, name TEXT)`; } async onRequest(req: Request) { // HTTP const {pathname} = new URL(req.url); if (pathname === "/users") return Response.json(this.sql<{id,name}>`SELECT * FROM users`); return new Response("Not found", {status: 404}); } async onConnect(conn: Connection, ctx: ConnectionContext) { // WebSocket conn.accept(); conn.setState({userId: ctx.request.headers.get("X-User-ID")}); conn.send(JSON.stringify({type: "connected", state: this.state})); } async onMessage(conn: Connection, msg: WSMessage) { // WS messages const m = JSON.parse(msg as string); this.setState({messages: [...this.state.messages, m]}); this.connections.forEach(c => c.send(JSON.stringify(m))); } async onEmail(email: AgentEmail) { // Email routing this.sql`INSERT INTO emails (from_addr,subject,body) VALUES (${email.from},${email.headers.get("subject")},${await email.text()})`; } ``` ## State, SQL, Scheduling ```ts // State this.setState({count: 42}); // Auto-syncs this.setState({...this.state, count: this.state.count + 1}); // SQL (parameterized queries prevent injection) this.sql`CREATE TABLE IF NOT EXISTS users (id TEXT PRIMARY KEY, name TEXT)`; this.sql`INSERT INTO users (id,name) VALUES (${userId},${name})`; const users = this.sql<{id,name}>`SELECT * FROM users WHERE id = ${userId}`; // Scheduling await this.schedule(new Date("2026-12-25"), "sendGreeting", {msg:"Hi"}); // Date await this.schedule(60, "checkStatus", {}); // Delay (sec) await this.schedule("0 0 * * *", "dailyCleanup", {}); // Cron await this.cancelSchedule(scheduleId); ``` ## RPC Methods (@callable) ```ts import { Agent, callable } from "agents"; export class MyAgent extends Agent { @callable() async processTask(input: {text: string}): Promise<{result: string}> { return { result: await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt: input.text}) }; } } // Client: const result = await agent.processTask({ text: "Hello" }); // Must return JSON-serializable values ``` ## Connections & AI ```ts // Connections (type: Agent) this.connections.forEach(c => c.send(JSON.stringify(msg))); // Broadcast conn.setState({userId:"123"}); conn.close(1000, "Goodbye"); // Workers AI const r = await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt}); // Manual streaming (prefer AIChatAgent) const stream = await client.chat.completions.create({model: "gpt-4", messages, stream: true}); for await (const chunk of stream) conn.send(JSON.stringify({chunk: chunk.choices[0].delta.content})); ``` **Type-safe state:** `Agent` - third param types `conn.state` ## MCP Integration Model Context Protocol for exposing tools: ```ts // Register & use MCP server await this.mcp.registerServer("github", { url: env.MCP_SERVER_URL, auth: { type: "oauth", clientId: env.GITHUB_CLIENT_ID, clientSecret: env.GITHUB_CLIENT_SECRET } }); const tools = await this.mcp.getAITools(["github"]); return this.streamText({ model: openai("gpt-4"), messages: this.messages, tools, onFinish }); ``` ## Task Queue ```ts await this.queue("processVideo", { videoId: "abc123" }); // Add task const tasks = await this.dequeue(10); // Process up to 10 ``` ## Context & Cleanup ```ts const agent = getCurrentAgent(); // Get current instance async destroy() { /* cleanup before agent destroyed */ } ``` ## AI Integration ```ts // Workers AI const r = await this.env.AI.run("@cf/meta/llama-3.1-8b-instruct", {prompt}); // Manual streaming (prefer AIChatAgent for auto-streaming) const stream = await client.chat.completions.create({model: "gpt-4", messages, stream: true}); for await (const chunk of stream) { if (chunk.choices[0]?.delta?.content) conn.send(JSON.stringify({chunk: chunk.choices[0].delta.content})); } ``` ## Client Hooks (React) ```ts // useAgent() - WebSocket connection + RPC import { useAgent } from "agents/react"; const agent = useAgent({ agent: "MyAgent", name: "user-123" }); // name for idFromName const result = await agent.processTask({ text: "Hello" }); // Call @callable methods // agent.readyState: 0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED // useAgentChat() - AI chat UI import { useAgentChat } from "agents/ai-react"; const agent = useAgent({ agent: "ChatAgent" }); const { messages, input, handleInputChange, handleSubmit, isLoading, stop, clearHistory } = useAgentChat({ agent, maxSteps: 5, // Max tool iterations resume: true, // Auto-resume on disconnect onToolCall: async (toolCall) => { // Client tools (human-in-the-loop) if (toolCall.toolName === "confirm") return { ok: window.confirm("Proceed?") }; } }); // status: "ready" | "submitted" | "streaming" | "error" ```