Skip to content

Routing

Last updated View as MarkdownAgent setup

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.

Route requests

src/index.jsjs
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 })
		);
	},
};
src/index.tsts
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" }).

Call an Agent from a Worker

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

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().

Sub-agent URLs

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/job
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/job

Agent options

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 };
}

Next steps

Routing

URL shape, routing options, authentication, and custom routes.

Client SDK

Connect from browsers with useAgent and AgentClient.

Was this helpful?