Plugins
A Plugin wires up the agent in one shot — hooks, scopes, or any custom logic you want to attach.
Usage
import type { Ag2bPlugin } from '@ag2b/core';
const logger: Ag2bPlugin = (agent) => {
const offStart = agent.addHook('onChatStart', (ctx) => console.log('→', ctx.message));
const offDone = agent.addHook('onChatDone', (ctx) => console.log('←', ctx.response.content));
return () => {
offStart();
offDone();
};
};Install with agent.use(plugin):
use(plugin: Ag2bPlugin): Promise<Ag2bPluginCleanup | undefined>The returned cleanup tears the plugin down:
const cleanup = await agent.use(logger);
// later
cleanup?.();Async Setup
agent.use() awaits the plugin, so async plugins work the same way. Use this when setup needs IO before registering hooks — fetching config, opening a connection, etc.
const remoteFlags: Ag2bPlugin = async (agent) => {
const flags = await fetch('/api/flags').then((r) => r.json());
return agent.addHook('preRequest', (ctx) => {
if (flags.cacheEnabled) {
const cached = cache.get(hash(ctx.request));
if (cached) return { response: cached };
}
});
};
await agent.use(remoteFlags);Awaiting use() ensures setup errors surface to the caller before any chat starts.
Registering Scopes
A plugin can register scopes too — useful when a feature's tools, context, and lifecycle ship together. The register() disposer doubles as the plugin's cleanup:
import { Scope, Tool } from '@ag2b/core';
import { z } from 'zod/v4';
export const appearance: Ag2bPlugin = (agent) => {
const setBackground = new Tool({
name: 'setBackground',
description: 'Change the page background color.',
parameters: z.object({
color: z.string().describe('Any valid CSS color (name, hex, rgb, etc.)'),
}),
handler: ({ color }) => {
document.body.style.backgroundColor = color;
},
});
const scope = new Scope({
name: 'appearance',
tools: [setBackground],
});
return agent.scopes.register(scope);
};Plugin Contract
Ag2bPlugin
type Ag2bPlugin = (agent: Agent) => Awaitable<void | Ag2bPluginCleanup>;A plugin receives the agent and wires it up. Return:
void— plugin is fire-and-forget; nothing to tear down.Ag2bPluginCleanup— a function the caller invokes to undo the plugin's setup.
May be sync or async — agent.use() awaits either.
Ag2bPluginCleanup
type Ag2bPluginCleanup = () => void;Returned by a plugin to expose teardown.
Clean up every disposer the plugin created
addHookdisposersscopes.registerdisposers- plus any external resources (intervals, listeners, connections) the plugin owns
const telemetry: Ag2bPlugin = (agent) => {
const off1 = agent.addHook('onChatDone', (ctx) => report.done(ctx));
const off2 = agent.addHook('onChatError', (ctx) => report.error(ctx));
const interval = setInterval(flush, 5_000);
return () => {
off1();
off2();
clearInterval(interval);
};
};