Functions
An LLM on its own can only produce text, it can't read a file, run code, or change anything. To build an actual agent (something that takes action, not just talks), you first need real Python functions it can eventually be given access to. This lesson writes three: reading a file, writing a file, and running arbitrary Python code.
Reading and writing files
These are the two most basic actions any coding agent needs: seeing what's currently in a file, and changing it. Nothing fancy yet, just Python's built-in open().
Running arbitrary Python code
An agent that can fix bugs needs to actually execute code to test whether a fix works, not just read and write text:
exec(code, {})runs a string of Python code as if it were a script. Passing{}as its globals dict gives it a fresh, empty namespace each call, so onerun_pythoncall can't accidentally see variables left over from a previous one.contextlib.redirect_stdout(output)temporarily redirects anything the codeprint()s into an in-memory buffer (io.StringIO()) instead of your real terminal, sorun_pythoncan capture and return it as a string, exactly what's needed to hand the result back to an LLM as text.- The
try/exceptis deliberate: if the executed code raises an error (like the division by zero above),run_pythonreturns a description of the error as its result, instead of crashing your whole program. An agent needs to see its mistakes as feedback ("that failed because...") to correct course, not have the entire session die.
WARNING
exec runs code with the same permissions as your own program, there's no sandboxing here. This is fine for a personal learning project you control, but a production agent that executes model-generated code needs much stronger isolation (a container, a subprocess with a timeout, a restricted execution environment), never run untrusted, model-generated code with a bare exec in anything real.