Agents and Tool Use · Making It Safe · lesson 6 of 7
Permissioning and sandboxing
about 20 minutes · free · runs in your browser
The model asks; your code decides
Everything an agent does, your process does. The model produces a name and some arguments; if the resulting call deletes a table, your code deleted the table. "The model decided to" is not a defence anyone has ever accepted.
So permissioning belongs at the dispatcher, not in the prompt. A system prompt saying "never delete anything" is a request. A dispatcher that has no delete tool in its registry is a boundary.
Two rules that between them prevent most of the damage:
- Allow-list, never deny-list. A deny-list has to anticipate every dangerous tool. An allow-list only has to name the safe ones, and a tool added tomorrow is denied by default rather than permitted by omission.
- Read and write are different permissions. Most agent tasks need only reads. Granting writes because one task needed one is how an agent that summarises documents ends up able to delete them.
Your turn: write permit(tool_name, args, allowed, writable) returning (ok, reason). A tool must be in allowed; a tool whose name starts with write_ or
delete_ must additionally be in writable.
You start from this, and edit it in the browser:
WRITE_PREFIXES = ("write_", "delete_")
def permit(tool_name, args, allowed, writable):
"""Return (ok, reason). reason is None when the call is permitted."""
return (True, None)