TL;DR: Fewer than you think. Usually one. The number of voice agents a business needs is decided by boundaries of ownership, direction and flow shape, not by how many phone numbers, locations or intents it has. Four clinics with different addresses, hours and staff names are four rows in a lookup table, not four agents. Every extra agent multiplies the regression surface, the knowledge maintenance and the number of places a fix can fail to land, so I split only when something genuinely cannot be expressed as data.
A client with four locations asks for four agents. An agency with eleven clients assumes eleven agents. Someone who has read a little about multi-agent systems asks for a booking agent, an FAQ agent and a triage agent that hand off to each other.
All three instincts point the same direction, and it is usually the wrong one. The question is not how many things the agent has to know. It is how many things you are willing to keep in sync at 2am when a client texts to say the agent gave a caller the old opening hours.
I have built agents for hospitals, vet clinics, estate agents and car garages at Fortell AI, and voice and chat agents wired into GoHighLevel for a US product at Tested Media. The pattern that survives contact with production is a small number of agents carrying a lot of data, not a large number of agents each carrying a little.
Every agent you add is a maintenance multiplier
The cost of a second agent is not the hour it takes to clone the first one. Cloning is the cheap part, which is exactly why people do it without thinking.
The cost shows up later, in four places.
Regression surface. A live agent needs a frozen scenario set you re-run before publishing a change, somewhere between twelve and twenty scenarios covering the top intents, every refusal, a messy capture and a transfer. That is a real cost per agent. Six agents means either six sets to run on every prompt change or, in practice, one set run properly and five run never.
Drift. The first time you fix a wording problem across six cloned agents, it lands in six. The third time, it lands in four, because two were mid-edit or someone had already tweaked that line locally. Six months in, nobody can tell you what is different between them without reading all six side by side.
Knowledge maintenance. Staleness, not hallucination, is the real failure mode of a voice agent's knowledge. A stale fact sounds completely correct. Every duplicated copy of a knowledge base is another surface where a fact can go stale independently, and another human on the client side who has to remember it exists.
Provider changes. Model versions move, voices get updated, recognition behaviour shifts. Whatever re-testing you do when a provider changes something under you, you do it once per agent.
None of that argues for never splitting. It argues for making each split earn itself.
What looks like a reason to split but is not
Here is the list I get asked about most, and it is all data.
Different phone numbers. Different addresses, opening hours, holiday closures. Different staff first names. Different booking links, different calendars, different price lists. Different accents in the local caller base. A branch that closes at 4pm on Fridays.
None of that is a different agent. It is a different row.
The mechanic is straightforward on any serious platform: when a call arrives, you get the number that was dialled before the agent says its first line. You look that number up in one table, and you inject what comes back as variables into the prompt at call start. The greeting says the right business name, the hours block holds the right hours, the booking tool receives the right calendar id, and the post-call automation in n8n receives a location id it can route on.
One agent, one flow, one set of refusals, one regression set. The variation lives in a table a non-engineer can edit, which is also the only version of this that survives a client wanting to change Saturday hours at one branch.
The same logic kills the micro-agent idea. A booking agent and an FAQ agent that transfer to each other is not an architecture, it is a latency tax plus a context loss. Within one call, that separation is what flow nodes and reusable components are for. Splitting by intent inside a single conversation buys nothing and costs a handoff the caller can hear.
The boundaries that do justify a separate agent
Four of them, in the order I actually hit them.
A different client. This one is not technical, it is ownership. Two clients should never share a config where one wrong edit reaches the other's callers, and the reporting, access and billing lines have to be clean. This is the boundary VoiceDash exists to sit on: separate agents, separate branded portals, shared engineering underneath. Agencies get this one right by instinct.
A different direction. An outbound agent is not an inbound agent dialling out. The consent posture is inverted, the first eight seconds do completely different work, answering machine detection is a real feature rather than an edge case, and the calling windows and retry rules are compliance rather than tuning. Trying to make one agent do both produces a prompt full of "if this is an outbound call" branches and a flow nobody can reason about. Split it.
A different flow shape. Not different words, different structure: different exits, different tools, different definition of a successful call. A reception agent and a payment-chasing agent are different jobs. The test is whether the handoff and refusal rules differ, because those are the parts that carry risk. If the exits are the same and only the vocabulary changes, it is one agent with better variables.
A different language. A second language is a different voice, different recognition configuration, different number and date phrasing, and a different set of things that sound rude. That is not a variable, it is a rebuild of the speech layer even when the logic underneath is identical.
Vertical is the interesting near-miss. Medical clinics and car garages look like the same product with different words, but the refusal rules for a clinic are load-bearing in a way a garage's are not, and the exits differ. In practice that lands on the flow shape rule, which is why I treat verticals as separate builds rather than separate rows.
If you do split, split from a template
The mistake is not having six agents. It is having six agents whose only relationship is that one was copied from another eight months ago.
Keep the config in git, the way you would for any live change you might need to reverse. Keep one canonical version of anything shared: the refusal wording, the capture and confirmation behaviour, the transfer ladder, the recording disclosure. When an agent differs from the template, that difference should be a diff you can print and read in a minute, not something you reconstruct by listening to calls.
This is the same boundary I kept building a cross-platform SDK at Geonode, where one networking core served Windows, Android and iOS and only genuinely platform-specific behaviour was allowed to fork. Share the logic, never the platform. Voice agents want the same rule: share the behaviour, fork only what the boundary actually forces.
One agent still gives you per-location numbers
The usual objection to consolidation is reporting. If all four branches run through one agent, how does anyone see how the Leeds branch is doing?
Tag the call. The location id you looked up before the greeting is attached to the call, travels through the post-call payload and lands on the record you write. Every number that actually matters, pickup, resolution, bookings against intent, transfer rate, cost per booked appointment, then slices by location without a single extra agent existing.
Reporting is a grouping problem, and grouping is cheap. Do not buy it with configuration you have to maintain forever.
The question to ask before cloning
Before you duplicate an agent, ask what the caller would actually experience differently, and whether that difference can be written down as data.
If the answer is a name, an address, a set of hours, a calendar, a price or a phone number, it is a row in a table. If the answer is a different set of exits, a different consent posture, a different language or a different client's callers, it is a new agent and it deserves its own regression set, its own knowledge owner and its own line in your reporting.
Most businesses that ask me for six agents need one agent and a lookup table. The ones that genuinely need six are usually not asking, because the boundary was obvious to them before they picked up the phone.
I build production AI voice agents and the automation, CRM and telephony layer behind them for founders across the US, UK and Europe. More about my work here, or book a call.