Cloudflare Agents SDK
Instrument Cloudflare Agents SDK classes with Sentry and link chats to the Conversations view.
Available since: v10.69.0
When you build agents with the Cloudflare Agents SDK, wrap your agent classes with instrumentAgentWithSentry. Agents are Durable Objects under the hood, so the wrapper applies everything Durable Object instrumentation does (request transactions, alarms, WebSocket handlers, RPC trace propagation), plus agent-specific telemetry:
- Callable RPC spans: a span for each
@callable()method invoked over WebSocket, carrying the agent class and instance name as attributes. - Automatic conversation IDs: the SDK sets the conversation ID on every chat turn (
onChatMessage) and every callable RPC call, sogen_aispans group in Conversations without anysetConversationIdcall.
import * as Sentry from "@sentry/cloudflare";
import { Agent, callable } from "agents";
class MyAgentBase extends Agent<Env> {
@callable()
async greet(name: string): Promise<string> {
return `Hello, ${name}!`;
}
}
// Export your named class as defined in your wrangler config
export const MyAgent = Sentry.instrumentAgentWithSentry(
(env: Env) => ({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
enableRpcTracePropagation: true,
}),
MyAgentBase,
);
import * as Sentry from "@sentry/cloudflare";
import { Agent, callable } from "agents";
class MyAgentBase extends Agent<Env> {
@callable()
async greet(name: string): Promise<string> {
return `Hello, ${name}!`;
}
}
// Export your named class as defined in your wrangler config
export const MyAgent = Sentry.instrumentAgentWithSentry(
(env: Env) => ({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
enableRpcTracePropagation: true,
}),
MyAgentBase,
);
instrumentAgentWithSentry works with Agent from agents, AIChatAgent from @cloudflare/ai-chat, and McpAgent from agents/mcp. When you build with the Sentry Cloudflare Vite plugin's autoInstrumentation, the plugin detects and wraps Agent classes automatically.
The automatic conversation ID defaults to the agent instance name, which is correct when one agent instance is one chat session (for example useAgent({ name: chatSessionId })). When the chat is cleared (clearHistory() from useAgentChat, or anything that emits the message:clear observability event), the SDK rotates to a fresh conversation ID, so a reset chat groups as a new conversation.
If your instances are per-user or a shared singleton like "default", the default would group unrelated chats into one conversation. Override it with your own chat session ID at the start of onChatMessage, before any model or tool calls:
import * as Sentry from "@sentry/cloudflare";
import { AIChatAgent } from "@cloudflare/ai-chat";
class MyChatAgentBase extends AIChatAgent<Env> {
async onChatMessage() {
// Your chat session ID (not user id / "default")
Sentry.setConversationId("conv_abc123");
// … run your model and tools …
}
}
import * as Sentry from "@sentry/cloudflare";
import { AIChatAgent } from "@cloudflare/ai-chat";
class MyChatAgentBase extends AIChatAgent<Env> {
async onChatMessage() {
// Your chat session ID (not user id / "default")
Sentry.setConversationId("conv_abc123");
// … run your model and tools …
}
}
Use a real chat session ID, such as a UUID or conv_... value your app creates when the user starts a chat. Do not use a user ID or room name: those group unrelated chats into one conversation. To clear the ID, call Sentry.setConversationId(null).
On older SDK versions, wrap agent classes with instrumentDurableObjectWithSentry instead and set the conversation ID manually at the start of the handler (onRequest for Agent, onChatMessage for AIChatAgent), before any AI calls:
import * as Sentry from "@sentry/cloudflare";
import { AIChatAgent } from "@cloudflare/ai-chat";
class MyChatAgentBase extends AIChatAgent<Env> {
async onChatMessage() {
Sentry.setConversationId("conv_abc123");
// … run your model and tools …
}
}
export const MyChatAgent = Sentry.instrumentDurableObjectWithSentry(
(env: Env) => ({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
}),
MyChatAgentBase,
);
import * as Sentry from "@sentry/cloudflare";
import { AIChatAgent } from "@cloudflare/ai-chat";
class MyChatAgentBase extends AIChatAgent<Env> {
async onChatMessage() {
Sentry.setConversationId("conv_abc123");
// … run your model and tools …
}
}
export const MyChatAgent = Sentry.instrumentDurableObjectWithSentry(
(env: Env) => ({
dsn: "___PUBLIC_DSN___",
tracesSampleRate: 1.0,
}),
MyChatAgentBase,
);
Populate the Conversations User column with Sentry.setUser on every request or handler that performs AI calls, before those calls run. See Tracking Conversations.
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").