All posts
Cognitive DebtSystem Design

Running agents in parallel

It’s all about how running agents in parallel increases engineering capacity, not engineering judgment. To use them effectively, you must learn to think in systems and move your thought process upstream into architecture and system design.

Gokul JS··6 min read

I’ve been using coding agents for the past few years, and by now it’s fairly common for most of us to use them in our daily work. They have become the new norm. Since last November, there has been a step-function change in what these agents are capable of. But all this improvement has also brought a lot of noise and drawbacks. Some people say, “There’s so much cognitive load that I can’t run more than two agents at a time.” Others say, “I just press Enter.” Some say there is now too much code to review properly. Some argue that you should read every line an agent generates, while others argue that reading the code at all misses the point. The result is that we have much more engineering capacity than before, but very little agreement on how to use that capacity well.

So basically, the problem is that more code is being generated than before, and we are losing sight of what is happening, how the pieces fit together, and how to manage it all. That loss of visibility is what most people are struggling with. The solution to all of this comes back to proper software engineering. Nothing else.

Whiteboarding defense

The effective way to run multiple agents and overcome cognitive load is through effective system design. Before starting a feature or building a product end to end, you need to design the system thoroughly at every layer and deal with all failure cases. You don’t need to know the entire codebase or every implementation detail, but you need to understand the data flow. Why did you choose X instead of Y? What happens if this actor behaves maliciously? What data structure did you use here, and why? Where does this fail? You should be able to answer confidently. Basically, you’re doing system design. You should be in a position to defend your decisions while being well aware of what is happening. Let’s say there is some core work. For example, if you have to add an AI agent to this flow, you need to take it separately and do the system design again. Once you’re done with that, articulate and aggregate it well so that you can run multiple agents. If you want to know how to run agents in parallel, just Google it or watch a YouTube video on how to run parallel agents using Git worktrees.

Doing this solves multiple problems. You now have a better understanding of the system and what is happening inside it. Why is that important? Because your job is not only to ship code. For example, when you are in a meeting with founders or upper management and a customer request comes in, you need to understand the system currently in place well enough to decide what can be shipped quickly and what cannot. These decisions are easier in the early stages, but they become much harder as the system scales. At that point, your input is required to set the direction and bring everything into place. Second, product improvements do not come only from customer requests. They also come from improving the systems you already have. This is especially important when you are building agent systems or RAG pipelines, because failures do not always show up as obvious errors. You need to know how the current system performs at each layer, identify where accuracy is being lost, and work on that specific area.

Once you have worked through the system design on a whiteboard, it becomes easier for someone else to understand what you are building and contribute. Effective communication is not about explaining everything you know. It is about giving someone the information they need to build the right mental model and take it forward. A good whiteboard design does exactly that. It shows the major blocks, how they connect, and what happens at each layer at a high level. Another engineer can understand the system much faster than they could by starting with the code, then decide where they need to go deeper. This is where LLM-generated system designs often fail. Ask a model to design a system or write documentation and it tends to include everything, even when you ask for a high-level explanation. Important decisions get buried under details, and the reader spends more time processing the document than understanding the system. You can see the same problem in many open source pull requests. Instead of clearly explaining what changed, why it changed, and where the reviewer should focus, the description becomes a wall of generated text that creates more work for the reviewer. Good technical communication is not measured by how much information it contains. It is measured by how quickly another person can understand the system and decide where to go deeper.

Reviewing code

Now, when it comes to reading code, some people say you have to read all the code, while others say you should not. At a given point in time, both pieces of advice can be true, but it depends on the person. I believe junior engineers should read an enormous amount of code, no matter what, because that develops patterns for understanding how systems are built. Once you read enough code and understand it, this knowledge compounds at later stages. You quickly know which code to ignore, which code to read, and where failures might occur and stuff.

When agents generate this much code, reading every line with the same amount of attention stops making sense. I don’t follow a blanket rule of reviewing everything or reviewing nothing. I decide based on the risk of each change, how easily I can verify it, and how expensive it would be to reverse.

For routine frontend changes, one-off scripts, internal tooling, and throwaway prototypes, a proper AGENTS.md and focused skills can often be enough. If the result is easy to verify and cheap to discard, I am comfortable letting the agent own most of the implementation. Do not waste your attention re-deriving an understanding you will never need again.

But the rule changes when the code touches a core part of the product or when failure is expensive and difficult to reverse. Think about authentication, payments, and anything touching data integrity. For this kind of work, I treat the agent’s output as a first draft. I read the diff line by line, trace how it affects the rest of the system, and make the agent explain any decision I cannot defend myself before I merge it.

Agents save time by writing code faster. I want to spend that saved time reading deeply where it matters. That is the whole tradeoff.