Aevum Cadence AI

Hooks

A hook is a function the assistant calls at a known boundary. The harness owns the loop. Your code runs at named points. Each hook lives in hooks/<name>.ts. The filename is the hook name.

The agent loop

NodeWhat it means
User promptuser-prompt-submit as the message enters the loop
Context checkFits the model window, or compact first
Model callpre-model-call immediately before the request
Model responsepost-model-call; then tool, continue, or stop
Assistant replystop at the terminal end of the turn
Compactionpost-compact after history is reduced
Tool resultpost-tool-use before the result rejoins history

pre-model-call, post-model-call, and post-tool-use can fire more than once per turn.

Outside the loop

Anatomy

type HookFunction<TCtx> = (ctx: TCtx) => Promise<Partial<TCtx> | void>;

Mutate the context in place, or return a partial. Omitted keys keep their existing values. One hook per file, default-exported. Types come from @aevumcadence/plugin-api.

// hooks/pre-model-call.ts
import type { PreModelCallContext } from "@aevumcadence/plugin-api";

export default async function preModelCall(ctx: PreModelCallContext) {
  if (ctx.callSite !== "mainAgent") {
    return;
  }
  ctx.systemPrompt = (ctx.systemPrompt ?? "") + "\nBe concise.";
}

Resolution order

  1. Built-in default plugins, always first.
  2. User plugins, by original install date (install-meta.json).

Each plugin contributes at most one hook per boundary. The chain is linear.

When to write a hook

When the behavior must happen every time the loop reaches that boundary: rewrite a prompt, route a call, truncate a tool result, re-inject context after compaction. If the model should choose the action by name, write a tool instead.