Skip to Content
Platform
How-toServe many customers

Serve many customers

One recipe serves every customer; you choose how far apart each customer’s runtime, credentials, and data sit.

An end user is your customer’s user, named by the user_id your backend passes.

You need: a deployed runtime (here support-agent), a backend that starts tasks (Run tasks from your backend), and owner or admin role.

Choose the split

The customer needsUse
Only its own settings, playbook, or prompt variantOne shared runtime with per-task metadata (steps 1–3)
Its own credentials, connector, judges, experiment, or cost reportA runtime per customer (step 4)
Teammates who must not see each other’s customersRole member, with tasks tagged per customer (sharing). Owners and admins see every project; only a separate organization separates them.

1. Name the end user on every task

Take the ID from your server session. Identity tags group end users by customer.

const runner = await client.runtimes("support-agent").run({ identity: { user_id: user.id, tags: ["customer:acme"] }, });

Memory and connections follow the identity (ownership). Tags apply only when the member is first created, and only tags the agent member holds: an owner or admin tags the agent member first.

2. Pass per-task configuration

Task metadata reaches the agent as INTROSPECTION_TASK_METADATA_JSON.

const handle = await runner.tasks.start({ prompt, metadata: { customer: "acme", playbook: "acme-v3", region: "eu" }, tags: ["customer:acme"], });
SYSTEM.md
Read $INTROSPECTION_TASK_METADATA_JSON first. Follow the playbook in /workspace/files/playbooks/<playbook>.md.

Task tags are access-bearing: any member whose tags intersect them can read and write the task. List a customer’s tasks with runner.tasks.list({ tag: "customer:acme" }).

3. Share customer-wide files

introspection shares create --resource-type file --resource-id <file-id> --tag customer:acme

Every Acme end user may read it; the agent gets it when your backend attaches it by ID (Sharing).

4. Onboard a customer with its own runtime

  1. Add a manifest from the same recipe, here for Acme:

    .introspection/support-acme.yaml
    name: support-acme path: apps/support-agent
  2. Commit and push it to main.

  3. Create the runtime:

    introspection runtimes create --manifest .introspection/support-acme.yaml
  4. Bind the customer’s own credentials and servers:

    introspection bindings credentials create --name CRM_TOKEN --from-env CRM_TOKEN -r support-acme introspection bindings mcp connect --mcp-server-id crm --endpoint-url <crm-url> \ --header 'Authorization=Bearer ${CRM_TOKEN}' -r support-acme

Bindings, judges, metrics, and experiments are per runtime. To ship to one customer first, pin production on the others (Test before production).

Verify

introspection conversations list --filter owner_key=user:<id> -o table introspection members get user:<id>

Expect only that end user’s conversations and one customer member.

Or ask your agent: “Onboard Acme with its own support-agent runtime.”

Limits

Not supportedDo this instead
An experiment for one customer in a shared runtimeA runtime per design partner.
A different connector per task in one runtimePer-user Pipedream connections, or a runtime per customer.
Cost or metrics grouped by tagGroup by user_id and roll up in your database, or a runtime per customer.
Customer admins seeing only their own users’ workYour backend lists conversations list --filter owner_key=user:<id> with an Admin Agent key.
Last updated on