When Code Becomes Feedback
For MathModelAgent, the move from a model description to executable code is not a clerical step. It is the point where an abstract proposal meets data, libraries, runtime state, and failure. This chapter follows the CoderAgent’s execution loop and compares its local Jupyter and E2B paths. The practical question is what execution feedback can repair, what artifacts it preserves, and which forms of correctness remain outside the interpreter’s reach.
A one-shot code generator returns text. A tool-using coder has another possible behavior: propose code, run it, inspect what came back, revise the proposal, and run again. That loop is more useful because many coding errors are visible only after execution. It is also more demanding because the system must preserve the right conversation state, control retries, capture outputs, and keep the resulting artifacts available to the later writing stage.
The execution loop has a state, not just a prompt
The CoderAgent receives a subtask prompt and exposes an execute_code tool to the language model. When the model calls that tool, the agent records the assistant message and the tool request, sends the code to an interpreter, and receives text, images, or an error. A successful tool response stays in the conversation so the model can use the output when deciding what to do next. If the model requests another execution, the interpreter session can retain variables and files from the earlier call rather than starting from an empty process.
This persistent state changes the nature of the interaction. A first execution might load a data set or define a helper function. A later execution might alter a parameter, rerun a model, or produce a sensitivity plot using the objects already in memory. The state makes iterative analysis efficient, and it mirrors how a human researcher works in a notebook. It also creates coupling: a later result may depend on variables or files created earlier, so the sequence of cells becomes part of the evidence.
When an execution fails, the CoderAgent does not treat the error as a final answer. It adds the tool response to the conversation, records the error message, creates a reflection prompt, and gives the model another opportunity to correct the code. The system can therefore respond to missing imports, syntax errors, incompatible data shapes, plotting failures, and other errors that appear in the interpreter’s output. The important mechanism is the feedback path: the failure becomes an input to the next attempt rather than disappearing into a log that the model cannot see.
The loop ends when the model stops making tool calls and returns a response, or when configured limits are reached. The absence of a tool call is treated as the model’s signal that the subtask is complete. This is a workable completion rule, but it is not a proof of completeness. A model can stop after producing an incomplete analysis, and a successful execution can still implement a poor formulation. The loop is designed to make runtime failure visible, not to decide whether the mathematical task has been fully solved.
The state diagram highlights two different endings.