← Vytvářejte agenty na Cloudflare / agents / runtime / communication
HTTP a Server-Sent Events
Agents umí zpracovávat HTTP požadavky a streamovat odpovědi pomocí Server-Sent Events (SSE). Tato stránka se věnuje onRequest metodu a vzory SSE.
Zpracování HTTP požadavků
Definujte onRequest metodu pro zpracování HTTP požadavků na vašeho agenta:
import { Agent } from "agents";
export class APIAgent extends Agent {
async onRequest(request) {
const url = new URL(request.url);
// Route based on path
if (url.pathname.endsWith("/status")) {
return Response.json({ status: "ok", state: this.state });
}
if (url.pathname.endsWith("/action")) {
if (request.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
const data = await request.json();
await this.processAction(data.action);
return Response.json({ success: true });
}
return new Response("Not found", { status: 404 });
}
async processAction(action) {
// Handle the action
}
}import { Agent } from "agents";
export class APIAgent extends Agent {
async onRequest(request: Request): Promise<Response> {
const url = new URL(request.url);
// Route based on path
if (url.pathname.endsWith("/status")) {
return Response.json({ status: "ok", state: this.state });
}
if (url.pathname.endsWith("/action")) {
if (request.method !== "POST") {
return new Response("Method not allowed", { status: 405 });
}
const data = await request.json<{ action: string }>();
await this.processAction(data.action);
return Response.json({ success: true });
}
return new Response("Not found", { status: 404 });
}
async processAction(action: string) {
// Handle the action
}
}Server-Sent Events (SSE)
SSE umožňuje streamovat data klientům přes dlouhotrvající HTTP připojení. To je ideální pro odpovědi AI modelů, které generují tokeny postupně.
Ruční SSE
Vytvořte stream SSE ručně pomocí ReadableStream:
export class StreamAgent extends Agent {
async onRequest(request) {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
// Send events
controller.enqueue(encoder.encode("data: Starting...\n\n"));
for (let i = 1; i <= 5; i++) {
await new Promise((r) => setTimeout(r, 500));
controller.enqueue(encoder.encode(`data: Step ${i} complete\n\n`));
}
controller.enqueue(encoder.encode("data: Done!\n\n"));
controller.close();
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}
}export class StreamAgent extends Agent {
async onRequest(request: Request): Promise<Response> {
const encoder = new TextEncoder();
const stream = new ReadableStream({
async start(controller) {
// Send events
controller.enqueue(encoder.encode("data: Starting...\n\n"));
for (let i = 1; i <= 5; i++) {
await new Promise((r) => setTimeout(r, 500));
controller.enqueue(encoder.encode(`data: Step ${i} complete\n\n`));
}
controller.enqueue(encoder.encode("data: Done!\n\n"));
controller.close();
},
});
return new Response(stream, {
headers: {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive",
},
});
}
}Formát zpráv SSE
Zprávy SSE mají specifický formát:
data: your message here\n\nMůžete také zahrnout typy událostí a ID:
event: update\n
id: 123\n
data: {"count": 42}\n\nS AI SDK
AI SDK ↗ poskytuje vestavěné streamování SSE:
import { Agent } from "agents";
import { streamText } from "ai";
import { createWorkersAI } from "workers-ai-provider";
export class ChatAgent extends Agent {
async onRequest(request) {
const { prompt } = await request.json();
const workersai = createWorkersAI({ binding: this.env.AI });
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
prompt: prompt,
});
return result.toTextStreamResponse();
}
}import { Agent } from "agents";
import { streamText } from "ai";
import { createWorkersAI } from "workers-ai-provider";
interface Env {
AI: Ai;
}
export class ChatAgent extends Agent<Env> {
async onRequest(request: Request): Promise<Response> {
const { prompt } = await request.json<{ prompt: string }>();
const workersai = createWorkersAI({ binding: this.env.AI });
const result = streamText({
model: workersai("@cf/zai-org/glm-4.7-flash"),
prompt: prompt,
});
return result.toTextStreamResponse();
}
}Zpracování připojení
Připojení SSE mohou být dlouhotrvající. Odpojení klientů řešte elegantně:
- Uložit průběh : Zápis do stav agenta aby klienti mohli obnovit
- Použití směrování agenta : Klienti mohou znovu se připojit ke stejné instanci agenta bez úložišť relací
- Žádné časové limity : Cloudflare Workers nemají žádný efektivní limit na délku odpovědi SSE
export class ResumeAgent extends Agent {
async onRequest(request) {
const url = new URL(request.url);
const lastEventId = request.headers.get("Last-Event-ID");
if (lastEventId) {
// Client is resuming - send events after lastEventId
return this.resumeStream(lastEventId);
}
return this.startStream();
}
async startStream() {
// Start new stream, saving progress to this.state
}
async resumeStream(fromId) {
// Resume from saved state
}
}export class ResumeAgent extends Agent {
async onRequest(request: Request): Promise<Response> {
const url = new URL(request.url);
const lastEventId = request.headers.get("Last-Event-ID");
if (lastEventId) {
// Client is resuming - send events after lastEventId
return this.resumeStream(lastEventId);
}
return this.startStream();
}
async startStream(): Promise<Response> {
// Start new stream, saving progress to this.state
}
async resumeStream(fromId: string): Promise<Response> {
// Resume from saved state
}
}WebSockets vs. SSE
| Funkce | WebSockets | SSE |
|---|---|---|
| Směr | Obousměrný | Pouze Server → Klient |
| Protokol | ws:// / wss:// |
HTTP |
| Binární data | Ano | Ne (pouze text) |
| Opětovné připojení | Ruční | Automaticky (prohlížeč) |
| Vhodné pro | Interaktivní aplikace, chat | Streamované odpovědi, oznámení |
Doporučení: Pro interaktivní aplikace použijte WebSockets. Pro streamování odpovědí AI nebo notifikace odesílané serverem použijte SSE.
Viz WebSockets pro dokumentaci k WebSocket.