PlimsollCodeTool gives a CrewAIagent one tool, plimsoll_run_code, that runs the model's Python or JavaScript in a fresh plimsoll sandbox and tells the model whether the code ran, failed, or was refused before it could run.
CrewAI: an open-source Python framework that runs a crew of agents, each with a role, a goal and its tools. CrewAI (EXTERNAL · official docs ↗)
The Professor (a fictional narrator)
The agents interviewed one another and were unanimously impressed. Their code still runs in a sandbox: committees are bad enough without root access.
Real quote
Geoffrey Hinton: “I had a principle when selecting graduate students: 'If they're not smarter than me, what's the point?' And I've had quite a number of graduate students who were smarter than me.”
Replay a recorded scenario. The diagram lights each hop the call passes; a refused call stops where it is refused.
These buttons send no execution requests. Each answer's source states how it was recorded, including any fixture used.
Exception panels show what reached the application, rather than an invented code result.
The model asks for
The tool answers the model
The Professor (a fictional narrator)
Each step of the call
The model: The language model decides to run code and writes the arguments: the code, its language and any input files.
CrewAI: CrewAI validates the model's arguments against the tool's argument schema (the language list included) and calls the tool; a call that does not fit stops here.
PlimsollCodeTool: Checks the arguments, hands them to the executor, and turns whatever comes back into the JSON the model reads: ran true, false or "unknown".
CodeExecutor: Asks the daemon what it is, refuses if its isolation tier is below the floor or it lacks the language, then sends the code and files as one fresh project with a fixed command.
plimsolld: Checks the floor again against its current evidence, admits the run if it has capacity, and states a run record of exactly what it ran and answered.
Fresh sandbox: A new locked-down container with no network: the files are written, the code runs once, and the container is removed.
How thick should the walls be?
The executor carries a floor; the daemon states its
isolation tier. This picker is a teaching simulation:
change either to see whether the tier meets the floor. It sends no request and does not check other capabilities.
The Professor (a fictional narrator)
The executor's floor defaults to kernel: docker under runc is the container tier and refuses every call until it runs gVisor, or the executor is built with an explicit container floor, which is for development on your own code only. Use the spelling shown in this page's wiring example.
Surprises and limits
CrewAI has no code interpreter of its own any moreSince April 2026 an agent's allow_code_execution only prints a deprecation warning that points to hosted sandboxes (checked in CrewAI 1.15.23). This tool is how a crew runs code on infrastructure you choose. A crew that turns on CrewAI's tool cache (Crew(cache=True); off by default) looks a call up by tool name and arguments before calling the tool, whatever the tool says about caching, so another tool of the same name could answer for it with nothing run. The tool closes that: building one makes every read of CrewAI's cache miss for its name, so CrewAI always calls it. A cache handler of your own that overrides read is not covered; turn caching off for that crew.
The default floor refuses plain DockerCodeExecutor's floor is kernel. A daemon on docker under runc is the container tier and refuses every call until it runs gVisor, or until the executor is built with minimum_isolation="container", which is for development on your own code only.
Nothing persists between callsEvery call is a fresh sandbox: no variable, import or file from an earlier call is there. The tool's description says so, so the model writes each call complete.
Only the libraries built into the imageThe sandbox has no network and installs nothing. Bake what models may import into the daemon's project image (plimsoll/sandbox-python carries NumPy and SciPy).
Cancelling arun cancels the callThe tool's arun runs the call in a worker thread with a cancel handle, which cancelling the await cancels too. Cancelled before the run request is sent (while the daemon is still answering Describe, say), the call never sends it. Cancelled while the run is in flight, its connection is cut and the thread ends at once rather than at the executor's timeout. The code may have run by then; the daemon stops it only if its provider honors the closed connection.