Skip to main content

Chapter 05

One Prompt, Many Specialists

Polymorphic Delegation in Agent Systems

9 min read

Polymorphic Delegation in Agent Systems


We didn't know we had competition.

It was the summer of 2010, just a few months after Apple released the first iPad. The touch-screen computer was completely game-changing. I was one of six developers who had never met before that came together on an empty floor in Boston. We had a single UI design of the main page, one network jack, and no company equipment. The enterprise, a Fortune 500 financial company, didn't have a process to buy Macs. We had to use the corporate card of a VP to procure equipment. Testing was even more challenging. We had to use MiFis to get external access, and if it rained, all bets were off. Learning Objective C while simultaneously building a secure stock trading application was the easy part. Finally, exhausted from sleepless nights, we launched the first iPad trading app for a Fortune 500 financial institution. We shipped the working application in under 6 months.

Later, we found out we'd beaten five other internal teams. Teams that knew the trading domain and had years of institutional knowledge. We won because of grit and the incredibly lucky collection of amazing people.

Leadership had a new problem. They needed an Android application. They weighed the choice. Hire a bunch of new Android experts, or use the new iOS experts and train them in a new language?

The answer was to use the experienced iOS developers and add 2 Android experts to the team. We had mobile UI experts, REST API specialists (developers focused on the server communication layer), and Android experts. We divided the work among us, but assigned tasks to the best suited specialist. What happened next showed me something I wouldn't have the vocabulary for until years later.

We shipped the Android app in half the time.

We implemented the same UI and trading features, but on a different platform with a different implementation. The Java specialists didn't teach us Java. We taught them trading. The specialization worked because we understood what was actually being varied and what needed to stay constant.

I didn't have the vocabulary for it then, but I was watching polymorphism in action.

One Interface, Many Implementations

Polymorphism is the fourth and final pillar of object-oriented programming. The formal definition is "the provision of one interface to entities of different types." The word itself comes from Greek: "poly" meaning many, "morph" meaning form. Many forms, one interface.

Consider the classic example. You have a Shape class with a draw() method. Circle, Square, and Triangle all inherit from Shape. Each implements draw() differently, but the calling code doesn't need to know which shape it's working with. It just calls draw() and the right thing happens.

The calling code is decoupled from the implementation details.

Now consider how natural language works with AI agents.

Suppose you tell your engineering team lead agent to "Review this code."

The team lead will orchestrate passing that prompt on to the subagents of their team. In turn, that single prompt will mean different things to each of the different subagent specialists. A security agent scans for OWASP Top 10 vulnerabilities (the most critical web application security risks): injection flaws, broken access control, security misconfigurations. A performance agent looks for memory leaks and algorithmic inefficiency (how efficiently code scales with more data). A testing agent evaluates coverage and edge cases. Same prompt. Different implementations. The right thing happens based on which specialist receives the request.

Natural language behaves polymorphically in agent systems.

This brings us to the concept of agent specialization. I define agent specialization as designing agents around specific capabilities so that identical prompts produce appropriately different outputs based on which specialist receives them.

One Interface, Many Specialists: Polymorphic Dispatch

Think back to our trading app team. "Trade stocks, pay bills, deposit checks." Those were the requirements. iOS and Android were just different ways of implementing them. The interface was the user experience. The implementations varied by platform. Polymorphism at work.

The Swiss Army Agent Anti-Pattern

Before exploring how to build specialists, we need to address why you should build them at all.

Swiss Army Agent vs Specialized Agents

The temptation with AI agents is to create what I call the Swiss Army Agent. One agent that does everything. One massive system prompt that has all your security rules, your git rules, your formatting issues, your naming conventions, performance minimums, and test coverage minimum, documentation guidelines, and so on.

