LLM Application Design As Fluid Mechanics
Building an effective application using LLMs can be challenging. The technology is still quite new, and owing to the intrinsic statistical nature of the principles it operates on, they can be unstable. The same flexibility that allows an LLM to generate infinite unique responses and display unprecedented flexibility is the same thing that can cause it to hallucinate or behave undesirably. One thing developers have learned is that you can’t just plop down an LLM, give it a system prompt, and expect good performance. Instead, a system of constraints must be built around the model to channel it down desirable paths and eliminate excess degrees of freedom. A good analogy is fluid engineering.
When an engineer builds irrigation channels, they are effectively controlling the flow of water by shaping the environment surrounding it. Water will flow anywhere it is not explicitly contained, so engineers exploit this property and laws such as gravity to make it do useful work. In the same way, LLMs operate by a principle of flows, rather than discrete structured operations. You don’t get results by micromanaging each water molecule to get it to go where you want; you can’t do that. Instead you exploit global tendencies to get it to flow where you want by deciding where it can’t go.
For these same reasons, it’s helpful to think of tool calls and other programmatic plugins as constraints on LLM behavior, not necessarily just as capability enhancements. It’s true that tools and MCP servers empower LLMs to interact with new systems, but their utility also stems from limiting what the model can do to those options as well. Hence why it is useful to think of an AI application—the thing you build around the model—as a system of constraints. If the application was just an amplifier, you’d get runaway, uncontained behavior from the model and unpredictable outcomes. You want to implement dampeners, to channel it down intentional paths to minimize the odds of it misbehaving while maximizing steerable, functional behavior. The goal is to create reliable programmatic checkpoints that the LLM inevitably has to pass through regardless of what path it takes on its own.
In essence you want to spend as much time thinking about what you don’t want the LLM to do as what you want it to do. By packing away the don’ts you funnel it towards the do’s with higher confidence. This kind of negatory thinking is necessary for the unique stochastic species of technology LLMs represent.


