Gates
Preconditions a tool call has to satisfy before it runs.
A gate is a precondition on a tool call. Until the gate is marked, the tool returns a message instead of running.
from agentino.safety.gates import GateRule, GateManager
rules = [GateRule(
gate="invoice_listed",
tools=["set_invoice_status"],
message="Run list_invoices first so you've actually seen the IDs.",
)]
When the loop reaches set_invoice_status and invoice_listed has not been
marked, the model gets the message back as the tool result. It reads as
feedback, so the model does the prerequisite and tries again.
Why not just say so in the prompt
Because the prompt is advice and the gate is a rule. A model that has been told "list the invoices first" will usually do it, and the times it does not are exactly the times you find out by shipping a wrong status change to a customer.
Gates cost one line of config and remove the failure mode.
Every field
gate | The name that must be marked before the tools may run |
tools | Which tools this rule applies to |
message | What the model gets back when the gate is not marked. It reads as feedback, so the model does the prerequisite and retries |
condition | Another gate. The rule is only enforced once that one is marked |
condition is how a rule becomes conditional rather than absolute. A rule
that requires a security check before sending mail need not apply to internal
recipients — mark an external_recipient gate and make the rule conditional
on it, and the check is enforced exactly where it matters.
A tool marks a gate when it completes:
gm = GateManager(rules)
gm.mark("invoice_listed") # list_invoices calls this when it returns
Confirmation gates
The other common shape is a gate that requires a human:
gates:
rules:
- gate: confirm
tools: [raise_purchase_order]
message: "Raise this purchase order?"
The tool call is held, the user is asked, and the call proceeds only on a yes. Use this for anything that spends money, sends a message outside the company, or is hard to reverse.