Most LLM agents that "run code" are just generating text. Giving one an actual execution environment - where it writes, runs, and reacts to real output - is a different class of capability, and it's more approachable than it sounds.
The Idea: Execution Loop, Not Just Code Generation
The core pattern is a tool-calling loop: the agent writes code, hands it to a sandboxed executor, reads the stdout/stderr back as context, and decides what to do next - fix an error, run a follow-up script, or return a final answer. The agent isn't just producing code for a human to run; it's closing the loop itself.
Docker is the right container for this. You isolate execution in a throwaway container, cap CPU and memory, and the host filesystem stays untouched regardless of what the model generates. The OpenAI Agents SDK (or any agent framework that supports custom tool functions) lets you register a run_code tool the model can call mid-conversation.
Real Example: Wiring a Code Tool to Docker
Here's the minimal shape of a sandboxed executor you'd register as a tool:
import subprocess, textwrap
def run_python_in_docker(code: str) -> str:
safe_code = textwrap.dedent(code)
result = subprocess.run(
["docker", "run", "--rm", "--memory=256m", "--cpus=0.5",
"--network=none", "python:3.11-slim", "python", "-c", safe_code],
capture_output=True, text=True, timeout=15
)
return result.stdout or result.stderr
Register this as a tool in the OpenAI Agents SDK, and the model can call run_python_in_docker whenever it needs to verify logic, process data, or debug its own output. --network=none blocks outbound traffic; --rm deletes the container after each run. Timeout at 15 seconds prevents runaway loops.
The agent prompt matters here too. Something like: "You have access to a Python executor. Write code, run it, read the result, and iterate before responding." Without that instruction, many models default to generating code without calling the tool.
From there, a PM demoing data analysis, an AI engineer building an autonomous pipeline, or a freelancer automating a tedious transformation task can all hand the agent a messy CSV and watch it figure out the cleanup logic on its own.
Key Takeaways
- The useful pattern is a write-run-observe loop, not one-shot code generation - the agent reads its own execution output and adjusts
- Docker's
--rm,--memory,--cpus, and--network=noneflags are the minimum viable sandbox; skip any one of them and you've opened a real risk - Registering the executor as a named tool function (not a system prompt trick) gives the model reliable, structured access to the capability
What's the gnarliest real-world task you'd trust a sandboxed code agent to handle without human review in the loop?
Sources referenced: Towards Data Science - Build an LLM Agent That Can Write and Run Code
Top comments (0)