Skip to main content
Hooks live on a profile in configuration.hooks, at most 16 of them, and run in list order.

Points

match.tools is only valid on the two tool points. Patterns are exact names (payments.transfer) or one trailing wildcard (billing.*). Omit match entirely to run on every event at that point. match.where takes at most eight conditions using the same operators as permissions. After-output hooks cannot undo external effects. Once a tool has run, the hook only controls what gets persisted and returned.

Processors

asyncTimeoutMs is capped at 24 hours. A url processor must be HTTPS (except http://localhost for development), and an agent processor cannot itself trigger another agent hook. onFailure is fail_closed (the default: no answer means the work does not happen) or fail_open.

Decisions

A HookResult carries a decision, an optional reason, and an optional rewrite (updatedInput, updatedOutput, or updatedText). So hooks evaluate in profile order, and the first non-defer decision wins. A defer may carry a rewrite; rewrites compose in order, and if every matching hook defers, the turn continues with the composed value.

HookInput

Delivered to url and agent processors:

Default hooks

Create a profile without a hooks field and Matrices installs six removable client-approval hooks. All six run at before_tool_call with a client processor, wait up to 24 hours, and are fail_closed. Three rules for the default set:
  • Omitting hooks installs the defaults.
  • hooks: [] installs none. That is the explicit opt-out.
  • Any non-empty list you send is authoritative. The defaults are not merged back in.
Their IDs are reserved, which is how a newly added default reaches existing profiles without overwriting a hook you authored under the same ID.

The audit trail

Every evaluated hook writes a hook_decision event carrying hookId, index, point, processor, decision, latencyMs, and, when they apply, reason, rewrote, and deliveryId. Parked work shows up as pendingWaits on the thread, and GET /v1/threads?state=waiting lists every thread holding one. Resolve with POST /v1/threads/{threadId}/waits/{waitId}/resolve.