Anvia
Agents

Hooks

Observe and customize agent runtime behavior with hooks.

Hooks run inside a prompt request and can inspect or alter runtime behavior. Use observers for telemetry. Use hooks for guardrails, approvals, skips, and cancellation.

Create a Hook

import { cancelPrompt, createHook, requireApproval, skipTool } from "@anvia/core";

const hook = createHook({
  onCompletionCall({ prompt, history }) {
    console.log("model_call", { role: prompt.role, history: history.length });
  },
  onCompletionResponse({ response }) {
    console.log("model_response", response.usage.totalTokens);
  },
  onToolCall({ toolName, args }) {
    console.log("tool_call", { toolName, args });
  },
  onToolResult({ toolName, result }) {
    console.log("tool_result", { toolName, result });
  },
});

const agent = new AgentBuilder("support", model).hook(hook).build();

Register a default hook on the agent with .hook(...), or attach one to a single request with .withHook(...).

Skip a Tool

const hook = createHook({
  onToolCall({ toolName }) {
    if (toolName === "lookup_order" && maintenanceMode) {
      return skipTool("Order lookup is temporarily unavailable.");
    }
  },
});

Skipping a tool returns the reason as the tool result, then the model continues the run.

Require Approval

const hook = createHook({
  onToolCall({ toolName }) {
    if (toolName === "refund_order") {
      return requireApproval({
        reason: "Refunds require staff approval.",
        rejectMessage: "Refund was not approved.",
      });
    }
  },
});

const response = await agent
  .prompt("Refund order A-100.")
  .withHook(hook)
  .withToolApprovalHandler(async (approval) => {
    const approved = await approvals.waitForDecision(approval);

    return {
      ...approval,
      status: approved ? "approved" : "rejected",
      resolvedAt: new Date().toISOString(),
    };
  })
  .send();

If approval is rejected or times out, Anvia skips the tool and sends the rejection or timeout message back to the model. For the full approval workflow, read Human in the Loop.

Cancel a Prompt

const hook = createHook({
  onCompletionCall({ prompt }) {
    if (containsBlockedContent(prompt)) {
      return cancelPrompt("Prompt blocked by policy.");
    }
  },
});

Cancellation throws PromptCancelledError. Catch it at the application boundary when you want to return a user-facing message.