The checks
Every check the guardrail runs, in the order a call meets them; the first that stops a call decides. They run in four stages:
- Tool kinds: each tool is known to read, write or send something out;
- the admission chain: checks that may refuse a call before anything else is asked;
- the tool check: the ten rules of the licensed tool check, the first that applies deciding;
- the checks of what was said: grounding, the S1 and S2 vetoes and the confirm read. These only ever make an answer stricter: a refusal stands, and a confirmation is never turned into an allow.
Pass checks=[...] to turn on only the checks listed; a check that cannot be switched off runs whether listed or not.
Switching a check off withholds the input that check reads, so the tool check itself still decides every call.
S1, S2 and the confirm read read only the person's latest turn, and only when turns are given. Each has three
modes: off; refuse, a strict block; and confirm, ask the person, which is the default. The confirm read never
changes a call: a value it reads as missing or different makes the call wait for the person, and its reading is
shown to them.
This page is made from the guardrail's own list of checks, so it says nothing of a check that the guardrail does not.
| Check | What it does, simply | When it stops a call | Can be switched off |
|---|---|---|---|
| Tool kinds | Each tool is known to read, change something or send something out: from your file, the tool's own marks, or its name, description and arguments. A tool nobody marked counts as one that changes something. | asked (a tool not known to read is a write) | yes |
| Tool withdrawn | A tool its owner withdrew from the registry cannot be used. | refused | no |
| Address not allowed | A call cannot reach an address you do not allow, such as the cloud's metadata service or the company's own network. | refused | yes |
| Not the approved plan | Where a person approved a plan, a call that is not its next step does not run. | refused | yes |
| Plan's tool tier | Not active yet: every call passes. | never (not active yet) | yes |
| Labels | Not active yet: every call passes. Outside content is stopped by the outside content check. | never (not active yet) | yes |
| Payment limit | Not active yet: every call passes. Spending limits are set in your rules. | never (not active yet) | yes |
| Allowed tools | Only tools on your list can be used, and only by a named agent where you say so. | refused | no |
| Session record | The record of the calls already made must be intact; if anyone altered it, nothing more runs. | refused | no |
| Arguments | Each call's values must fit the tool's own description (types, required fields, allowed values). | refused | yes |
| Destinations | A tool may send something to an address only if it is known to send things out. | refused | yes |
| Order | A tool runs only at an allowed point: after another, never after another, or at most N times. | refused | yes |
| Undo | An undo must match the step it reverses, and a step is undone only once. | refused | yes |
| Your rules | Your own rule sheet decides, e.g. "refunds over 100 need a manager"; limits per period and spending limits too. | refused or asked, as the rule says | yes |
| Outside content | A call proposed after reading outside content (a web page, an email) is stopped where you forbid it. | refused, or asked where your setting asks | yes |
| Confirmation | A call needing a person's yes runs only with that yes, signed; if nobody can give it, it does not run. | refused | no |
| Any other write | Anything that changes something and no rule allowed waits for a person's yes. | asked | no |
| Grounding | A value in a write that nobody said and no tool returned is asked about, never allowed and never refused. | asked | yes |
| S1: sending verb | Where the person's turn asks to send something out and no tool sends anything, the call is stopped. | asked by default; refused in strict mode | yes |
| S2: destination | Where the turn names a place to send to that no tool takes, and the call does not take it either, the call is stopped. | asked by default; refused in strict mode | yes |
| Confirm read | The call is read against the turn, its values as typed. Where the turn gives a value the call lacks, or a different one, the person is shown both and asked. The call is never changed. | asked by default; refused in strict mode | yes |
Tool kinds
Each tool is known to read, change something or send something out: from your file, the tool's own marks, or its name, description and arguments. A tool nobody marked counts as one that changes something.
- What it catches: A write or a sending tool treated as a read because nobody marked it.
- What it cannot catch: A tool whose name and description hide what it does may be classed wrongly: mark it in the tool kinds file.
- When it stops a call: asked (a tool not known to read is a write)
- What it reads:
catalogue,tool_kinds.yaml - Can be switched off: yes
- Settings:
infer: true: infer the kind of tools nobody marked; false: every unmarked tool is a write - Settings:
file: the tool kinds file, which always wins - Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "orders", "arguments": {"order_id": "A1"}}
checks.Setting("tool_kinds")
Tool withdrawn
A tool its owner withdrew from the registry cannot be used.
- What it catches: Calls to a tool the registry no longer serves to this agent.
- What it cannot catch: A tool that was never registered: the allowed tools check stops that.
- When it stops a call: refused
- What it reads:
registry - Can be switched off: no
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "old_refund", "arguments": {}}
checks.Setting("withdrawn")
Address not allowed
A call cannot reach an address you do not allow, such as the cloud's metadata service or the company's own network.
- What it catches: A URL argument pointing at a private or metadata address.
- What it cannot catch: An address the deployment allows but that is still the wrong one for this call.
- When it stops a call: refused
- What it reads:
arguments - Can be switched off: yes
- Allowed:
{"tool": "fetch_page", "arguments": {"url": "https://example.org/a"}} - Stopped:
{"tool": "fetch_page", "arguments": {"url": "http://169.254.169.254/latest"}}
checks.Setting("address")
Not the approved plan
Where a person approved a plan, a call that is not its next step does not run.
- What it catches: A step out of order, a step added, or a step with values changed after approval.
- What it cannot catch: A plan a person approved that was itself wrong.
- When it stops a call: refused
- What it reads:
plan,plan_token,plan_step - Can be switched off: yes
- Allowed:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 900}}
checks.Setting("plan_step")
Plan's tool tier
Not active yet: every call passes.
- What it catches: Nothing yet.
- What it cannot catch: Anything: it lets every call through today.
- When it stops a call: never (not active yet)
- What it reads:
tier - Can be switched off: yes
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}}
checks.Setting("tier")
Labels
Not active yet: every call passes. Outside content is stopped by the outside content check.
- What it catches: Nothing yet.
- What it cannot catch: Anything: it lets every call through today.
- When it stops a call: never (not active yet)
- What it reads:
labels - Can be switched off: yes
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}}
checks.Setting("labels")
Payment limit
Not active yet: every call passes. Spending limits are set in your rules.
- What it catches: Nothing yet.
- What it cannot catch: Anything: it lets every call through today.
- When it stops a call: never (not active yet)
- What it reads:
amount - Can be switched off: yes
- Allowed:
{"tool": "pay", "arguments": {"amount": 5}}
checks.Setting("payment_limit")
Allowed tools
Only tools on your list can be used, and only by a named agent where you say so.
- What it catches: A tool the model made up, or one this agent may not reach.
- What it cannot catch: A listed tool used for the wrong purpose.
- When it stops a call: refused
- What it reads:
catalogue,agent - Can be switched off: no
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "delete_everything", "arguments": {}}
checks.Setting("allowed_tools")
Session record
The record of the calls already made must be intact; if anyone altered it, nothing more runs.
- What it catches: A history edited, reordered or replayed from another session.
- What it cannot catch: A call that ran outside the guardrail and was never recorded.
- When it stops a call: refused
- What it reads:
session - Can be switched off: no
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "get_order", "arguments": {"order_id": "A1"}, "tampered": true}
checks.Setting("session_record")
Arguments
Each call's values must fit the tool's own description (types, required fields, allowed values).
- What it catches: A missing required value, a wrong type, a value outside the allowed list.
- What it cannot catch: A value of the right type that is still the wrong one.
- When it stops a call: refused
- What it reads:
catalogue - Can be switched off: yes
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "get_order", "arguments": {}}
checks.Setting("arguments")
Destinations
A tool may send something to an address only if it is known to send things out.
- What it catches: An email address or URL slipped into a tool that should not send anything.
- What it cannot catch: A wrong address given to a tool that does send things out.
- When it stops a call: refused
- What it reads:
catalogue,tool_kinds - Can be switched off: yes
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "get_order", "arguments": {"order_id": "https://attacker.example/x"}}
checks.Setting("destinations")
Order
A tool runs only at an allowed point: after another, never after another, or at most N times.
- What it catches: A refund before the order was looked up; a third refund where two are allowed.
- What it cannot catch: A sequence your order rules do not describe.
- When it stops a call: refused
- What it reads:
catalogue,session - Can be switched off: yes
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}}
checks.Setting("order")
Undo
An undo must match the step it reverses, and a step is undone only once.
- What it catches: An undo with other values than the step it claims to reverse, or a second undo of one step.
- What it cannot catch: A tool's undo that does not really reverse it.
- When it stops a call: refused
- What it reads:
catalogue,session - Can be switched off: yes
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "cancel_refund", "arguments": {"refund_id": "R9"}, "compensation_of": 0}
checks.Setting("undo")
Your rules
Your own rule sheet decides, e.g. "refunds over 100 need a manager"; limits per period and spending limits too.
- What it catches: A call your rules forbid, or one over a limit.
- What it cannot catch: A case your rules do not cover: the bug hunter finds those.
- When it stops a call: refused or asked, as the rule says
- What it reads:
rules,arguments,results,usage - Can be switched off: yes
- Allowed:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 500}}
checks.Setting("your_rules")
Outside content
A call proposed after reading outside content (a web page, an email) is stopped where you forbid it.
- What it catches: A write a web page or an email talked the model into.
- What it cannot catch: Outside content that reached the model without a label.
- When it stops a call: refused, or asked where your setting asks
- What it reads:
labels - Can be switched off: yes
- Settings:
taint_policy: refuse or confirm (the default) - Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}, "labels": ["web"]}
checks.Setting("outside_content")
Confirmation
A call needing a person's yes runs only with that yes, signed; if nobody can give it, it does not run.
- What it catches: A yes reused for a different call, an altered call, or an expired yes.
- What it cannot catch: A person who says yes without reading.
- When it stops a call: refused
- What it reads:
confirmation - Can be switched off: no
- Allowed:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}, "approved": true} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 30}, "approved_for_other": true}
checks.Setting("confirmation")
Any other write
Anything that changes something and no rule allowed waits for a person's yes.
- What it catches: A write no rule speaks about.
- What it cannot catch: A read that leaks what it reads: the guardrail judges calls, not what a reply says.
- When it stops a call: asked
- What it reads:
catalogue - Can be switched off: no
- Allowed:
{"tool": "get_order", "arguments": {"order_id": "A1"}} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}}
checks.Setting("any_other_write")
Grounding
A value in a write that nobody said and no tool returned is asked about, never allowed and never refused.
- What it catches: An amount, id or date the model made up.
- What it cannot catch: A value someone did say that is still the wrong one.
- When it stops a call: asked
- What it reads:
turns,results - Can be switched off: yes
- Allowed:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}, "turns": ["refund 20 on order A1"]} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 80}, "turns": ["refund 20 on order A1"]}
checks.Setting("grounded")
S1: sending verb
Where the person's turn asks to send something out and no tool sends anything, the call is stopped.
- What it catches: "post it to the channel" answered by a call to a tool that only saves.
- What it cannot catch: A turn that sends something out in words the reader does not know.
- When it stops a call: asked by default; refused in strict mode
- What it reads:
turns - Can be switched off: yes
- Modes:
off,refuse,confirm(confirm) - Allowed:
{"tool": "save_note", "arguments": {"text": "hi"}, "turns": ["save a note saying hi"]} - Stopped:
{"tool": "save_note", "arguments": {"text": "hi"}, "turns": ["post hi to the team channel"]}
checks.Setting("s1_veto")
S2: destination
Where the turn names a place to send to that no tool takes, and the call does not take it either, the call is stopped.
- What it catches: "save the note for ana@x.com" answered by a tool that cannot send it there.
- What it cannot catch: A destination written in a way the reader does not recognise.
- When it stops a call: asked by default; refused in strict mode
- What it reads:
turns - Can be switched off: yes
- Modes:
off,refuse,confirm(confirm) - Allowed:
{"tool": "save_note", "arguments": {"order_id": "A1", "text": "x"}, "turns": ["save a note on A1 saying x"]} - Stopped:
{"tool": "save_note", "arguments": {"order_id": "A1", "text": "x"}, "turns": ["save a note on A1 for ana@x.com"]}
checks.Setting("s2_veto")
Confirm read
The call is read against the turn, its values as typed. Where the turn gives a value the call lacks, or a different one, the person is shown both and asked. The call is never changed.
- What it catches: A call whose values differ from what the person said.
- What it cannot catch: A value the person never said: grounding asks about that.
- When it stops a call: asked by default; refused in strict mode
- What it reads:
turns - Can be switched off: yes
- Modes:
off,refuse,confirm(confirm) - Allowed:
{"tool": "refund_card", "arguments": {"order_id": "A1", "amount": 20}, "turns": ["refund 20 on order A1"]} - Stopped:
{"tool": "refund_card", "arguments": {"order_id": "A2", "amount": 20}, "turns": ["refund 20 on order A1"]}
checks.Setting("confirm_read")