Coding agents are fast. The problem is that fast code generation creates a new bottleneck: understanding what the agent actually built.
Keivan Esbati hit this wall while building ML applications with coding agents. His review habit stayed constant while the codebase grew. Eventually he was reading hundreds of lines of diffs per session, and the code was becoming meaningless without understanding what the application was actually computing.
The fix was not a better diff tool. It was a different unit of review entirely.
The Code Review Trap
Early on, reviewing the diff after each agent session is manageable. The codebase is small, the changes are contained, and you can still hold the whole thing in your head.
Then the application grows. A single feature in an ML app might touch preprocessing, model inference, postprocessing, and application logic. The agent adds several hundred lines in one session. At some point, reading the code stops being the same thing as understanding the application.
Esbati describes the problem precisely: he was spending most of his time reviewing the agent’s implementation rather than the application output. He was trying to control the means instead of the result.

️ The Framework Shift: Explicit, Inspectable Pipelines
Without code review, the application collapses into a black box:
Input → [ ? ? ? ? ? ] → OutputThe fix was to ask the agent to compose the application as a set of explicit, named steps rather than arbitrary functions and modules:
Pipeline([
Preprocess(...),
Inference(...),
Postprocess(...),
ApplicationLogic(...),
])The agent still writes the implementation behind each step. The code is still there. But the developer no longer needs to read the entire codebase to understand what the computation is doing.
With named pipeline steps, intermediate data becomes visible:
Input → Preprocess → Inference → Postprocess → Application Logic → Output
│ │ │ │ │
▼ ▼ ▼ ▼ ▼
data input result result stateWhen something goes wrong, the useful question shifts from what did the agent change? to at which step did the result stop looking right? That narrows the problem immediately.
Why This Works for ML Specifically
ML applications are fundamentally computations over data with state management layered on top. But the standard toolkit for understanding them, source code, logs, and final outputs, leaves a large gap in the middle.
The final output tells you what you got. The source code tells you how it was implemented. The intermediate results tell you what actually happened along the way. For ML correctness, the intermediate results often matter more than either of the other two.
This framework makes those intermediate results a first-class object in the development workflow rather than something you reconstruct after the fact by reading the code.

How It Changes the Agent Workflow
Structuring applications as inspectable pipelines changes what you ask the agent to do. Instead of asking it to produce code that seems plausible, you ask it to structure code so that the computation is observable at each boundary.
This creates a shared structure between developer and agent. The agent handles implementation details within each step. The developer reasons at the level of steps. When a problem surfaces, the developer can point the agent to the specific failing step instead of asking it to debug the entire application from scratch.
Code review does not disappear. Performance, concurrency, resource management, and security still require reading implementation. But it moves to second in the review order, not first. Results first, code second.
When This Works
- ML applications where intermediate data transformations drive correctness more than code structure does
- Any AI-assisted development workflow where agent sessions produce large diffs
- Projects where debugging time is dominated by figuring out where something broke rather than why
When It Does Not
- Applications where the computation is trivial and a single input-output check is sufficient
- Domains like security and concurrency where implementation details are the risk, not data flow
- Very early prototypes where structure introduces more overhead than value
The Open Source Implementation
Esbati built a small framework around this idea called ml-pipes, available on GitHub under trained-by-humans/ml-pipes. The goal is to compose applications as pipelines you can run, inspect, trace, and benchmark.
The examples in the repository show the pipeline structure, data flowing through each step, and how to inspect the computation in practice. If you are building ML applications with coding agents and spending more time reading diffs than checking outputs, the examples are worth twenty minutes.
As code generation gets faster, the question that matters is not how to review more generated code. It is how to observe what the computation is actually doing.


