Skip to main content

tool_guards — Tool Guards

Pre-flight validation and transformation rules that sit in front of every tool call — built-in, custom code, wrapped, MCP, Composio connector, OpenAPI, and skill tools all pass through the same guard layer before their code runs. Validation rules reject a bad call with a structured fix-it message the model can act on; transform rules silently fix the arguments and let the call proceed. Section key tool_guards · Shape object · Tier All plans
Edit in the dashboard: Tools page — the Parameter guards section of the wrap editor, or the Tool Guards dialog for any tool by its runtime name
Per-tool guards, keyed by exact tool name.
Guards are keyed by the tool’s runtime name: a built-in by its plain name (web_search), one of your custom tools as tool_<name>, and an MCP/connector tool by its namespaced name. A tool with no guard entry passes through untouched.

Fields

Per-tool guard fields

Per-parameter rule fields

Each rule combines any of three kinds of field. Validation rules reject the call when violated; transform rules never reject — they change the value and let the call continue. Validation (reject) rules: Transform (silently fix) rules: Messaging and advertising:

Evaluation order

For each guarded call:
  1. block — if set, the call is refused immediately with blockMessage; no parameter rules run.
  2. Per parameter, rules apply in a fixed order: forbiddendefault (fill if missing) → hardSet (always override) → string transforms (trim, lowercase, uppercase) → required → and then, only when a value is present: type, numeric min/max (or clamp), minLength/maxLength, pattern, enum, custom.
  3. Violations are collected across all parameters and reported together in one message, so the model can fix everything in a single retry.
  4. If nothing violated, the tool runs with the transformed arguments. The model’s original message is never mutated — transforms apply to a copy.

What the model sees on a violation

A rejected call never reaches the tool — the guard’s message is surfaced to the model as an error tool result, so it can self-correct in the next step. The message is structured plain English:
Each bullet names the parameter, previews the offending value (truncated to 60 chars), names the failed rule, and gives the reason (your message override if set). Blocked tools produce a “Tool call to … was refused before running.” message naming the tool, plus the block message. Guard refusals also fire your post_tool_call hooks with the error summary, and are recorded as refused tool calls in the conversation’s interaction trace.

Layering and precedence

Three guard layers merge per turn, weakest first: subscriber → owner → platform. A stronger layer’s field wins on the same parameter; block is OR-ed across layers, so a weaker layer can block a tool but never un-block one. Guards a subscriber adds on their own Tools page are forced reject-only — the value-mutating fields (default, hardSet, clamp, trim, lowercase, uppercase) are stripped, so a subscriber can tighten your rules but can never transform an argument past them.

Examples

Validate an email recipient — reject any send_email call without a well-formed address, and tell the model up front:
Pin and clamp a search tool — force the region, keep limit sane without ever failing the call:
Block a dangerous tool outright — with a custom refusal the model will relay: