Designing Agentic AI Systems, Part 2: Modularity

In Part 1 of this series, we introduced the overall architectural patterns of agentic systems. We talked about the three logical layers of an agentic system: tools, action, and reasoning. We also looked at mechanisms such as function calling which allow LLMs to interact with the outside world via the action layer.
We also suggested that as agents grow in complexity, the quality and reliability of the agentic processing often suffers. Therefore, we need need to design our agentic systems in a way to combat this. One of the key design principles we can adopt to help with his is modularity, which we will cover here.
Modularity
One of the best ways to achieve consistent performance of a complex agentic system is to decomposing the problem space into smaller sub-agents.
This is achieved through a parent/children relationship between agents. The top level parent agent serves as an entry point into the agentic processing. Most of the functions offered to the reasoning layer are handoffs that dispatch processing to one of the child agents.

Each of these child agents handles a specific part of the problem space. In effect, this applies the concept of bounded context, which is commonly used in microservices architectures, to the world of AI agents.
Benefits of Modularity
Imagine you were building a customer support agent for an online retailer. That agent would handle things like returns, order status, product questions and many others.
If you started with a monolithic architecture, you would soon find that your prompts to the reasoning layer would become long and complex. The list of functions would become long. As both those things occur, the accuracy and performance of your agentic system would suffer.

Adopting a more modular approach simplifies numerous aspects of the overall architecture. One way to separate the concerns of the overall system might be to organize the subagents by functional area. The result would look something like this:

More Predictable Decision Flows
By decomposing the system into specialized sub-agents, each agent takes on a well-defined set of responsibilities. As the parent agent orchestrates the workflow, it becomes much easier to see what is happening and why. Rather than trying to juggle multiple tasks in one massive flow, the request can be handed off to the specific agent best suited to handle it.
This leads to more transparent interactions, clearer data paths, and a logical, step-by-step progression of tasks. In a monolithic approach, the lines of responsibility blur, which makes it difficult to pinpoint where something might have gone wrong. A modular design eliminates that confusion by establishing distinct boundaries for each agent’s domain.
Separation of Concerns
Modularization allows each agent to focus on a specific facet of the system. If you have a ReturnsAgent that only processes returns and an OrdersAgent solely responsible for orders, you avoid muddying the waters with extraneous data or tangential questions. This separation keeps domain knowledge highly concentrated within each agent, which can greatly enhance accuracy—no more random tangents pulling in unrelated information.

In practice, this approach mirrors techniques used in microservices and domain-driven design, where each component has a “bounded context.” By restricting the scope of each child agent, you reduce the volume of instructions and dependencies, making every interaction more precise. As a result, both the child agents and the parent agent benefit from greater clarity, simpler prompts, and fewer off-topic responses.
Reduced Complexity
When a system has to handle multiple tasks or handle large amounts of data, complexity can balloon quickly. By distributing responsibility across several sub-agents, you shrink the size of each individual agent’s problem space. This decentralization makes it easier for each agent to reason effectively about its own tasks without being overwhelmed by unrelated concerns.
Reduced complexity also means fewer chances for procedural or logical errors. Because each sub-agent is independent, changes in one domain don’t accidentally cascade into another.
Improved Maintainability & Testing
Maintaining a large, monolithic system can be a nightmare. With a modular architecture, you can improve or replace one sub-agent without worrying about toppling the entire system. This not only cuts down on development time but also reduces the risk of introducing new bugs in areas unrelated to the changes. If your OrdersAgent requires a new feature, you can confidently implement it there, assured that you are not breaking your ReturnsAgent or other parts of the system.
What’s Next
While modularity offers advantages to reduce complexity and improve the maintainability of your agentic system, it also introduces key interaction patterns that you must consider.

Agents need a way to dispatch requests to sub-agents and to callback to the parent agent to ultimately deliver the end result of the agentic processing.
In Part 3, we’ll dig deeper into these interactions and look at a sample interface for what this would look like using Python.