跳转到主要内容

Runtime

import { TypeScriptExample } from "~/components";

Every agent built with the Agents SDK runs on a Durable Object. The runtime coordinates its startup, incoming events, and scheduled work. Your capabilities or harness use stored state to recover after interruptions:

  • Lifecycle (agents/lifecycle) runs startup, dispatches each request and WebSocket event, and owns a durable job queue and the object's single alarm.
  • Routing (agents/routing) sends requests from your Worker to the right named object.
  • Capabilities are features you attach with lifecycle.use(), such as WebSocket clients, shared state, a scheduler, and MCP connections.
  • Observability traces model calls and publishes events from the Lifecycle and its capabilities.
flowchart LR
    Client["Client<br/>useAgent, AgentClient, HTTP"] -->|"HTTP or WebSocket"| Worker["Worker<br/>routeAgentRequest()"]
    Worker --> L
    subgraph DO["Durable Object, one per name"]
        L["Lifecycle<br/>startup, dispatch, jobs, the one alarm"]
        L --> WS["WebSockets"]
        L --> SC["Scheduler"]
        L --> H["Harness, such as PiHarness"]
        L --> More["Other capabilities"]
        WS --- DB[("SQLite storage")]
        SC --- DB
        H --- DB
        More --- DB
    end
    DO -.->|"traces and events"| Obs["Observability"]

If you use a harness

You do not have to assemble all of this yourself. A harness sets up what it needs:

  • Think extends the Agent class, which installs the Lifecycle and its capabilities for you.
  • Pi is one capability. You install the Lifecycle and add the harness with .use(), and Pi handles its own storage and recovery.

With either harness, the parts of the runtime you work with directly are usually:

  • Routing, to send requests to the right agent and check who is calling.
  • WebSockets, to connect your frontend to the agent.
  • Observability, to trace model calls and debug what the agent did.

The rest of this section matters when you build your own agent loop, or add a capability of your own.

Compose the runtime yourself

You compose these parts on a plain DurableObject:

import { DurableObject } from "cloudflare:workers";
import { Lifecycle } from "agents/lifecycle";
import { routeAgentRequest } from "agents/routing";
import { Scheduler } from "agents/schedules";
import { WebSockets } from "agents/websockets";

export class MyAgent extends DurableObject<Env> {
	readonly scheduler = new Scheduler({ callbacks: {} });
	readonly webSockets = new WebSockets();
	readonly lifecycle = Lifecycle.install(this)
		.use(this.scheduler)
		.use(this.webSockets);

	onRequest(request: Request): Response {
		return new Response(`Hello from ${this.lifecycle.name}`);
	}
}

export default {
	async fetch(request: Request, env: Env): Promise<Response> {
		return (
			(await routeAgentRequest(request, env)) ??
			new Response("Not found", { status: 404 })
		);
	},
} satisfies ExportedHandler<Env>;

The Agent class is a preset of the same runtime: a Durable Object with the Lifecycle and several capabilities already installed.

Lifecycle

Routing

Capabilities

Capabilities are optional features. Start with Choose capabilities to check what your harness already provides and what to add yourself.

Capability Import What it adds Status
WebSockets agents/websockets Real-time client connections Stable
State agents/state Shared state that syncs to clients Stable
Scheduler agents/schedules Delayed, dated, cron, and interval callbacks Stable
MCPClientManager agents/mcp/client Connections to MCP servers Stable
Streams agents/streams Durable incremental output Experimental
Sessions agents/sessions Durable conversation history Experimental

To write your own capability, refer to Build a capability.

Observability

  • Tracing records model calls, tool runs, and approvals as Workers traces.
  • Diagnostics channels publish structured events from the Lifecycle, its capabilities, and the Agent class.