The cycle hasn’t changed, it’s just that there are more tools
"The loop hasn't changed at all, I just added things to the TOOLS array." - s02_tool_use.py Original words.
How many places do you need to move to add a tool?
S01’s agent only knows bash. How would you change it to make it also work read_file / write_file / edit_file?
Many people’s first reaction is: change loop. wrong. Don't touch a single line ofloop. Only three things are needed:
- Write a Python handler function (
run_read(path, limit)). - Register it to the
TOOL_HANDLERSmapping table ("read_file": lambda **kw: run_read(...)). - Add a JSON schema statement to the
TOOLSarray (tell the model what the tool is called and what parameters it accepts).
When the loop sees a tool_use block, press block.name to search the function in the dispatch map, execute it, and stuff the output back to tool_result. It follows the exact same path as bash.
# Dispatch map: name → handler lambda TOOL_HANDLERS = { "bash": lambda **kw: run_bash(kw["command"]), "read_file": lambda **kw: run_read(kw["path"], kw.get("limit")), "write_file": lambda **kw: run_write(kw["path"], kw["content"]), "edit_file": lambda **kw: run_edit(kw["path"], kw["old_text"], kw["new_text"]), }
See how dispatch is routed
The widget below allows you to click on a tool_use request that may be sent by the model to see how it is routed to a specific Python function. Note: block.name determines which line to take.
safe_path: a line of defense that cannot be omitted
Give the agent file access rights. The most likely safety issue is path escape: the model was supposed to work in /home/user/project/, but it ended up sending a read_file("../../etc/passwd").
There is a small function in s02 that deals with this:
def safe_path(p: str) -> Path: path = (WORKDIR / p).resolve() # Normalize, resolve .. and soft links if not path.is_relative_to(WORKDIR): raise ValueError(f"Path escapes workspace: {p}") return path
The key lies in the two steps .resolve() + .is_relative_to() - parse to the absolute path and then check whether it is still in the sandbox. Without the former, foo/../../etc can pass through; without the latter, no inspection is even done.
Identify path security
The following 5 paths are all read_file parameters that may be sent by the model. Which ones will be allowed by safe_path and which ones will be rejected? Assume WORKDIR = /home/user/project.
Do not add dangerous tools to the agent
It is easy to add tools, but remember: Every tool you add is a new capability boundary of the model. In s02, bash already has a blacklist (rm -rf /, sudo, shutdown), and write_file has safe_path restrictions. Ask yourself three questions before adding tools to production:
- Can this tool allow the model to do irreversible things? (rm, send email, git push)
- What can itleak? (env vars, .ssh, cookies)
- Will error output be treated as command feedback? (prompt injection via tool output)
Lecture s07 will add a "permission layer" to pull these decisions out of the code and make them declarative.