Agents use the same routing as any Durable Object with the Lifecycle. routeAgentRequest() sends /agents/:binding/:name to the Agent named :name. For the URL shape, routing options, authentication, and custom routes, refer to Routing. This page covers what the Agent class adds.
import { Agent, getAgentByName, routeAgentRequest } from "agents";
export class Counter extends Agent {
initialState = { count: 0 };
async increment() {
this.setState({ count: this.state.count + 1 });
return this.state.count;
}
}
export default {
async fetch(request, env) {
if (new URL(request.url).pathname === "/api/increment") {
const counter = await getAgentByName(env.Counter, "global");
return Response.json({ count: await counter.increment() });
}
return (
(await routeAgentRequest(request, env)) ??
new Response("Not found", { status: 404 })
);
},
};import { Agent, getAgentByName, routeAgentRequest } from "agents";
export class Counter extends Agent<Env, { count: number }> {
initialState = { count: 0 };
async increment(): Promise<number> {
this.setState({ count: this.state.count + 1 });
return this.state.count;
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
if (new URL(request.url).pathname === "/api/increment") {
const counter = await getAgentByName(env.Counter, "global");
return Response.json({ count: await counter.increment() });
}
return (
(await routeAgentRequest(request, env)) ??
new Response("Not found", { status: 404 })
);
},
} satisfies ExportedHandler<Env>;A request to /agents/counter/global reaches the Counter Agent named global. Clients connect the same way with useAgent({ agent: "Counter", name: "global" }).
getAgentByName(namespace, name, options?) returns a stub for RPC calls. Unlike getByName(), it starts the Agent before it returns, so its capabilities and onStart() are ready. It accepts locationHint, jurisdiction, props, and routingRetry.
Props pass values to onStart(props) when a request or call starts the Agent:
import { Agent, getAgentByName } from "agents";
export class Profile extends Agent {
#userId;
onStart(props) {
this.#userId = props?.userId;
}
}
export async function openProfile(env, userId) {
return getAgentByName(env.Profile, userId, { props: { userId } });
}import { Agent, getAgentByName } from "agents";
type Props = { userId: string };
export class Profile extends Agent<Env> {
#userId: string | undefined;
onStart(props?: Props) {
this.#userId = props?.userId;
}
}
export async function openProfile(env: Env, userId: string) {
return getAgentByName(env.Profile, userId, { props: { userId } });
}Props only reach an Agent that is starting. routeAgentRequest() accepts the same props option, and passes them to whichever Agent the URL matches. For per-Agent values, use getAgentByName().
buildAgentPath() builds the path for an Agent and its sub-agents, with a /sub/ segment for each level. Inside an Agent, this.selfPath holds its own path:
import { buildAgentPath } from "agents";
const path = buildAgentPath(
[
{ className: "Inbox", name: "alice" },
{ className: "Chat", name: "chat-1" },
],
{ leafPath: "/callbacks/job" },
);
// /agents/inbox/alice/sub/chat/chat-1/callbacks/jobimport { buildAgentPath } from "agents";
const path = buildAgentPath(
[
{ className: "Inbox", name: "alice" },
{ className: "Chat", name: "chat-1" },
],
{ leafPath: "/callbacks/job" },
);
// /agents/inbox/alice/sub/chat/chat-1/callbacks/job| Static option | Default | Description |
|---|---|---|
sendIdentityOnConnect |
true |
Set to false to keep the Agent's name out of the identity frame |
hibernate |
true |
Set to false to keep the Agent in memory while clients are connected |
import { Agent } from "agents";
class SecureAgent extends Agent {
static options = { sendIdentityOnConnect: false };
}