Ten minutes is not a claim about typing speed. It is a claim about a property: that the whole path from signed contract to working agent is a sequence of calls, with no person in the middle choosing something in a console. Once that holds, the elapsed time is however long the calls take. Once it does not, the elapsed time includes that person's queue — and the difference between ten minutes and three days is almost never labour. It is waiting.
This piece explains how AI Agent Builder puts a client on the platform with that property, and why each step has the shape it has. It picks up where why every client should be a tenant of its own leaves off: that piece is about the boundary, this one is about the procedure that creates it.
What the agency needs
"A client signs on Monday. I want their agent answering on their own site by the time I send the welcome email: inside the limits I sold them, on my model provider key without them ever holding it, configured exactly like the last forty — and I want to be able to say afterwards what was done and by whom."
Four requirements hide in that sentence, and they pull in different directions. Repeatable: the fortieth client has to equal the first. Bounded: what the client may consume has to be written before they can consume it. Keyless: the client operates an agent, not your credentials. Traceable: when something is wrong, someone has to be able to say what was done. The sections below take them in the order the path runs.
Everything is a call, including the console
Every operation the admin console performs — creating a tenant, importing an agent, writing limits, inviting a person — is also an operation of the platform's protected API, and the same set is exposed as tools to any MCP client. The console is one client of that API, not a privileged path around it. Everything below depends on this: a step that existed only as a screen would be the step where the clock stops.
Callers authenticate with keys, and a key issued for a tenant is bound to it and to one role: it cannot reach another tenant's data.
The diagram is the shape of the argument, not a measurement: the same eight steps, the same amount of work in each, and the only thing that differs is how many of them wait for a person.
The boundary comes first
One call creates the client's tenant under the agency's: a name, a slug, a language and the parent it hangs from. The platform keeps each tenant's position as a path from the root, and that is what makes everything below cheap — "which ancestors does this client have" is a string split, not a recursive query.
The parent is the one decision in the sequence that is awkward to undo, because everything the client inherits comes from it. A tenant can be moved afterwards and its path is recomputed, but it changes what the client inherits from that moment on. It is the single place worth a validation step in your script.
Two things are deliberately not part of that first call: limits, and connection inheritance. A new tenant starts with no limits of its own and with inheritance switched off. Both are written explicitly in the next steps, which is why the order matters.
Limits are values, resolved nearest-first
Three families of control are written onto the tenant as values:
| Family | Examples | At the edge |
|---|---|---|
| Resource | agents, users, child tenants, hierarchy depth, storage | Creation is refused, with an error that names the resource and the count |
| Consumption | messages per month, spend per cycle | A new conversation is refused; one already running is not cut off |
| Feature gates | channels, integrations, the workflow editor, code nodes | The capability is refused for that tenant |
A tenant uses its own set of values if it has one. Otherwise it uses the nearest ancestor's. Otherwise it gets the platform default, which is unlimited. The set is taken as a whole — there is no field-by-field merge. So an operator who writes a ceiling once at the agency covers every client underneath that has none of its own; and a client given a set of its own stops following the agency's for every field, not only the ones that changed.
Enforcement never reads the plan. Assigning a plan writes the plan's values onto the tenant — limits, flags, rate limits, billing mode — and from then on the runtime reads only those values. Plans are commercial; limits are functional. That decoupling is what turns a temporary exception for one client into a write on that client, instead of a new plan invented for it.
Consumption is checked once, before a conversation starts, against a counter that resets on the first of the calendar month in UTC. A conversation already in flight finishes. Unlimited stays the default on purpose: a limits system whose failure mode is blocking existing tenants gets switched off within a quarter.
Connections are resolved, never copied
The client's agents do not receive a copy of the agency's provider key. At run time the platform looks for the tenant's own active connections. If it has at least one, those win outright. If it has none and inheritance is switched on, it takes the nearest ancestor that has any. If inheritance is off and it has none, the run fails with an explicit error rather than guessing. The model defaults travel with the connections: a client with none of its own reads those of the tenant that supplied them.
Because nothing is copied, two things follow. Rotating a key is one write at the parent. And the credential never exists as a row in the client's tenant, so there is nothing for the client's administrators to read. They operate their agent; they do not hold your key.
The agent comes from an artifact
An agent is exported as one document: its workflow — guardrail steps included, because they are nodes of that workflow — its schedule, and its static data. Importing that document into the client's tenant is a single operation, and it is built to be repeatable:
- It never creates what it only references. Provider connections, tool connections and API sources are resolved by name inside the client's tenant, and a name it cannot find comes back as a warning, not as a silently created empty one.
- The definition is overwritten, not appended. Importing the same artifact twice leaves the same agent; the stored version always matches the document.
- Policy travels with the agent. Because the guardrail configuration is part of the definition, it is not something somebody configures per client afterwards — well for the clients they were watching, badly for the rest. The manipulation surface should not vary with how busy you were that week.
The import returns its warnings and a health read of the new agent, which is what a script should assert on.
Who may talk to the agent
Web traffic is governed per tenant by an origin policy. A new tenant allows every origin; switching it to an allow-list restricts the widget to the listed origins, matched exactly, and a request from any other is rejected with a named error. Requests that carry no origin at all — server to server — are not subject to it.
So the default is an open door, and the allow-list is the step that closes it. Script it, and script the check that a listed origin works and an unlisted one does not.
People, without a password
Inviting the client's administrator creates the identity without a permanent password, issues a single-use token valid for 72 hours, assigns the person to the client's tenant with a role — owner, admin or viewer — and sends the email. A resend invalidates the previous token, with a one-minute cooldown, and a pending invitation can be revoked. At no point does the onboarding know, transmit or store the client's credential, so there is no secret sitting in a provisioning log.
Proving it works before the client sees it
This is the step a pipeline has to supply, because the platform does not gate on it: importing an agent leaves it active immediately. What the platform gives you is a real channel to test through — the same one the client's users will use. Send a real message, assert on the reply, and only then send the invitation. The invitation is the step that makes the client aware of the work, so it goes last.
Without that step the pipeline has confirmed that its calls returned success, which is not the same as a working agent. With it, the failure lands on you before the client has been told anything.
Who did what, and undoing it
Every change to the control plane — a tenant, an agent, a connection, a key — is recorded with the actor (a person, an API key or the platform itself), the action, the resource, and the values before and after, in a log where each row is chained to the one before it. It records changes, not what agents did at run time; that lives in the run records. Writing it never blocks the operation it is watching: a failure to record is logged loudly instead.
Teardown is one operation too. Deleting a tenant removes its whole subtree, children first — agents, connections, knowledge bases, sessions, runs, billing, channel settings, invitations, branding — and returns a count per kind. It cannot be undone, which is exactly why it is worth running on a throwaway tenant first: an onboarding that has never been torn down has never really been run twice.
Where it stops
- A client's own credentials stay on the client's clock. A messaging account the client has to request is waiting that no script removes. It can be moved to the front and made a precondition, which is the most the procedure can do.
- Every limit and flag check fails open. If the platform cannot read a limit or a flag, it lets the request through rather than blocking a client because of its own fault.
- Only the hard consumption caps bite. The soft thresholds that sit beside them are stored, and nothing acts on them at run time today.
- Limits are taken as a whole set, and they are not a ceiling a client cannot exceed. Whoever can write a client's own set replaces the agency's.
- Connection inheritance is all or nothing per tenant. One connection of its own and the client no longer inherits any; the two are never mixed.
- The import looks for the connection names in the artifact inside the client's own tenant. A client that inherits is told it is missing a connection it will in fact use through inheritance. Read those warnings knowing that.
- The origin policy is open until someone closes it, and invitations need an identity provider that supports them; otherwise the call fails explicitly.
Eight checks for any onboarding
Whatever puts your clients live — this procedure or another — these are the properties worth scoring, one point each and without partial credit, because partial credit is what hides the problem.
- Can you provision a complete client without opening a UI? Not "mostly": at all.
- Is the agent's configuration a versioned artifact in source control, or does it live only in the platform?
- Does the new client inherit your provider credentials, or receive a copy? A copied key is a key to rotate in forty places and one the client's team can read.
- Are limits written as values, so an exception does not need an invented tier?
- Is there an automated test between provisioning and the invitation? Forty calls returning success is not a working agent.
- Can you tear a client down completely, in one operation? Untested teardown means untested onboarding.
- Does the audit log record which identity performed each step?
- Could someone who joined last week run it end to end from the documentation?
Six or better and your constraint is genuinely the client's paperwork. Below four, ten minutes is not a tooling problem: the process still has people standing in it, and each of them is a queue.
RFC 7644 made this argument for user accounts in 2015 — provisioning is machine-to-machine work — and the industry agreed. The same argument for tenants is not harder. It is only newer, and still mostly made in consoles.