agents
Version:
A home for your AI agents
88 lines (87 loc) • 3.4 kB
JavaScript
import { channel, subscribe as subscribe$1, unsubscribe } from "node:diagnostics_channel";
//#region src/observability/index.ts
/**
* Diagnostics channels for agent observability.
*
* Events are published to named channels using the Node.js diagnostics_channel API.
* By default, publishing to a channel with no subscribers is a no-op (zero overhead).
*
* To observe events, subscribe to the channels you care about:
* ```ts
* import { subscribe } from "node:diagnostics_channel";
* subscribe("agents:rpc", (event) => console.log(event));
* ```
*
* In production, all published messages are automatically forwarded to
* Tail Workers via `event.diagnosticsChannelEvents` — no subscription needed.
*/
const channels = {
state: channel("agents:state"),
rpc: channel("agents:rpc"),
message: channel("agents:message"),
chat: channel("agents:chat"),
transcript: channel("agents:transcript"),
fiber: channel("agents:fiber"),
agentTool: channel("agents:agent_tool"),
schedule: channel("agents:schedule"),
lifecycle: channel("agents:lifecycle"),
workflow: channel("agents:workflow"),
mcp: channel("agents:mcp"),
email: channel("agents:email"),
channel: channel("agents:channel")
};
/**
* Channel keys whose diagnostics channel name differs from `agents:${key}`.
* Keep this in sync with {@link channels} for any camelCase key that maps to a
* snake_case diagnostics channel.
*/
const CHANNEL_DIAGNOSTIC_NAME_OVERRIDES = { agentTool: "agents:agent_tool" };
/**
* Map event type prefixes to their diagnostics channel.
*/
function getChannel(type) {
if (type.startsWith("mcp:")) return channels.mcp;
if (type.startsWith("workflow:")) return channels.workflow;
if (type.startsWith("fiber:")) return channels.fiber;
if (type.startsWith("transcript:") || type.startsWith("chat:transcript:")) return channels.transcript;
if (type.startsWith("chat:")) return channels.chat;
if (type.startsWith("agent_tool:")) return channels.agentTool;
if (type.startsWith("schedule:") || type.startsWith("queue:")) return channels.schedule;
if (type.startsWith("message:") || type.startsWith("tool:") || type.startsWith("submission:") || type.startsWith("action:")) return channels.message;
if (type === "rpc" || type.startsWith("rpc:")) return channels.rpc;
if (type.startsWith("state:")) return channels.state;
if (type.startsWith("email:")) return channels.email;
if (type.startsWith("channel:") || type.startsWith("notice:")) return channels.channel;
return channels.lifecycle;
}
/**
* The default observability implementation.
*
* Publishes events to diagnostics_channel. Events are silent unless
* a subscriber is registered or a Tail Worker is attached.
*/
const genericObservability = { emit(event) {
getChannel(event.type).publish(event);
} };
/**
* Subscribe to a typed observability channel.
*
* ```ts
* import { subscribe } from "agents/observability";
*
* const unsub = subscribe("rpc", (event) => {
* console.log(event.payload.method); // fully typed
* });
* ```
*
* @returns A function that unsubscribes the callback.
*/
function subscribe(channelKey, callback) {
const name = CHANNEL_DIAGNOSTIC_NAME_OVERRIDES[channelKey] ?? `agents:${channelKey}`;
const handler = (message, _name) => callback(message);
subscribe$1(name, handler);
return () => unsubscribe(name, handler);
}
//#endregion
export { channels, genericObservability, subscribe };
//# sourceMappingURL=index.js.map