Most agencies hit the same wall somewhere past the tenth client. What was easy to hold in your head with three accounts turns into a full-time job of remembering which setting belongs to whom.
Automation moves the wall, and brings a new question with it. Does every client get their own agent, with its own instructions and its own copy of every tool?
Or does one agent serve all of them and work out for itself whose data it is touching?
We spent longer than we should have treating that as the question. It is the wrong one.
The useful split is not how many agents you run. It is what they share. You share the code. You never share the state.
This post covers how that line gets drawn in practice, the step everyone skips, and what the approach costs.
One toolchain, one configuration per client
Our shared directory holds the tools: the connector for each platform we touch, the reply digest, the reporting, the lifecycle commands that onboard or archive a client. Every client's automation runs the same code.
What differs is configuration. Each client has its own folder, its own config file, its own credentials, its own Slack channel. The shared scripts walk that set and act on each one in turn.
The reply digest is the clearest example. We built it for one client, it worked, and it became the thing every new client gets rather than a bespoke build each time.
Adding a client after that is writing a config file. It is not a rebuild, and that is the whole argument for sharing the code.
Resolving who you are acting for is step zero
The failure that actually bites is not a clumsy reply. It is doing the right thing to the wrong account.
This is easier than it sounds, because the name a person uses and the name on disk are frequently different. Two of our client folders are named nothing like the brands they belong to.
So the first command in any client task resolves the name into exactly one account and prints what is wired to it. Guessing costs a step when you are right and a great deal when you are wrong.
The same class of error shows up without agents anywhere near it. We have opened a CRM and found a US manufacturing software company filed as a UK health and wellness brand.
Stale enrichment was never corrected, and nothing was checking which record matched which reality.
An agent with broad access and no identity check makes that mistake faster and more often.
Credentials belong to the client, not to the shared store
A single shared environment file is the most convenient thing in the world and the fastest way to dissolve the boundary you just drew.
Each client's keys live in that client's own bundle. Only genuinely cross-account credentials, the ones that are ours rather than theirs, go in the shared store.
The practical test is offboarding. When a client leaves, everything of theirs should be in one place you can hand over or archive in a single move.
Our own tooling will print the filename of a secret and never its value, which sounds pedantic until you remember that the thing reading the output is often a model.
This is the unglamorous half of automation engineering, and it decides whether any of it is safe to run unattended.
The blast radius is the machine, not the agent
One host running every client's jobs has a failure mode that no amount of prompt design addresses. A command written as a pattern rather than a target does not respect the boundaries in the filing system.
Stopping processes by matching a name, editing configs with a wildcard, cleaning up by glob: each of those reaches past the client you meant and into the ones sharing the machine.
So operations target one process, one path, one account, explicitly. It is slower to type and it is the rule we are strictest about.
What it costs
Sharing the code is not free, and pretending otherwise would be dishonest.
Per-client quirks take more work, because the code has to read context instead of assuming one fixed setup. Access boundaries have to exist before the first client is onboarded rather than after something leaks.
Debugging is harder too, since one codebase now touches every account and a bug is never isolated to the client who reported it.
We take that trade because the alternative grows with the number of configurations instead of the number of clients, and that is the difference between onboarding in an afternoon and onboarding by rebuilding.
The Questions We Get Asked
Should every client get their own AI agent?
Not their own agent. Their own configuration and their own credentials, running shared code.
A separate agent per client means every prompt change, permission change and tool connection gets replicated by hand, and the copies drift.
What is the real risk with one agent serving many accounts?
Acting on the wrong account, not sounding wrong. Context from one client surfacing in work meant for another is the failure that costs you a relationship.
That is an identity and permissions problem, and no amount of model quality fixes it.
Does sharing the code slow down work for individual clients?
Somewhat, yes. Handling per-client quirks takes more logic than hardcoding one setup, and the boundaries have to be built up front.
The trade pays off at the point where onboarding a new client is writing a config file rather than starting again.
