input_guardrails= / output_guardrails= right on the tool, next to approval=.
send_email and never for any other tool.
Quick Start
1
Block a tool's arguments by rule
An input guardrail returns
(False, "reason") to block. The reason is handed back to the model as the tool result, never raised at the user.2
Rewrite the arguments before the tool runs
Return
(True, new_arguments) to rewrite. The rewritten dict is what the tool receives.3
Substitute the result
An output guardrail sees the raw result before it re-enters the LLM context. Return
(True, new_result) to substitute, or (False, "reason") to block.How per-tool guardrails run
Per-tool guardrails are the layer closest to the tool in both directions. The input guardrail runs last on the way in (immediately before dispatch); the output guardrail runs first on the way out (before any agent-wide guardrail and before the trust fence).The ordering is deliberate. Human approval stays upstream of every automated rewrite, so a reviewer audits exactly what the model proposed. The input guardrail runs immediately before dispatch, so “the tool never runs with arguments its own guardrail did not see” holds. The output guardrail sees the raw result, so it does not have to parse the external-content fence, and a substituted result is fenced exactly like an original one.
Per-tool vs agent-wide guardrails
Per-tool guardrails share the same machinery as agent-wide ones — a guardrail written for one scope drops into the other.
A guardrail entry may be a plain callable
(value) -> (ok, value), a bare True / False, a GuardrailResult, or any object exposing validate_tool_call / validate_tool_result — so an existing GuardrailChain reuses unchanged. A guardrail that raises, or returns an unreadable verdict, fails closed and blocks the call.
Best Practices
Scope the guardrail to where the rule lives
Scope the guardrail to where the rule lives
When a rule belongs to one tool — “
send_email recipients must be on-domain” — declare it on that tool, not agent-wide. An agent-wide guardrail fires for every tool and has to branch on tool_name.Prefer rewriting arguments over blocking
Prefer rewriting arguments over blocking
Returning
(True, sanitised_args) is safer than (False, reason) and hoping the model retries correctly. Fix the call rather than bouncing it back.Redact in the output guardrail rather than reject
Redact in the output guardrail rather than reject
When a result carries a secret, return
(True, redacted) so the model still gets a usable answer, instead of (False, ...) which throws the whole result away.Keep guardrail logic pure
Keep guardrail logic pure
A guardrail should inspect and transform its input with no side effects — no network calls, no writes. A guardrail that raises fails closed and blocks the tool.
Related
Guardrails
Agent-wide output and tool guardrails.
Approval
Human-in-the-loop sign-off before a tool runs.
Tool Approval
Declare a tool needs approval in one line.