This happened to me when I wrote an all-encompassing prompt to research SDLC, developer best practices, and then use that research to build me a frontend developer agent. I got a massive and super detailed subagent, but when I used it, it never did what it was supposed to. Just like I talked about in Chapter 2, the agent's context was so large, it "forgets" what it's supposed to do in the moment.

This is the Swiss Army Agent trap.

A God Object in traditional programming is a class that accumulates too many responsibilities, violating the principle that each class should have a single job, until it becomes unmaintainable. The Swiss Army Agent fails for the same reason God Objects fail. No single configuration optimizes for everything. When you tell an agent to be comprehensive about security AND focus on performance AND write extensive tests AND keep responses concise, you've created conflicting optimization pressures. The agent compromises on all of them, excelling at none.

Imagine if we'd had one team trying to build a cross-platform app from day one. One codebase. One set of UI components. One approach to everything. The result would have been mediocre on both platforms. I've seen this with mobile cross-platform frameworks that promise "write once, run anywhere" and deliver "write once, debug everywhere." In reality, you create two crappy applications that were full of security holes because you need to wait for the framework to update after each operating system update.

Specialization enables excellence. The iOS team went deep on iOS patterns. The Android specialists went deep on Android patterns. Both teams understood trading. The domain expertise transferred. The platform expertise specialized.

The same principle applies to agents. A security agent that deeply understands the OWASP Top 10 will catch vulnerabilities that a general-purpose agent glosses over. A performance agent focused on algorithmic complexity will identify bottlenecks that a security agent wouldn't flag. Different specialists catch different issues because they're optimized for different concerns.

This creates a framework for thinking about agent types.

Three Types of Agent Specialists

Domain Specialists understand specific business areas. Trading, healthcare, logistics. They know the vocabulary, the regulations, the edge cases.

Task Specialists excel at specific operations. Code review, test generation, documentation, refactoring. They know the patterns and anti-patterns of their task.

Skill Specialists bring specific technical capabilities. Security analysis, performance optimization, accessibility auditing. They know what to look for.

The goal isn't maximum specialization. It's appropriate specialization. Enough to excel, not so much that you can't maintain them.

When to Create a New Specialist

"When should I create a new specialist agent?"

This is the practical question everyone asks. From my experience, the decision comes down to four factors.

First, ask whether distinct expertise is required. Does this task require knowledge that conflicts with or distracts from other tasks? Security expertise is distinct from performance expertise. They look at different things, flag different concerns, and optimize for different outcomes. That's a candidate for specialization.

Second, consider whether different context is needed. Does this specialist need access to information that would clutter other agents? A security agent might need access to CVE databases (catalogs of known software vulnerabilities) and vulnerability scanners. A coding agent doesn't need that context taking up its limited attention window.

Third, evaluate conflicting optimization goals. Can you optimize for this task without jeopardizing others? "Be thorough" and "be to the point" create tension. A documentation agent should be thorough. A commit message agent must be brief. Splitting them eliminates the tension.

Fourth, assess frequency of use. Is this task common enough to justify the overhead of maintaining a specialist? A task you perform once a month might not warrant a dedicated agent. A task you perform fifty times a day definitely does.

When to Create a New Specialist

There's a practical threshold that signals when you need a specialist. If you find yourself repeatedly prefixing prompts with "Act as a security expert" or "Focus only on performance," you're manually dispatching to a specialist that doesn't exist yet. Create the specialist. Let the routing be explicit rather than included in every prompt.

But avoid the opposite extreme. Over-specialization creates its own maintenance burden. You don't need separate agents for JavaScript and TypeScript. You don't need different specialists for unit tests and integration tests. Look for natural boundaries where specialized skills genuinely diverge.

The trading app team illustrates this balance. We didn't have separate specialists for every feature. We had iOS specialists, Android specialists, and domain experts. The iOS people could still discuss architecture with the Android team. The Java specialists could still participate in trading workflow design. Specialization was focused, not fragmenting.

