Skip to content
Cloudflare Docs
非官方翻译 - 此文档为非官方中文翻译版本,仅供参考。如有疑问请以 英文官方文档 为准。

调用 Agents

了解如何从 Workers 调用您的 Agents,包括如何即时创建 Agents、寻址它们以及将请求路由到 Agent 的特定实例。

调用您的 Agent

Agents 是即时创建的,可以并发处理多个请求。每个 Agent 实例与其他实例隔离,可以维护自己的状态,并有唯一的地址。

您可以使用以下方式之一直接从 Worker 创建和运行 Agent 实例:

  • routeAgentRequest 助手:这将基于 /agents/:agent/:name URL 模式自动将请求映射到单个 Agent。:agent 的值将是您的 Agent 类名转换为 kebab-case:name 的值将是您想要创建或检索的 Agent 实例的名称。
  • getAgentByName,如果该名称不存在 Agent 实例,它将创建一个新的 Agent 实例,或检索现有实例的句柄。

查看以下示例中的使用模式:

import {
Agent,
AgentNamespace,
getAgentByName,
routeAgentRequest,
} from "agents";
export default {
async fetch(request, env, ctx) {
// 路由寻址
// 自动将 HTTP 请求和/或 WebSocket 连接路由到 /agents/:agent/:name
// 最适合:使用 agents/react 的 useAgent 将 React 应用直接连接到 Agents
return (
(await routeAgentRequest(request, env)) ||
Response.json({ msg: "no agent here" }, { status: 404 })
);
// 命名寻址
// 最适合:通过名称/ID 创建或检索 Agent 的便利方法。
// 带上您自己的路由、中间件和/或插入现有的
// 应用程序或框架。
let namedAgent = getAgentByName(env.MyAgent, "my-unique-agent-id");
// 将传入请求直接传递给您的 Agent
let namedResp = (await namedAgent).fetch(request);
return namedResp;
},
};
export class MyAgent extends Agent {
// 您的 Agent 实现在这里
}

在 Agents 上调用方法

使用 getAgentByName 时,您可以传递请求(包括 WebSocket)连接,并使用原生 JavaScript RPC(JSRPC)API 调用直接在 Agent 本身上定义的方法。

例如,一旦您有了 Agent 唯一实例的句柄(或"存根"),您可以在其上调用方法:

import { Agent, AgentNamespace, getAgentByName } from "agents";
export default {
async fetch(request, env, ctx) {
let namedAgent = getAgentByName(env.MyAgent, "my-unique-agent-id");
// 直接在 Agent 上调用方法,并传递原生 JavaScript 对象
let chatResponse = namedAgent.chat("你好!");
// 无需从 HTTP 请求或 WebSocket 序列化/反序列化
// 消息然后再返回
let agentState = getState(); // agentState 的类型是 UserHistory
return namedResp;
},
};
export class MyAgent extends Agent {
// 您的 Agent 实现在这里
async chat(prompt) {
// 调用您喜欢的 LLM
return "result";
}
async getState() {
// 直接返回 Agent 的状态
return this.state;
}
// 根据需要的其他方法!
}

使用 TypeScript 时,确保将您的 Agent 类作为 TypeScript 类型参数传递给 AgentNamespace 类型,以便正确推断类型:

interface Env {
// 将您的 Agent 类作为 TypeScript 类型参数传递,允许您调用
// 在您的 Agent 上定义的方法。
MyAgent: AgentNamespace<CodeReviewAgent>;
}
export class CodeReviewAgent extends Agent<Env, AgentState> {
// Agent 方法在这里
}

为您的 Agents 命名

为您的 Agents 创建名称时,考虑 Agent 代表什么。一个唯一的用户?一个团队或公司?用于协作的房间或频道?

一致的命名方法允许您:

  • 将传入请求直接定向到正确的 Agent
  • 确定性地将新请求路由回该 Agent,无论客户端在世界的哪个地方。
  • 避免依赖集中式会话存储或外部服务进行状态管理,因为每个 Agent 实例可以维护自己的状态。

对于给定的 Agent 定义(或下面代码中的"命名空间"),可以有数百万(或数千万)个该 Agent 的实例,每个都处理自己的请求、调用 LLM 并维护自己的状态。

