Recipes← all recipesView on GitHub

Require verification before unlocking AI agent tools

AI Agentsverification-gated AI agent tools

The account tools do not exist in the model's world until a handler says the caller passed.

governancetool-calling

The claim

The model cannot call a tool that is not active. get_balance and list_recent_transactions are declared with active: false, so at the start of the call they are not in the model’s world: not discouraged, absent. The only thing that turns them on is a toggle_functions action emitted by the verify_pin handler. The handler emits it only when the PIN matches the caller’s record. A prompt that says “verify before discussing the account” is a request; this is a constraint.

How it works

@AgentBase.tool(name="get_balance", description="...", parameters={}, active=False)
def get_balance(self, args, raw_data): ...

@AgentBase.tool(name="verify_pin", ...)
def verify_pin(self, args, raw_data):
    if pin_matches(raw_data["caller_id_num"], args["pin"]):
        return (FunctionResult("You are verified.")
                .toggle_functions([{"function": "get_balance", "active": True},
                                   {"function": "list_recent_transactions", "active": True}])
                .toggle_functions([{"function": "verify_pin", "active": False}])
                .update_global_data({"verified": True}))
    return FunctionResult("That PIN does not match.")   # no action: nothing unlocks

In the rendered SWML the account functions carry "active": false. The successful handler’s reply carries the platform action the model never composes:

{"toggle_functions": [{"function": "get_balance", "active": true}, {"function": "list_recent_transactions", "active": true}]}

The check is code, so a caller from an unknown number with the right digits still fails, and verify_pin retires itself once it has done its job. Retiring is optional; re-verification mid-call is the same toggle in reverse.

What to change first

Swap the PIN for an OTP: send a code with send-an-otp-by-sms-with-voice-fallback and verify it in the same handler before toggling the tools on.