Allow-list and path boundary
The registry is the allow-list. safe_path refuses anything that would leave the base folder.
Tool arguments come from a model that users and documents can steer, so they are untrusted input. Parse them in a try block, check them against the schema, allow-list tool names and paths, and never pass them to eval, a shell or a string-built query.
Change the code and press Run (Ctrl+Enter). Predict what will happen first, then break it on purpose and read what changes. Your edits are saved and match the lesson page.
Ready for more? This phase has 6 hands-on exercises with automatic checks.
Practice questions
Write the code in the editor, run it, then open the model answer to compare.
Write parse_args(text) that returns (args, error): args is the dict and error is None on success; otherwise args is None and error is "not valid JSON" or "not an object".
Write reject_unknown(args, allowed) that returns a list of messages "unknown argument: <key>" for each key not in allowed, in the order they appear in args.
Explain it without notes
Why must tool arguments be treated as untrusted input even though your own model produced them?
List the checks a tool runner should make between receiving a tool call and running the function.
Why is eval on tool arguments dangerous and what do you do instead for a calculator tool?
Expected output
read_file q1.txt: ok: contents of /data/reports/q1.txt
read_file 2026/../q2.txt: ok: contents of /data/reports/q2.txt
read_file ../secrets/keys.txt: refused: path leaves /data/reports
read_file a/../../x: refused: path leaves /data/reports
read_file /etc/passwd: refused: absolute paths are not allowed
read_file 42: refused: path must be a string
delete_all -: refused: unknown tool delete_all