Activation required. AI access management must be enabled for your tenant before you can use it. To get started, contact the C1 support team for a walkthrough.
How hooks work
Each hook fires on one of three events:
Hooks run in priority order (lower priority numbers run first). Each hook is independently enabled or disabled and can be scoped to specific tools with a CEL filter expression. Multiple hooks can stack on the same call — input or output modifications from earlier hooks are passed to later ones, and any hook can short-circuit the chain by denying.
Hooks are fail-closed. If a hook errors, times out, or its filter expression fails to evaluate, the call is denied. Custom function hooks have a 60-second invocation timeout.
Every hook execution is recorded in the audit log with one of these statuses:
ALLOWED, MUTATED, DENIED, ERROR, TIMEOUT, or FILTER_ERROR.
Configure a hook
Create hooks from the Hooks section under AI > Classifiers.1
Go to AI > Classifiers, open the General tab, and find the Hooks section.
2
Click New hook.
3
Fill out the form:
4
If you selected Built-in pattern, choose the pattern and configure its options. If you selected Custom function, pick the function from the dropdown.
5
Click Save.
Filter variables by event
A filter expression only sees the variables available for its event. Referencing one that isn’t set for that event makes the expression fail to evaluate, which denies the call — see the fail-closed note above. Pre-tool use, Post-tool use
Pre-output
ctx.tool_name is unset on Pre-output — no tool call is involved.
Event and pattern must be compatible
What events you can pick between depends on the hook type:
C1 rejects a mismatch between the selected event and pattern when you save the hook.
Custom function hooks cannot use the Pre-output event. Saving one is rejected. Pre-output is reachable only through a built-in pattern: Block output (locked to it) or Link filter (selectable).
Managed by classifiers
Each hook has a Managed by classifiers toggle:- Off (default) — the hook always evaluates on every matching call.
- On — the hook only evaluates when a classifier rule explicitly selects it.
Built-in patterns
Each built-in pattern is a self-contained handler with its own configuration; no function code is required.* Secrets masking, Encoded content guard, and Prompt injection scan are defined in the API but aren’t currently offered in the admin UI’s pattern picker when creating a hook — the other ten are.
Pattern configuration and defaults
Custom function hooks
When the built-in patterns don’t fit, write a function and attach it to a hook. C1 invokes the function with a JSON payload describing the call and uses the return value to decide whether to allow, modify, or deny. See the Functions overview and Create a function for how to author and deploy a function.Pre-tool-use payload
The function receives:tool_source is builtin, connector, or claw. classification is the tool’s configured action class (READ, WRITE, DESTRUCTIVE, SENSITIVE, or DANGEROUS). caller identifies who made the call; token_id, mcp_client_id, and mcp_client_type are omitted when empty.
Post-tool-use payload
The function receives the same fields plus the call result:Return value
In both events the function returns an object with any subset of these fields:- Set
deny: trueto block the call. Thereasonis recorded in the audit log and surfaced to the AI client as a denial. - Omit
input(pre) oroutput(post) when you don’t need to modify the payload. - Returning an empty object
{}is equivalent to allowing the call unchanged.
ERROR or TIMEOUT in the audit log.
Patch tool input hooks
A patch hook merges fields onto a tool’s input before it runs, with no function call — use it for a small, static or CEL-computed change that doesn’t need custom logic. It’s always on the Pre-tool use event. Like any hook, its Filter (CEL expression) field decides whether it fires on a given call — empty matches every Pre-tool-use call. Below that, a separate Patch source decides what gets merged in when it does fire: The merge follows RFC 7396 JSON merge-patch semantics: a key in the patch overwrites or adds that key on the input, anull value removes it, and a nested object replaces the existing one rather than merging into it.
Choose a Patch source:
- CEL expression — must evaluate to a map of the fields to merge. Available variables:
ctx,input, andcaller. - Static fields — a fixed JSON object, entered directly, merged the same way.
A patch hook only rewrites the input — it can’t deny a call or inspect the output. To deny or inspect, use a built-in pattern or a custom function instead.