Plugin hooks
React to durable runtime events without changing the run being observed.
This page documents the TypeScript extension contract. Agents activate hooks
through the owning published or local plugin. A root hooks/ folder is not an
authoring surface.
Hooks are plugin-owned reactions to durable runtime events. Use them for audit records, application metrics, notifications, analytics, and other cross-cutting side effects that should run regardless of which channel or automation started the run.
// plugins/audit/ai.assemblyline/audit.ts
import { defineHook } from "@assemblyline-agents/core";
export default defineHook({
description: "Record completed runs in the application audit log.",
events: {
async "run.completed"(event, ctx) {
await auditLog.record({
runId: ctx.runId,
agent: ctx.agent.name,
hook: ctx.hook?.name,
status: event.data.status ?? "completed"
});
}
}
});Expose the module and its static event inventory from the plugin entry:
// plugins/audit/ai.assemblyline/index.ts
import { defineAssemblyLinePlugin } from "@assemblyline-agents/core";
export default defineAssemblyLinePlugin({
hooks: {
audit: {
definition: "./ai.assemblyline/audit.ts",
eventTypes: ["run.completed"]
}
}
});The key under hooks is the contribution name; the compiled name is qualified
as <plugin>.<hook>. definition must be an existing contained ./ path, and
eventTypes must contain at least one event. Each key in the implementation's
events object is a durable run event type; "*" observes every event. Keep
the two inventories equal. Exact handlers run before wildcard handlers.
Callbacks receive the persisted event plus run, agent, and hook identity.
A published plugin whose hook construction depends on
capabilities.<plugin>.config names a factory in the descriptor:
hooks: {
audit: {
definition: "./ai.assemblyline/audit.ts",
factory: "createAuditHook",
eventTypes: ["run.completed"]
}
}createAuditHook receives the plugin's schema-validated config and returns a
HookDefinition. Lifecycle descriptors support the same factory contract.
Credential values remain environment bindings, never plugin config.
Runtime Contract
The runtime persists and publishes the event before invoking hooks. A thrown
hook records agent.event_handler_failed and is logged, but it does not change
the originating run's result. Hooks may perform real side effects, so protect
at-least-once external writes with an application idempotency key.
Hooks are reactors, not interceptors:
- They cannot replace the run message, target, model, tools, or result.
- They do not contribute model context.
- They should not own work required for a run to be considered successful.
Put required automation preparation or finalization in a named plugin lifecycle contribution referenced by the automation. Put arbitrary capability composition in a bounded plugin composition contribution, provider ingress in its explicit channel/connection implementation, and telemetry setup in an observability profile or plugin instrumentation contribution.
Review a plugin's event inventory in plugins.lock before activation.