例如,您可能为每个使用新的基于 AI 的代码编辑器的用户拥有一个 Agent。在这种情况下,您希望基于系统中的用户 ID 创建 Agents,这将允许该 Agent 处理该用户的所有请求。

它还确保 Agent 内的状态,包括聊天历史、语言偏好、模型配置和其他上下文可以与该用户特别关联,使状态管理变得更容易。

以下示例显示如何为请求中的每个 userId 创建唯一的 Agent:

import {
Agent,
AgentNamespace,
getAgentByName,
routeAgentRequest,
} from "agents";
export default {
async fetch(request, env, ctx) {
let userId = new URL(request.url).searchParams.get("userId") || "anonymous";
// 使用允许您路由到请求、WebSockets 或在 Agent 上调用方法的标识符
// 您也可以在这里放置身份验证逻辑 - 例如,仅为已知用户创建或检索 Agents。
let namedAgent = getAgentByName(env.MyAgent, "my-unique-agent-id");
return (await namedAgent).fetch(request);
},
};
export class MyAgent extends Agent {
// 您可以在 Agent 内的任何方法中通过 this.name 访问 Agent 的名称
async onStartup() {
console.log(`agent ${this.name} ready!`);
}
}

根据您的 Agents 目标,将 userId 替换为 teamNamechannelcompanyName - 和/或配置身份验证以确保仅为已知的、经过身份验证的用户创建 Agents。

验证 Agents

使用 Agents SDK 构建和部署 Agents 时,您通常希望在将请求传递给 Agent 之前验证客户端,以便限制 Agent 将调用谁、为特定 Agents 授权特定用户,和/或限制谁可以访问 Agent 公开的管理或调试 API。

作为最佳实践:

  • 在调用 Agent 之前,在您的 Workers 代码中处理身份验证。
  • 使用 routeAgentRequest 助手时使用内置钩子 - onBeforeConnectonBeforeRequest
  • 在使用其他方法调用 Agent 之前,使用您首选的路由器(如 Hono)和身份验证中间件或提供商来应用自定义身份验证方案。

本指南前面记录的 routeAgentRequest 助手公开了两个有用的钩子(onBeforeConnectonBeforeRequest),允许您在创建或检索 Agent 之前应用自定义逻辑:

import { Agent, AgentNamespace, routeAgentRequest } from "agents";
export default {
async fetch(request, env, ctx) {
// Use the onBeforeConnect and onBeforeRequest hooks to authenticate clients
// or run logic before handling a HTTP request or WebSocket.
return (
(await routeAgentRequest(request, env, {
// Run logic before a WebSocket client connects
onBeforeConnect: (request) => {
// Your code/auth code here
// You can return a Response here - e.g. a HTTP 403 Not Authorized -
// which will stop further request processing and will NOT invoke the
// Agent.
// return Response.json({"error": "not authorized"}, { status: 403 })
},
// Run logic before a HTTP client clients
onBeforeRequest: (request) => {
// Your code/auth code here
// Returning nothing will result in the call to the Agent continuing
},
// Prepend a prefix for how your Agents are named here
prefix: "name-prefix-here",
})) || Response.json({ msg: "no agent here" }, { status: 404 })
);
},
};

如果使用 getAgentByName 或底层 Durable Objects 路由 API,则应在调用 getAgentByName 之前验证传入请求或 WebSocket 连接。

例如,如果您使用 Hono,您可以在调用 Agent 之前在中间件中进行身份验证:

import { Agent, AgentNamespace, getAgentByName } from "agents";
import { Hono } from "hono";
const app = new Hono();
app.use("/code-review/*", async (c, next) => {
// Perform auth here
// e.g. validate a Bearer token, a JWT, use your preferred auth library
// return Response.json({ msg: 'unauthorized' }, { status: 401 });
await next(); // continue on if valid
});
app.get("/code-review/:id", async (c) => {
const id = c.req.param("teamId");
if (!id) return Response.json({ msg: "missing id" }, { status: 400 });
// Call the Agent, creating it with the name/identifier from the ":id" segment
// of our URL
const agent = await getAgentByName(c.env.MyAgent, id);
// Pass the request to our Agent instance
return await agent.fetch(c.req.raw);
});

这确保我们仅创建已验证用户的 Agents,并允许您验证 Agent 名称是否符合您首选的命名方案,然后再创建实例。

下一步