The domain expertise was shared. The platform expertise was specialized. We succeeded because the Java developers brought deep platform knowledge to problems we defined, not because they learned to become trading experts themselves. That's the right balance.

Matching Tasks to Specialists

Once you have specialists, you need routing. How does work get to the right agent?

There are three approaches, each with trade-offs.

Routing Approaches for Agent Dispatch

Manual routing is the simplest. The developer explicitly chooses which specialist to invoke. "Send this to the security agent." Clear, predictable, but requires the developer to know which specialist handles what. This works well for small teams with fewer than five specialists.

Rule-based routing uses patterns to dispatch automatically. Files ending in .test.js go to the testing agent. Pull requests modifying authentication code go to the security agent. Changes to API contracts go to the documentation agent. This scales better but requires maintaining the rules and makes sense when you have five to fifteen specialists with identifiable file or path patterns. For teams just getting started, manual routing delivers value within days and lets you learn which specialists you actually need before investing in automation.

Context-aware routing uses an orchestrator agent to analyze the request and dispatch to appropriate specialists. This is the most sophisticated approach, essentially adding an AI layer to handle the dispatch decision. It becomes worth the complexity when you exceed fifteen specialists and the routing logic itself requires judgment. We'll explore orchestration patterns in depth in Chapter 8 and revisit the design pattern foundations in Chapter 15.

Context-aware routing introduces its own security considerations. The orchestrator becomes a potential target for prompt manipulation, a risk we'll address alongside the pattern itself. Until then, treat the orchestrator as a decision log. Every dispatch should be auditable. The orchestrator itself should have minimal permissions. For instance, it should not have write access to production systems or the ability to approve its own recommendations.

Think of it like our trading app project. Leadership made the initial dispatch decision. "iOS team handles iPads. Android team handles tablets." That was rule-based. But within teams, routing was contextual. The trading workflow expert handled trading questions regardless of who asked. The UI specialist handled interface questions. The team self-organized around expertise.

Routing is where polymorphism becomes operational. It's also where Part I comes together.

In OOP terms, this maps to patterns where something examines the request and delegates to the right handler, rather than hardcoding which specialist does what. The calling code doesn't need to know all the specialists. It just needs to know how to submit requests.

The orchestrator role becomes important as your specialist count grows. Without coordination, you get fragmented outputs and conflicting recommendations. When specialists disagree, and they will, the orchestrator needs a conflict resolution strategy. We'll tackle that in Chapter 8. With good orchestration, specialists amplify each other. Security findings shape coding changes. Performance insights shape architectural decisions. Testing outcomes confirm the whole system.

Routing is where all four pillars converge. Encapsulation keeps each specialist's context clean. Abstraction gives each specialist the right tools. Inheritance provides the shared configuration they all start from. And polymorphism makes the whole system work through a single interface.

From Principles to Practice

With Context Isolation, Agent Tools & Capabilities, Context Inheritance, and Agent Specialization now covered, Part I is complete.

Four Pillars Overview

These aren't academic abstractions. They're practical patterns extracted from decades of software engineering experience, applied to AI-augmented development. Master the principles, and the implementations follow, regardless of which platform you're using. Claude Code, Cursor, Windsurf, or whatever comes next.

Part II shifts from "what" and "why" to "how."

Before you open Chapter 6, take 10 minutes for this exercise: list every agent prompt or configuration in your current workflow. Circle the ones that try to do more than one job. Those are your Swiss Army Agents. For each one, write down two specialists that should replace it. If you can't define clear boundaries between them, they shouldn't be split. Then pick one Swiss Army Agent and create two separate prompt files this week. Test them on your next code review and compare the results to what the single agent produced.

We built iOS first, then Android in half the time. The patterns transferred because we understood the domain, not just the syntax. The same is true for agents. Master the principles, and the implementations follow. Chapter 6 begins Part II with the Agent Development Lifecycle. The foundation is set. Now we build.

Like what you read? Get the next chapter in your inbox.